Получите доступ к FormControl из компонента пользовательской формы в Angular
У меня есть пользовательский компонент управления формой в моем приложении Angular, который реализует интерфейс ControlValueAccessor
.
Однако я хочу получить доступ к экземпляру FormControl
, связанному с моим компонентом. Я использую реактивные формы с помощью FormBuilder
и обеспечивая управление формой с помощью атрибута formControlName
.
SO, как мне получить доступ к экземпляру FormControl
изнутри моего настраиваемого компонента формы?
Ответы
Ответ 1
Это решение родилось из обсуждение в репозитории Angular. Пожалуйста, не забудьте прочитать его или даже лучше участвовать, если вы заинтересованы в этой проблеме.
Я изучил код директивы 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
в компонент, а затем получаю от него конкретный FormControl
, используя имя управления, полученное посредством привязки FormControlName
.
Однако следует иметь в виду, что это решение специально предназначено для использования, где директива FormControlName
используется для элемента хоста. В других случаях это не сработает. Для этого вам нужно добавить дополнительную логику. Если вы считаете, что это должно быть адресовано Angular, обязательно посетите обсуждение.
Ответ 2
Использование formControlName
в качестве входного параметра не работает при связывании через директиву [formControl]
.
Вот решение, которое работает в обоих направлениях без каких-либо входных параметров.
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
}
}
}
Ответ 3
Поскольку @Ritesh уже записал в комментарии, вы можете передать управление формой как привязку ввода:
<my-custom-form-component [control]="myForm.get('myField')" formControlName="myField">
</my-custom-form-component>
И затем вы можете получить экземпляр элемента управления внутри своего настраиваемого компонента формы следующим образом:
@Input() control: FormControl;
Ответ 4
Для тех, кто приезжает сюда в 2019 году, с Angular 6/7+, решение, которое не выдает предупреждение об устаревании, - это решение, описанное в этом ответе:
fooobar.com/info/14214332/...
Для получения более подробной информации смотрите эту презентацию, как описано выше.