Angular 2 - 表单组组件
Angular 2 - form group component
我正在尝试构建一个数据驱动的表单,输入来自另一个组件,如下所示:
<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
<app-form-group [name]="name"></app-form-group>
<app-form-group [name]="email"></app-form-group>
<app-form-group [name]="other"></app-form-group>
</form>
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" [name]="name" [formControlName]="formCtrlName">
</div>
问题是 formControlName
需要一个 formGroup
指令,因此我得到这个错误:
Error : Error in ./FormGroupComponent class FormGroupComponent - inline template:3:58 caused by: formControlName must be used with a parent formGroup directive.You'll want to add a formGroup
directive and pass it an existing FormGroup instance (you can create one in your class).
有什么办法可以解决这个问题吗?
您应该在 app-form-group
中使用您的 FormGroup [formGroup]="signupForm"
Component.You 可以使用此代码:
<div class="form-group" [formGroup]="signupForm">
<label class="col-md-2 control-label">{{Name}}</label>
<div class="col-md-9">
<input class="form-control" [name]="name" [formControlName]="formCtrlName">
</div>
您可以使用@Input 属性 将引用获取到子组件中:
app-form-group.ts:
@Input('group')
public signupForm: FormGroup;
app.html:
<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
<app-form-group [name]="name" [group]="signupForm"></app-form-group>
<app-form-group [name]="name" [group]="signupForm"></app-form-group>
<app-form-group [name]="name" [group]="signupForm"></app-form-group>
</form>
应用程序表单-group.html:
<div class="form-group" [formGroup]="signupForm">
<label class="col-md-2 control-label">{{Name}}</label>
<div class="col-md-9">
<input class="form-control" [name]="name" [formControlName]="formCtrlName">
</div>
有关详细信息,请查看本教程:https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2
当您想要实现自定义组件以将数据绑定到单个值时,正确的 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
}
]
您的子组件的 class 然后需要实现 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>
这是需要最少代码的方法,当您想要嵌入编辑多条数据(如地址)的复合控件时,我会推荐这种方法。
我正在尝试构建一个数据驱动的表单,输入来自另一个组件,如下所示:
<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
<app-form-group [name]="name"></app-form-group>
<app-form-group [name]="email"></app-form-group>
<app-form-group [name]="other"></app-form-group>
</form>
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" [name]="name" [formControlName]="formCtrlName">
</div>
问题是 formControlName
需要一个 formGroup
指令,因此我得到这个错误:
Error : Error in ./FormGroupComponent class FormGroupComponent - inline template:3:58 caused by: formControlName must be used with a parent formGroup directive.You'll want to add a formGroup
directive and pass it an existing FormGroup instance (you can create one in your class).
有什么办法可以解决这个问题吗?
您应该在 app-form-group
中使用您的 FormGroup [formGroup]="signupForm"
Component.You 可以使用此代码:
<div class="form-group" [formGroup]="signupForm">
<label class="col-md-2 control-label">{{Name}}</label>
<div class="col-md-9">
<input class="form-control" [name]="name" [formControlName]="formCtrlName">
</div>
您可以使用@Input 属性 将引用获取到子组件中:
app-form-group.ts:
@Input('group')
public signupForm: FormGroup;
app.html:
<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
<app-form-group [name]="name" [group]="signupForm"></app-form-group>
<app-form-group [name]="name" [group]="signupForm"></app-form-group>
<app-form-group [name]="name" [group]="signupForm"></app-form-group>
</form>
应用程序表单-group.html:
<div class="form-group" [formGroup]="signupForm">
<label class="col-md-2 control-label">{{Name}}</label>
<div class="col-md-9">
<input class="form-control" [name]="name" [formControlName]="formCtrlName">
</div>
有关详细信息,请查看本教程:https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2
当您想要实现自定义组件以将数据绑定到单个值时,正确的 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
}
]
您的子组件的 class 然后需要实现 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>
这是需要最少代码的方法,当您想要嵌入编辑多条数据(如地址)的复合控件时,我会推荐这种方法。