模板驱动的表单如何访问组件中的控件?



我有一个使用模板驱动方法的<form>

表单包含本地控件的混合,如<input><select>,以及包装器组件,如<text-control><checkbox-control>,其中包含本地<input>元素。

表单如何访问<text-control>的原生元素来读取其错误和触摸状态?

另外,如果我想在该包装器组件上放置一个验证器指令,并将其向下管道到本机<input>,我该如何实现这一点?

我试图在包装器组件上使用ngModel,但它不起作用,因为ngModel是挂钩到包装器组件,而不是底层的<input>元素。

另一种方法是使用<ng-content>,但是底层的原生元素有很多属性,所以到处复制粘贴会很痛苦。

的例子:

<checkbox-control>
<!-- Now, it's easy for the form to access the control. -->
<!-- But I've too many attributes and properties that go here. -->
<input type="checkbox">
</checkbox-control>

PS:我不希望使用ElementRef来访问本地元素,我只是希望<form>能够意识到本地元素的错误状态,以便我可以判断表单是否有效。

的例子:

<form #editor="ngForm">
<input type="text" validateText />
<select validateSelect>
<option value="1"></option>
<option value="2"></option>
</select>
<!-- Does not work. -->
<checkbox-control validateCheckbox></checkbox-control>
</form>

提前感谢。

可以在模板方法中使用元素的局部引用。请参考我刚刚写的代码来解释:

https://stackblitz.com/edit/angular-ivy-7no9ok?file=src/app/app.component.html

我找到了一个合理的解决方案,不需要编写太多代码,也不需要编辑太多组件。

步骤1:创建验证器

@Directive({ selector: '[assertNoSpecialChars]' })
export class SpecialCharacterValidator implements Validator {
// The directive will have a reference for the name of the form's control.
@Input() assertNoSpecialChars: string = '';
validate(group: FormGroup): ValidationErrors | null {
const control = group.controls[this.assertNoSpecialChars];
// For simplicity, let's say we don't want the dollar sign in our input.
if (control.value.includes('$')) {
return { invalid: true };
} else {
return null;
}
}
}

步骤2:在表单上应用指令

<form #f="ngForm" [assertNoSpecialChars]="'username'">
<text-control></text-control>
</form>

步骤3:将组件的输入事件绑定到宿主表单组件

<form #f="ngForm" [assertNoSpecialChars]="'username'">
<text-control (input)="updateFormManually($event, 'username')"></text-control>
</form>

步骤4:为你的NgForm获取一个引用,并实现更新机制

@Component({})
export class FormComponent implements AfterViewInit {
// Grab a reference for your NgForm.
@ViewChild('f', { static: true }) f!: NgForm;
// Create your form control.
username: FormControl = new FormControl();
// Register your control to the NgForm.
ngAfterViewInit(): void {
this.f.form.addControl('username', this.username);
}
// Update the control manually.
updateFormManually(event: any, controlName: string): void {
this.f.form.controls[controlName].setValue(event.target.value);
}
}

现在,表单的有效性状态和错误消息将被正确绑定。

最新更新