在我的Angular应用程序中有一个自定义的表单控件组件,它实现了ControlValueAccessor
接口。
但是,我想访问与我的组件相关联的FormControl
实例。我在FormBuilder
中使用反应式表单,并使用formControlName
属性提供表单控件。
那么,如何从自定义表单组件内部访问 FormControl
实例呢?
发布于 2017-06-24 11:46:16
这个解决方案诞生于Angular存储库中的the discussion。如果你对这个问题感兴趣,请务必阅读它,或者更好地参与。
我研究了FormControlName
指令的代码,它激发了我编写以下解决方案的灵感:
@Component({
selector: 'my-custom-form-component',
templateUrl: './custom-form-component.html',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: CustomFormComponent,
multi: true
}]
})
export class CustomFormComponent implements ControlValueAccessor, OnInit {
@Input() formControlName: string;
private control: AbstractControl;
constructor (
@Optional() @Host() @SkipSelf()
private controlContainer: ControlContainer
) {
}
ngOnInit () {
if (this.controlContainer) {
if (this.formControlName) {
this.control = this.controlContainer.control.get(this.formControlName);
} else {
console.warn('Missing FormControlName directive from host element of the component');
}
} else {
console.warn('Can\'t find parent FormGroup directive');
}
}
}
我将父FormGroup
注入到组件中,然后使用通过formControlName
绑定获得的控件名称从组件中获取特定的FormControl
。
但是,请注意,此解决方案是专门为在主机元素上使用FormControlName
指令的用例量身定做的。它在其他情况下不会起作用。为此,您需要添加一些额外的逻辑。如果你认为这个问题应该由Angular来解决,请务必访问the discussion。
发布于 2018-07-02 04:56:19
当通过[formControl]
指令进行绑定时,使用formControlName
作为输入参数不起作用。
这是一个不需要任何输入参数就可以双向工作的解决方案。
export class MyComponent implements AfterViewInit {
private control: FormControl;
constructor(
private injector: Injector,
) { }
// The form control is only set after initialization
ngAfterViewInit(): void {
const ngControl: NgControl = this.injector.get(NgControl, null);
if (ngControl) {
this.control = ngControl.control as FormControl;
} else {
// Component is missing form control binding
}
}
}
发布于 2020-05-18 02:52:20
基于之前的答案和在评论中找到的documentation,这是我对基于ControlValueAccessor
的组件最干净的解决方案的看法。
// No FormControl is passed as input to MyComponent
<my-component formControlName="myField"></my-component>
export class MyComponent implements AfterViewInit, ControlValueAccessor {
constructor(@Optional() @Self() public ngControl: NgControl) {
if (ngControl != null) {
// Setting the value accessor directly (instead of using
// the providers) to avoid running into a circular import.
ngControl.valueAccessor = this;
}
}
ngAfterContentInit(): void {
const control = this.ngControl && this.ngControl.control;
if (control) {
// FormControl should be available here
}
}
}
https://stackoverflow.com/questions/44731894
复制相似问题