将 formControlName 传递给 Angular 组件
Posted
技术标签:
【中文标题】将 formControlName 传递给 Angular 组件【英文标题】:Passing formControlName into Angular component 【发布时间】:2019-10-28 01:43:28 【问题描述】:我有一个反应形式。设置与此类似:
myForm: FormGroup;
this.myForm= new FormGroup(
name: new FormControl("", [Validators.required, Validators.maxLength(15), Validators.pattern('...')]),
...
);
我在我的表单上这样使用它:
<input
type="text"
formControlName="name"
/>
<div *ngIf="name.errors?.required">
Name is required
</div>
<div *ngIf="name.errors?.maxlength">
Name must be name.errors.maxlength.requiredLength characters
</div>
<div *ngIf="name.errors?.pattern">
Name has invalid characters.
</div>
这只是我的表格的精简版。我有多个输入,我必须为每个输入创建错误 div。
为了解决这个问题,我尝试创建一个组件。该组件与上面的代码非常相似:
<input
type="text"
[formControlName]="formControlName"
/>
<div *ngIf="name.errors?.required">
Name is required
</div>
etc...
ts 文件:
@Component(
selector: 'app-text',
templateUrl: './text.component.html'
)
export class TextComponent
@Input() formControlName: FormControl;
所以在我的表单上,我想按如下方式使用这个组件:
<app-text [formControlName]="name"></app-text>
但我无法让它与 formControlName 属性一起使用。
这可能吗?
谢谢
我快到了。
我已经创建了这个 StackBlitz,所以请展示我的进度:
Demo
现在只是在努力解决错误以及如何访问 formControl 以检查这些错误
【问题讨论】:
为什么要在 TextComponent 中使用 formControl? 所以我可以使用验证器来显示组件中的错误,从而不会在任何地方重复它们 你能提供stackblitz吗? 您需要为此使用自定义值访问器。如果你想避免使用样板,你可以使用github.com/cloudnc/ngx-sub-form在这里查看类似的帖子***.com/questions/40806779/… @maxime1992,不,如果您不想创建自定义表单控件,则不需要使用值访问器。只要通过控制 【参考方案1】:您需要将表单控件传递给输入元素,
<input
[value]="val"
type="text"
(input)="val=$event.target.value;onChange($event.target.value)"
(blur)="onTouched()"
[formControl]="control"
>
<span *ngIf="control && !control.valid && control.touched">
<span class="error" *ngIf="control.errors['required']"> The field should not be empty</span>
<span class="error" *ngIf="control.errors['email']"> The field should be an email
</span>
</span>
获取自定义组件中的控件作为输入,并据此显示错误。
import Component, OnInit, forwardRef, Input, OnChanges from '@angular/core';
import FormControl, ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS from '@angular/forms';
@Component(
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css'],
providers: [
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TestComponent), multi: true
]
)
export class TestComponent implements ControlValueAccessor, OnChanges
constructor()
propagateChange:any = () => ;
@Input() control: FormControl;
@Input('messageValue') _messageValue = 'whateves';
get messageValue()
return this._messageValue;
set messageValue(val)
console.log('set messageValue', val)
this._messageValue = val;
this.propagateChange(val);
hi(event)
console.log('hi');
console.log(event)
this.messageValue = event;
ngOnInit()
ngOnChanges(changes)
console.log('changes', changes);
this.propagateChange(this.messageValue);
writeValue(value)
console.log('writeValue', value);
if (value)
this.messageValue = value;
registerOnChange(fn)
console.log('onChange')
this.propagateChange = fn;
registerOnTouched()
【讨论】:
您不需要从 DefaultValueAccesor 扩展,也不需要提供 NG_VALUE_ACCESOR。如果你使用[formControl]="control"
并且在父级中你作为输入传递<app-text [control]="myControl.get('name')"></app-text>
是可以的
好的,我几乎可以完成这项工作,但我仍在努力解决错误部分。如何访问 formControl 以检查错误?我尝试了您的解决方案,但没有奏效。看到这个stackblitz.com/edit/…
如果解决方案解决了您的问题,您可以接受这个作为答案。【参考方案2】:
如果您想访问formControl
,最好使用NgControl
作为 DI
推理:
NgModel
FormControlDirective
FormControlName
都是NgControl
的子类,所以如果你这样做,你将为自己提供很大的帮助,这样如果你改变主意使用 formControl 到 NgControl 等......你会已经使用NgControl
覆盖了这些基础
所以举个例子,它看起来像
import Component, OnInit, Self from '@angular/core';
import NgControl from '@angular/forms';
@Component(
selector: 'app-text',
templateUrl: './text-box.component.html',
styleUrls: ['./text-box.component.css']
)
export class TextBoxComponent implements OnInit
constructor(@Self() private ngControl: NgControl)
ngOnInit()
console.log(this.ngControl);
HTML
<app-text[formControl]="control"></app-text>
我们使用@Self 的原因是组件不会在注入器树上进一步查找ngControl
,而只是在它的元素上查找。所以你可以嵌套等......
这对指令也非常有益,但到目前为止我希望这会有所帮助!
【讨论】:
如何在父级中设置formControlName?以上是关于将 formControlName 传递给 Angular 组件的主要内容,如果未能解决你的问题,请参考以下文章
使用 formControlName 和 ngModel 的角度 6 警告
在 Angular 中动态创建控件时不呈现 formControlName
带有 ControlValueAccessor 和 formControlName 的 Angular Material Datepicker [重复]