所以,我有一个问题,我有一个带有表单的基本组件。但我希望能够向其中添加另一个字段。为什么?因为我有四页,结构非常相似,最多只有一个字段不同。我有一个 stackblitz 也应该可以传达这个想法。渲染部分运行良好。 但也给出一个总体思路:
@Component({
selector: 'app-base-form',
standalone: true,
imports: [ReactiveFormsModule, CommonModule],
template: `<form
style="display: flex; flex-direction: column; gap: 1rem"
[formGroup]="form"
>
<input formControlName="search" type="text" placeholder="Search something" />
<ng-template
[ngTemplateOutletContext]="{ $implicit: form }"
[ngTemplateOutlet]="seachOptionalField()!"
></ng-template>
</form>`,
})
export class BaseFormComponent {
seachOptionalField = input<TemplateRef<any>>();
fb = inject(UntypedFormBuilder);
form = this.fb.group({
search: this.fb.control(['']),
});
}
最初的想法是通过出口上下文传递表单,但以编程方式添加控件并没有真正影响原始表单。另外,还有如何应用渲染的(要使用的)表单控件的问题。
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, BaseFormComponent],
template: `
<app-base-form [seachOptionalField]="searchOptionalField"></app-base-form>
<ng-template #searchOptionalField let-form>
<input type="text" placeholder="We just added this" />
{{form.value | json}}
</ng-template>
`,
})
export class App {}
formControlName
,并将它们包装在模板内的表单元素上。
您还可以添加一个额外的参数,它指定对象上的新表单控件配置,我们可以在初始化时将其解构到表单组中。下面是 stackblitz 的工作示例!
完整代码:
main.ts
import { Component, inject } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import 'zone.js';
import { BaseFormComponent } from './app/base-form/base-form.component';
import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, BaseFormComponent, ReactiveFormsModule],
template: `
<app-base-form [seachOptionalField]="searchOptionalField" [extraFormParams]="extraFormParams"></app-base-form>
<ng-template #searchOptionalField let-form>
<form [formGroup]="form">
<input type="text" placeholder="We just added this" formControlName="search2"/>
</form>
{{form.value | json}}
</ng-template>
`,
})
export class App {
fb = inject(UntypedFormBuilder);
extraFormParams = {
search2: this.fb.control(['']),
};
}
bootstrapApplication(App);
基本形式.ts
import { CommonModule } from '@angular/common';
import { Component, TemplateRef, inject, input } from '@angular/core';
import {
FormGroup,
ReactiveFormsModule,
UntypedFormBuilder,
} from '@angular/forms';
@Component({
selector: 'app-base-form',
standalone: true,
imports: [ReactiveFormsModule, CommonModule],
template: `<form
style="display: flex; flex-direction: column; gap: 1rem"
[formGroup]="form"
>
<input formControlName="search" type="text" placeholder="Search something" />
<ng-template
[ngTemplateOutletContext]="{ $implicit: form }"
[ngTemplateOutlet]="seachOptionalField()!"
></ng-template>
</form>`,
})
export class BaseFormComponent {
seachOptionalField = input<TemplateRef<any>>();
extraFormParams = input<Object>({});
fb = inject(UntypedFormBuilder);
form!: FormGroup;
ngOnInit() {
this.form = this.fb.group({
search: this.fb.control(['']),
...this.extraFormParams(),
});
}
}