我有Angular2 reactive form。我创建了formControl
并将其分配给[formControl]=...
的输入字段。据我了解,它会创建nativeElement <-> formControl
链接。
我的问题:是否可以nativeElement
获取formControl
?我想做myFormControl.nativeElement.focus()
答案 0 :(得分:7)
下面的代码不适用于纯ngModel绑定,所以我做了很多实验。最新的,也由Maximillian Schwarzmuller确认应该是:
@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 。
很遗憾,它不是开箱即用的......
答案 1 :(得分:5)
我可以分享一个可怕的解决方案,但它对我有用。
在反应形式中,我们可以使用
1)FormControlDirective
<强> TS 强>
myControl = new FormControl('')
<强>模板强>
<input type="text" [formControl]="myControl">
或
2)FormControlName
<强> TS 强>
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();
}
<强> Plunker Example 强>
答案 2 :(得分:4)
Added minor fix to baHI answer(moved logic to OnInit). Error mentioned in comments is probably connected to changes in forms. This answer is for "@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;
}
}
答案 3 :(得分:0)
是的,您必须使用[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' />
答案 4 :(得分:0)
您好!希望您在玩Angular的过程中也能玩得开心:)
我花了一些时间解决一个相关的问题,这使我陷入了困境。 在我看来,“注入器”指令解决方案似乎是一种解决方法,并且是解决问题的不可预测的方式。
我怀疑Angular团队可能有他们为什么没有“开箱即用”的原因。也许他们不想将FormControl绑定到确切的DOM元素上,因为这两个元素可能会彼此失效或被删除(对于本机元素而言),或者被克隆(不会复制“扩展”分配,并且,因此,可以有效地减少针对原始DOM元素和FormControl对象的先前克隆的指令中的所有分配),等等。
因此,经过一番思考,我采用了以下解决方案:
// Get the first invalid formControlName to scroll to:
const firstInvalidField =
Object.keys(form.controls).find(field => form.get(field)?.invalid);
// My DOM element query selector string
const selector = `[formControlName=${firstInvalidField}]`;
console.log(
document.querySelector( ${selector} )`
);
现在,我保证可以引用DOM元素。