Можно ли получить собственный элемент для formControl?
У меня есть Angular2 реактивная форма. Я создал formControl
и присвоил его полям ввода [formControl]=...
. Как я понимаю, он создает ссылку nativeElement <-> formControl
.
Мой вопрос: можно ли получить nativeElement
для formControl
? Я хочу сделать что-то вроде myFormControl.nativeElement.focus()
Ответы
Ответ 1
Приведенный ниже код не работает с чистой привязкой ngModel, поэтому я провел много экспериментов. Последний, также подтвержденный Максимиллианом Шварцмюллером, должен быть следующим:
@Directive({
selector: '[ngModel]', // or 'input, select, textarea' - but then your controls won't be handled and also checking for undefined would be necessary
})
export class NativeElementInjectorDirective {
constructor(private el: ElementRef, private control : NgControl) {
(<any>control.control).nativeElement = el.nativeElement;
}
}
Поэтому, если эта директива предоставлена и экспортирована в основной модуль, она присоединит настраиваемое свойство nativeElement ко всему FormControl.
Стыдно не выходить из коробки...
Ответ 2
Я могу поделиться одним ужасным решением, но оно работает для меня.
В реактивных формах мы можем использовать либо
1) FormControlDirective
ц
myControl = new FormControl('')
шаблон
<input type="text" [formControl]="myControl">
или
2) FormControlName
ц
myForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.myForm = this.fb.group({
foo: ''
});
}
шаблон
<form [formGroup]="myForm">
<input type="text" formControlName="foo">
</form>
Итак, для этих директив я мог бы написать некоторый патч, например
1) FormControlDirective
const originFormControlNgOnChanges = FormControlDirective.prototype.ngOnChanges;
FormControlDirective.prototype.ngOnChanges = function() {
this.form.nativeElement = this.valueAccessor._elementRef.nativeElement;
return originFormControlNgOnChanges.apply(this, arguments);
};
2) FormControlName
const originFormControlNameNgOnChanges = FormControlName.prototype.ngOnChanges;
FormControlName.prototype.ngOnChanges = function() {
const result = originFormControlNameNgOnChanges.apply(this, arguments);
this.control.nativeElement = this.valueAccessor._elementRef.nativeElement;
return result;
};
После этого мы можем легко получить доступ к собственному элементу с FormControl
экземпляром
1) FormControlDirective
focusToFormControl() {
(<any>this.myControl).nativeElement.focus();
}
2) FormControlName
focusToFormControlName(name) {
(<any>this.myForm.get(name)).nativeElement.focus();
}
Пример плунжера
Ответ 3
В ответ baHI добавлено незначительное исправление (перемещена логика в OnInit). Ошибка, упомянутая в комментариях, вероятно, связана с изменениями в формах. Этот ответ для "@angular/forms": "~ 7.1.0",
@Directive({
selector: '[ngModel]'
})
export class NativeElementInjectorDirective implements OnInit {
constructor (private el: ElementRef, private control : NgControl) {}
ngOnInit(){
(this.control.control as any).nativeElement = this.el.nativeElement;
}
}
Ответ 4
Да, вы должны написать директиву с помощью [formControl], [formControlName]
. Полный пример:
import { Directive, ElementRef } from "@angular/core";
import { NgControl } from '@angular/forms';
@Directive({
selector: '[formControl], [formControlName]'
})
export class ControlErrorsDirective {
get control() {
return this.controlDir.control;
}
constructor(
private controlDir: NgControl,
private host: ElementRef<HTMLFormElement>) {
}
ngOnInit() {
console.log(this.host.nativeElement);
}
}
и в вашем html просто используйте formControlName
следующим образом: <input formControlName='name'/>