Hea*_*ady 5 angular angular-reactive-forms angular-forms
我有一个输入组件customInput,它创建一个经典的输入字段并为其添加一些布局香料,没有额外的逻辑。
我想将一个 formControl 传递给它,将它绑定到它包含的输入。
应该这样使用:
<form [formGroup]="form">
<custom-input [formControl]="form.controls['control']"></custom-input>
</form>
Run Code Online (Sandbox Code Playgroud)
内部自定义输入:
export class HidInputFieldComponent {
@Input() formControl: AbstractControl
...
}
<div class="container">
<input [formControl]="formControl"/>
<label>label</label>
</div>
Run Code Online (Sandbox Code Playgroud)
现在当我初始化组件时,我得到
未指定名称的表单控件没有值访问器
在我的组件构造函数中记录控件,它是未定义的。
我做错了还是没有办法解决ControlValueAccessor?由于我实际上并没有构建自定义控件(我仍然使用经典输入),因此看起来很极端
Joh*_*ido 16
您不需要导入 ControlValueAccessor 或任何类似的东西来完成它。
您需要做的就是将 FormControl 对象传递给您的子组件,如下所示:
<form [formGroup]="form">
<custom-input [control]="form.get('theControlName')">
</custom-input>
</form>
Run Code Online (Sandbox Code Playgroud)
这意味着您的自定义输入组件应如下所示:
import {Component, Input} from '@angular/core';
import {FormControl} from '@angular/forms';
@Component({
selector: 'custom-input',
templateUrl: './input.component.html',
styleUrls: ['./input.component.scss']
})
export class InputComponent {
@Input() control: FormControl;
}
Run Code Online (Sandbox Code Playgroud)
和模板:
<input [formControl]="control">
Run Code Online (Sandbox Code Playgroud)
就是这样。
如果您实现这样的自定义输入,您将不必将父 formGroup 带入子组件逻辑中,则在那里完全没有必要(除非您需要对其或其他表单控件进行一些操作)。
此外,将 FormControl 对象传递给自定义输入将使您可以访问它的属性,而无需引用 FormGroup 然后获取特定控件,因为这是在父组件上完成的工作。
我希望这个解决方案有助于简化许多人的工作,因为制作这种自定义控件很常见。
im.*_*tov 10
Johann Garrido 的这个答案很好,但是它引入了额外的输入[control],您在使用自定义组件时需要始终牢记这些输入。
另外,它直接与工作相关,ReactiveFormsModule因为它只接受FormControl实例。
我认为更好的方法是实现ControlValueAccessor接口,但利用一些解决方法来不重复控制处理:
export const NOOP_VALUE_ACCESSOR: ControlValueAccessor = {
writeValue(): void {},
registerOnChange(): void {},
registerOnTouched(): void {}
};
Run Code Online (Sandbox Code Playgroud)
并NOOP_VALUE_ACCESSOR在包装表单控件的组件中使用:
@Component({
selector: "wrapped-input",
template: `
<mat-form-field class="example-full-width">
<mat-label>Wrapped input</mat-label>
<!--We pass NgControl to regular MatInput -->
<input matInput [formControl]="ngControl.control" />
</mat-form-field>
`
})
export class WrappedInput {
constructor(@Self() @Optional() public ngControl: NgControl) {
if (this.ngControl) {
// Note: we provide the value accessor through here, instead of
// the `providers` to avoid running into a circular import.
// And we use NOOP_VALUE_ACCESSOR so WrappedInput don't do anything with NgControl
this.ngControl.valueAccessor = NOOP_VALUE_ACCESSOR;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这样 Angular 就会认为它WrappedInput像任何其他实现ControlValueAccessor接口的组件一样工作(MatInput例如)。
另外,它可以与ReactiveFormsModule和 常规一起使用FormsModule。
WrappedInput可以像这样使用:
<wrapped-input [formControl]="sourceControl"></wrapped-input>
Run Code Online (Sandbox Code Playgroud)
这是您可以使用的完整工作 stackblitz: https://stackblitz.com/edit/angular-wrapped-form-control-example ?file=src/app/app.ts
使用FormGroup 指令
该指令接受现有的 FormGroup 实例。然后,它将使用此 FormGroup 实例将任何子 FormControl、FormGroup 和 FormArray 实例与子 FormControlName、FormGroupName 和 FormArrayName 指令相匹配。
这样做你可以从父级访问子 formControl
@Component({
selector: 'app-custom-input',
templateUrl: './custom-input.html',
viewProviders:[{ provide: ControlContainer, useExisting: FormGroupDirective}]
})
export class HidInputFieldComponent {
constructor(private fcd:FormGroupDirective) {
}
ngOnInit() {
this.fcd.form.addControl('formControl',new FormControl(''));
}
}
<div class="container">
<input [formControl]="formControl"/>
<label>label</label>
</div>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10225 次 |
| 最近记录: |