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

7
在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访问,以便通过ElementRef类的nativeElement方法访问它们对应的DOM元素。我已经尝试使用@ViewChild,但它返回NgModel类对象:
  @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直接访问DOM。

如果能得到帮助,我会很高兴的。

3个回答

20

不错!这也可以。谢谢。这是更标准的方式。 - asmmahmud

3

举个例子,您可以将#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不会因为一个字段有多个引用而报错(据我测试)


太棒了!它像魔法一样运行。非常感谢@Benedikt。 - asmmahmud

0
在你的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属性之前缺少了开头的'['。

Plunker链接:https://plnkr.co/edit/XHqOiEBmuFrA3slZSlrD?p=preview


但是,我不能这样做,因为我需要使用NgForm的模板驱动输入字段验证,例如requiredminlength,并且需要检查item_name.invaliditem_name.touched等。 - asmmahmud
1
实际上,您可以通过其根ngForm指令(https://angular.io/guide/forms#ngForm)和元素名称访问所有表单元素。 this.addForm.form.get('item_name')将为您获取一个元素,您甚至可以使用响应式表单API,例如this.addForm.form.get('item_type').disable()。您还可以像Benedict建议的那样添加额外的空模板引用。我更新了我的plunker,请单击“Focus”按钮。 - Andriy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接