我的要求是我需要创建一个包含嵌套组件的表单。
我正在为每个表单字段创建组件,意味着文本框会有
作为一个组件,对于单选按钮,将有另一个组件,如明智
<form [formGroup]="myForm">
<textbox-component></textbox-component>
<radioButton-component></radioButton-component>
</form>
我想使用Reactive表单创建此表单,因为我想要我的 html不受影响,仅通过打字稿进行表单验证。
但是我找不到任何解决方案我们如何能够嵌套反应形式 组件。
答案 0 :(得分:41)
经过我的研究和研究实验我找到了一个问题的答案,所以我自己回答。如果它节省了某人的时间,那么我会很高兴。
如果您想使用嵌套组件创建反应式表单,则可以执行以下操作
这里我创建一个包含两个嵌套组件的表单,一个用于textbox&amp;其他用于单选按钮
您的父组件可以是这样的
<form [formGroup]="myForm">
<child-textbox-component [parentFormGroup]="myForm">
</child-textbox-component>
<child-radio-button-component [parentFormGroup]="myForm">
</child-radio-button-component>
</form>
我们将FormGroup对象作为输入传递给在父组件中创建的子组件 作为子组件的输入,他们将在其中使用此FormGroup对象 用于设计类的特定控制的组件
您的孩子组件将是这样的
儿童文本框组分
<div class="form-group" [formGroup]="parentFormGroup">
<label>
{{control.caption}}
</label>
<input class="form-control" type="text" [title]="control.toolTip"
[attr.maxlength]="control.width" [name]="control.name"
[value]="control.defaultValue" [formControlName]="control.name"/>
</div>
儿童单选按钮组分
<div class="form-group" [formGroup]="parentFormGroup">
<label>
{{control.caption}}
</label>
<div>
<label *ngFor="let value of control.values; let idx = index"
class="radio-inline" [title]="control.tooltip">
<input type="radio" [name]="control.name" [formControlName]="control.name"/>
{{ value }}
</label>
</div>
</div>
这里控件是保存要为这些显示的数据的模型类 儿童组成部分。
通过这种方式,您可以使用嵌套组件生成表单, 所以你不需要单独的形式(可以说大表格) 零件。您可以将其分解为尽可能多的子组件和形式会 易于创造和保持也使用角度2的反应形式。您也可以轻松添加验证。
在回答此
之前,我已按照这些链接进行操作答案 1 :(得分:1)
对Mhesh的回答补充说明,您可以构建此相同的解决方案,而无需在HTML中注入[parentFormGroup]
。您可以在可重复使用的表单组中执行此Stack Overflow post来执行此操作。
这真的很好。
要采用现有解决方案,您可以执行相同的操作,但:
您的父组件可以是这样的,没有在
中传递任何其他参数<form [formGroup]="myForm">
<child-textbox-component></child-textbox-component>
<child-radio-button-component></child-radio-button-component>
</form>
另外请注意,您可以像这样设置表单组:
<form [formGroup]="myForm">
<child-textbox-component></child-textbox-component>
<child-radio-button-component formGroupName="myGroup"></child-radio-button-component>
</form>
儿童文本框组分
<div class="form-group" [formGroup]="controlContainer.control">
<label>
{{control.caption}}
</label>
<input class="form-control" type="text" [title]="control.toolTip"
[attr.maxlength]="control.width" [name]="control.name"
[value]="control.defaultValue" [formControlName]="control.name"/>
</div>
要启用此功能,您需要在ControlContainer
@Component
@Component({
moduleId: `MODULE_ID_HERE`,
selector: "child-textbox-component",
templateUrl: "childTextbox.component.html",
})
export class ChildTextboxComponent {
constructor(private controlContainer: ControlContainer, OTHER_PARAMETERS) {
}
}
答案 2 :(得分:1)
要扩展可能的答案列表,this article by Alexey Zuev建议在组件装饰器中使用provide:ControlContainer
和useExisting:NgForm
作为将ngForm
指令传递到子组件的方法。
@Component({
selector: 'registrant',
templateUrl: 'app/register/registrant.component.html',
**viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]**
})
答案 3 :(得分:0)
使用[formGroup]绑定在表单块中传递相同或子formGroup。
答案 4 :(得分:0)
尝试使用嵌套的日期选择器时出现相同的问题。上面的解决方案不适用于我。我通过发出更改日期和直接索取控制表来解决问题。
calendar-input.component.ts
@Component({
selector: 'app-calendar-input',
templateUrl: '...',
})
export class CalendarInputComponent {
@Output() dateChanged = new EventEmitter<Date|null>();
onClose() {
this.dateChanged.emit(this.currentDate);
}
...
}
模板
<app-calendar-input
...
(dateChanged)="setFormControlValueByItem(item, col.propName, $event)">
</app-calendar-input>
以及具有表单组和表单控件的组件:
setFormControlValueByItem(item: FormItem<I, FormGroup>, propName: string, value: any): void {
item.frameworkFormGroup.controls[propName].setValue(value);
item.frameworkFormGroup.controls[propName].markAsTouched();
item.frameworkFormGroup.controls[propName].markAsDirty();
}
在我的情况下, item.frameworkFormGroup
是FormGroup的实例,而propName
是我通常会写到属性formControlName
的字段名称。
此解决方案的不足之处在于,它使代码在某些情况下不易破坏FormGroup和FormConrol API中的中断。
另请参阅:https://angular.io/api/forms/FormGroup 和https://angular.io/api/forms/FormControl