Angular 表单和指令的一个小技巧
想象一下,你想在应用程序的多个地方使用一个表单。表单具有相同的布局,但验证方式却不同。
在我们的案例中,此表单用于多步骤流程,并且每一步都会变得更加严格。您能保持DRY原则吗?我们遇到了这个问题,并提出了以下解决方案。
表格
举个例子,我们来看一个简单的表单,表单中包含一个人的姓名、联系方式和过敏史。
一开始只需要填写姓名。之后,我们会逐步添加此人的其他信息。
@Component({
selector: 'person',
template: `
<div [formGroup]="form">
<div>
<label>Name</label>
<input type="text" formControlName="name" />
</div>
<div>
<label>Contact info</label>
<input type="text" formControlName="contactInfo" />
</div>
<div>
<label>Allergies</label>
<input type="text" formControlName="allergies" />
</div>
<strong>{{ form.valid ? 'valid' : 'invalid' }}</strong>
</div>
`,
})
export class PersonComponent {
form = this.formBuilder.group({
name: ['', Validators.required],
contactInfo: [''],
allergies: [''],
})
constructor(private formBuilder: FormBuilder) {}
}
默认情况下,我们将此人的姓名设为必填字段。
该指令
通过使用 Angular 指令,我们可以注入组件实例,从而访问表单。在本例中,我们可以修改表单的验证方式,并让更多字段成为必填字段。
@Directive({
selector: 'person[stage-one]',
})
export class StageOneDirective {
constructor(host: PersonComponent) {
host.form.get('contactInfo').setValidators([Validators.required])
}
}
为了确保指令能够注入PersonComponent
,我们必须使该指令特定于 Person 表单。为此,我们可以使用组件的选择器作为前缀,并在其后附加指令名称,即person[stage-one]
。这样,只有当指令作为 Person 组件的属性添加时,才能使用该指令。
由于 Person 组件的表单设置为公共,因此我们可以在指令内部访问表单。如果我们可以访问表单,我们就可以访问表单字段及其验证器。
我们可以使用相同的方法来创建更严格的验证。
@Directive({
selector: 'person[stage-two]',
})
export class StageTwoDirective {
constructor(host: PersonComponent) {
host.form.get('contactInfo').setValidators([Validators.required])
host.form.get('allergies').setValidators([Validators.required])
}
}
用法
为了使这个小例子完整,这就是你将如何将 person 组件与另一个组件中的指令一起使用或不一起使用。
<!-- Only the name is required -->
<person></person>
<!-- The name and the contactInfo are required -->
<person stage-one></person>
<!-- All fields are required -->
<person stage-two></person>
我发现这是一个与控制值访问器相结合的干净解决方案,正如在企业环境中使用 Angular 表单中讨论的那样。
在下面的闪电战中尝试一下这个例子。
文章来源:https://dev.to/angular/a-little-trick-with-angular-forms-and-directives-2mep