当您想要实现自定义组件以将数据绑定到单个值时,正确的 Angular 方法是使用父视图指定 [formControl] 或 [formControlName] 的方法。
<app-form-group formControlName="name"></app-form-group>
<app-form-group formControlName="email"></app-form-group>
<app-form-group formControlName="other"></app-form-group>
在您的子控件中,您需要执行以下操作:
首先将以下提供程序添加到您的 @Component 声明中,以便 Angular 知道您的组件可以使用 [formControlName] / [formControl]
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CountrySelectorComponent),
multi: true
}
]
然后您的子组件的类需要实现ControlValueAccessor 接口。这应该是一个完整的示例,如果没有,请告诉我,我会更改代码,我直接在浏览器中输入。
@Component({
// Ensure [formControl] or [formControlName] is also specified
selector: '[formControl] app-form-group, [formControlName] app-form-group',
templateUrl: './country-selector.component.html',
styleUrls: ['./country-selector.component.scss'],
providers: [
{
// Provide the value accessor
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CountrySelectorComponent),
multi: true
}
]
})
export class CountrySelectorComponent implements ControlValueAccessor {
private value: any;
private hasHadFocus = false;
private hasNotifiedTouched = false;
private propagateChange: any = () => {};
private propogateTouched: any = () => {};
public changed(event: any) {
this.value = event.srcElement.value;
this.propagateChange(this.value);
}
/**
* Called when (focus) is triggered
*/
public focused() {
this.hasHadFocus = true;
}
/**
* Called when (blur) is triggered
*/
public blurred() {
if (this.hasHadFocus && !this.hasNotifiedTouched) {
// Only notify once, and only if lost focus after a focus
this.hasNotifiedTouched = true;
this.propogateTouched();
}
}
/**
* Called when a new value is set via code
* @param obj
*/
writeValue(obj: any): void {
this.value = obj;
}
/**
* Register a call back to call when our value changes
* @param fn
*/
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
/**
* Register a call back to call when our value is first touched
* @param fn
*/
registerOnTouched(fn: any): void {
this.propogateTouched = fn;
}
}
您的app-form-group 模板看起来像这样
<div class="form-group">
<label class="col-md-2 control-label">{{Name}}</label>
<div class="col-md-9">
<input class="form-control" (blur)="blurred()" focus="focussed()" change="changed($event)">
</div>
- 将
[formGroup]="signupForm" 添加到主视图中的每个app-form-group 实例
- 在您的
app-form-group 控件中实现 OnInit。
- 将
private controlContainer: ControlContainer 添加到app-form-group 组件的构造函数中,以便Angular 将其注入
- 将
public form: FormGroup; 属性添加到您的app-form-group 组件。
-
在 ngOnInit 中添加如下代码
this.form = this.containerControl.control;
在您的 app-form-group 模板中,您可以像这样添加 [formGroup]
<div class="form-group" [formGroup]="form">
<label class="col-md-2 control-label">{{Name}}</label>
<div class="col-md-9">
<input class="form-control" [name]="name" [formControlName]="formCtrlName">
</div>
这是需要最少代码量的方法,当您想要嵌入编辑多条数据(如地址)的复合控件时,我会推荐这种方法。
来自这个博客 -> https://mrpmorris.blogspot.co.uk/2017/08/angular-composite-controls-formgroup-formgroupname-reactiveforms.html