Angular 如何从 NgForm 中的 NgModel FormControl 获取 ElementRef 引用 4+

How to get ElementRef reference from NgModel FormControl in NgForm in Angular 4+

在 Angular 4+ 中,我采用以下模板驱动形式:

<form #addForm="ngForm" (ngSubmit)="onFormSubmit($event, addForm)" >
  <div class="form-group">
    <label for="item_name">Item Name</label>
    <input id="item_name" name="item_name" [(ngModel)]="itemName" 
          #item_name="ngModel" autofocus class="form-control"
          required minlength="4" maxlength="20" 
          aria-describedby="itemNameHelpBlock">
    <small *ngIf="(item_name.invalid && item_name.touched)" id="itemNameHelpBlock" class="form-text text-error" >
      Value must be at least 4 characters and must not exceed 20 characters
    </small>
  </div>
  <div class="form-group">
    <label for="item_type">Item Type</label>
    <input id="item_type" name="item_type" [(ngModel)]="itemType" 
         #item_type="ngModel" class="form-control" required minlength="2"
          maxlength="20" aria-describedby="itemTypeHelpBlock">
    <small *ngIf="(item_type.invalid && item_type.touched)" id="itemTypeHelpBlock" class="form-text text-error" >
      Value must be at least 2 characters and must not exceed 20 characters
    </small>
  </div>
  <button class="btn btn-output-primary btn-lg" [disabled]="!addForm.form.valid">Add</button>
</form>

在组件部分,我想访问表单字段(即item_nameitem_type)作为ElementRef,以便我可以访问它们对应的DOM元素通过 ElementRef class 的 nativeElement 方法。

我试过 @ViewChild 但是,它 returns NgModel class 对象:

  @ViewChild('item_name') item_name: ElementRef;

  ngAfterViewInit() {
    console.log(this.item_name); // it returns NgModel class object
  }

但是,我需要访问 #item_name 表单域的 DOM HTMLElement,这样我就可以在每次提交表单后将文档焦点重置到 #item_name 输入域。现在,我不知道如何不直接访问 DOM 并且我不想通过 DOM api.[=24 直接访问 DOM =]

如果能在这里得到一些帮助,我会很高兴。

在您的 HTML 中,不要将模板引用 #item_name 指向 ngModel,只需将其留空,例如:

<div class="form-group">
  <label for="item_name">Item Name</label>
  <input id="item_name" 
         class="form-control"
         name="item_name" 
         [(ngModel)]="itemName" 
         #item_name 
         autofocus>
</div>

然后,您可以使用 @ViewChild 装饰器访问 DOM 元素(就像您所做的那样),例如:

this.item_name.nativeElement,

我注意到,您的提交按钮中有一个拼写错误:在 disabled 属性.

之前缺少开头的“[”

笨蛋:https://plnkr.co/edit/XHqOiEBmuFrA3slZSlrD?p=preview

仅举一个用例,您可以将 #item_name 指向 ngModel 以访问模型本身的某些属性,例如,如果它当前被认为是有效的。

<input id="item_name" name="item_name" [(ngModel)]="itemName" #item_name="ngModel" 
    autofocus class="form-control">
<!-- here's where you can access the attributes if it's pointed to ngModel-->
<small [hidden]="password.valid">
  The item name is not valid
</small>

如果您不需要这个相当花哨的东西,您可以按照 Andriy 的建议将其删除。然后它开箱即用,无需进一步更改。

但是如果您需要保留它,您可以为您的输入字段提供一个额外的引用,您可以使用它来获取 ElementRef。

<input id="item_name" name="item_name" [(ngModel)]="itemName"
   #item_name="ngModel" #itemNameField autofocus class="form-control">

您只需引用未指向 ngModel 的那个即可。

@ViewChild('itemNameField') itemNameField: ElementRef;

Angular 不会抱怨在一个字段上有多个引用(据我测试)

我只需将 read 选项添加到 ViewChild 查询:

@ViewChild('item_name', { read: ElementRef }) item_name: ElementRef;
                           ^^^^^^^^^^^^^^^

Stackblitz Example

另见