如何在具有反应形式的表单标签内进行动态输入
how to make dynamic input inside form tag with reactive form
我正在尝试使用动态输入制作反应式表单
所以我创建了这样的反应式表单组件
main_component.ts
constructor(private formBuilder: FormBuilder) {
this.operationGroupForm = this.formBuilder.group({
'operation': '',
'searchTerm': ''
});
}
main_component.html
<form [formGroup]="operationGroupForm">
<input type="text" formControlName="operation">
<div operationClass [type]="'mycustomtype'"
[_formControlName]="'searchTerm'"></div>
</div>
</form>
并创建附加到 div 的指令 operationClass
并将组件注入 div
operationClass.directive.ts
constructor(private el: ElementRef, private render: Renderer2, private viewContainerRef: ViewContainerRef,
private componentFactory: ComponentFactoryResolver) {}
ngOnInit(): void {
var comRef = this.componentFactory.resolveComponentFactory(input_component);
var _comRef = this.viewContainerRef.createComponent(comRef);
_comRef.instance.formControlName = this._formControlName;
_comRef.instance.type = this.type;
}
并且该组件通过采用 formControlName
和 type
并在自定义条件下呈现输入来呈现正确的输入
用于呈现输入的组件是:
input_component.ts
@Input() formControlName: string;
@Input() type: string;
constructor() {
}
ngOnInit(): void {
}
input_component.html
<ng-container *ngIf="type">
<ng-container [ngSwitch]="type">
<ng-container *ngSwitchCase="'mycustomtype'">
<input type="text" [formControlName]="formControlName" class="form-control" />
</ng-container>
<ng-container *ngSwitchDefault>
<input type="number" [formControlName]="formControlName" class="form-control" />
</ng-container>
</ng-container>
</ng-container>
问题是我认为内部输入 formControlName
看不到外部 formGroup
因为它会产生错误
ERROR Error: formControlName must be used with a parent formGroup directive. You'll want to add a formGroup
directive and pass it to an existing FormGroup instance (you can create one in your class).
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});
at Function.controlParentException (forms.js:1692)
at FormControlName._checkParentType (forms.js:6059)
at FormControlName._setUpControl (forms.js:6063)
at FormControlName.ngOnChanges (forms.js:5995)
at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.js:2131)
at callHook (core.js:3042)
at callHooks (core.js:3008)
at executeInitAndCheckHooks (core.js:2960)
at refreshView (core.js:7331)
at refreshEmbeddedViews (core.js:8408)
看起来您缺少组件中的 FormGroup
指令和实例化以及使用控件的 class,即 input.component.{ts|html}.
类似于:
this.myFormGroup = new FormGroup({
formControlName: new FormControl()
});
请参阅 Angular 文档中的 Create a FormGroup instance 部分。
考虑对您的代码应用以下更改:
main_component.ts
The value for each control name is an array containing the initial value as the first item in the array. (Angular Docs)
constructor(private formBuilder: FormBuilder) {
this.operationGroupForm = this.formBuilder.group({
'operation': [''], // <== provide an array
'searchTerm': [''] // <== provide an array
});
}
input_component.ts
由于 formControlName
必须与父 formGroup
指令一起使用,因此您需要添加一个 formGroup
指令并将其传递给您的 formGroup
实例,而不是传递您的 formGroup
实例可以使用 ControlContainer 将其注入子组件,如下所示:
import { FormGroup, ControlContainer } from '@angular/forms';
...
@Input() formControlName: string;
@Input() type: string;
public formGroup: FormGroup;
constructor(public controlContainer: ControlContainer) { // <== inject reference to formGroup via ElementInjector
this.formGroup = controlContainer.control as FormGroup
}
input_component.html
<ng-container *ngIf="type">
<ng-container [ngSwitch]="type" [formGroup]="formGroup"> <!-- <== pass injected form -->
<ng-container *ngSwitchCase="'mycustomtype'">
<input type="text" [formControlName]="formControlName" class="form-control" />
</ng-container>
<ng-container *ngSwitchDefault>
<input type="number" [formControlName]="formControlName" class="form-control" />
</ng-container>
</ng-container>
</ng-container>
我正在尝试使用动态输入制作反应式表单
所以我创建了这样的反应式表单组件
main_component.ts
constructor(private formBuilder: FormBuilder) {
this.operationGroupForm = this.formBuilder.group({
'operation': '',
'searchTerm': ''
});
}
main_component.html
<form [formGroup]="operationGroupForm">
<input type="text" formControlName="operation">
<div operationClass [type]="'mycustomtype'"
[_formControlName]="'searchTerm'"></div>
</div>
</form>
并创建附加到 div 的指令 operationClass
并将组件注入 div
operationClass.directive.ts
constructor(private el: ElementRef, private render: Renderer2, private viewContainerRef: ViewContainerRef,
private componentFactory: ComponentFactoryResolver) {}
ngOnInit(): void {
var comRef = this.componentFactory.resolveComponentFactory(input_component);
var _comRef = this.viewContainerRef.createComponent(comRef);
_comRef.instance.formControlName = this._formControlName;
_comRef.instance.type = this.type;
}
并且该组件通过采用 formControlName
和 type
并在自定义条件下呈现输入来呈现正确的输入
用于呈现输入的组件是: input_component.ts
@Input() formControlName: string;
@Input() type: string;
constructor() {
}
ngOnInit(): void {
}
input_component.html
<ng-container *ngIf="type">
<ng-container [ngSwitch]="type">
<ng-container *ngSwitchCase="'mycustomtype'">
<input type="text" [formControlName]="formControlName" class="form-control" />
</ng-container>
<ng-container *ngSwitchDefault>
<input type="number" [formControlName]="formControlName" class="form-control" />
</ng-container>
</ng-container>
</ng-container>
问题是我认为内部输入 formControlName
看不到外部 formGroup
因为它会产生错误
ERROR Error: formControlName must be used with a parent formGroup directive. You'll want to add a formGroup
directive and pass it to an existing FormGroup instance (you can create one in your class).
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});
at Function.controlParentException (forms.js:1692)
at FormControlName._checkParentType (forms.js:6059)
at FormControlName._setUpControl (forms.js:6063)
at FormControlName.ngOnChanges (forms.js:5995)
at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.js:2131)
at callHook (core.js:3042)
at callHooks (core.js:3008)
at executeInitAndCheckHooks (core.js:2960)
at refreshView (core.js:7331)
at refreshEmbeddedViews (core.js:8408)
看起来您缺少组件中的 FormGroup
指令和实例化以及使用控件的 class,即 input.component.{ts|html}.
类似于:
this.myFormGroup = new FormGroup({
formControlName: new FormControl()
});
请参阅 Angular 文档中的 Create a FormGroup instance 部分。
考虑对您的代码应用以下更改:
main_component.ts
The value for each control name is an array containing the initial value as the first item in the array. (Angular Docs)
constructor(private formBuilder: FormBuilder) {
this.operationGroupForm = this.formBuilder.group({
'operation': [''], // <== provide an array
'searchTerm': [''] // <== provide an array
});
}
input_component.ts
由于 formControlName
必须与父 formGroup
指令一起使用,因此您需要添加一个 formGroup
指令并将其传递给您的 formGroup
实例,而不是传递您的 formGroup
实例可以使用 ControlContainer 将其注入子组件,如下所示:
import { FormGroup, ControlContainer } from '@angular/forms';
...
@Input() formControlName: string;
@Input() type: string;
public formGroup: FormGroup;
constructor(public controlContainer: ControlContainer) { // <== inject reference to formGroup via ElementInjector
this.formGroup = controlContainer.control as FormGroup
}
input_component.html
<ng-container *ngIf="type">
<ng-container [ngSwitch]="type" [formGroup]="formGroup"> <!-- <== pass injected form -->
<ng-container *ngSwitchCase="'mycustomtype'">
<input type="text" [formControlName]="formControlName" class="form-control" />
</ng-container>
<ng-container *ngSwitchDefault>
<input type="number" [formControlName]="formControlName" class="form-control" />
</ng-container>
</ng-container>
</ng-container>