是否有可能获得formControl的原生元素?

时间:2016-09-22 15:01:02

标签: angular angular2-forms

我有Angular2 reactive form。我创建了formControl并将其分配给[formControl]=...的输入字段。据我了解,它会创建nativeElement <-> formControl链接。

我的问题:是否可以nativeElement获取formControl?我想做myFormControl.nativeElement.focus()

之类的事情

5 个答案:

答案 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元素。