【问题标题】:How to get ElementRef reference from NgModel FormControl in NgForm in Angular 4+如何在 Angular 4+ 中从 NgForm 中的 NgModel FormControl 获取 ElementRef 参考
【发布时间】:2018-05-12 10:38:39
【问题描述】:

在 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>

在组件部分,我想以ElementRef访问表单字段(即item_nameitem_type),这样我就可以通过ElementRefnativeElement方法访问它们对应的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。

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

【问题讨论】:

    标签: javascript angular angular-forms angular4-forms


    【解决方案1】:

    在您的 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
    • 实际上,您可以通过其根 ngForm 指令 (angular.io/guide/forms#ngForm) 和元素名称访问所有表单元素。 this.addForm.form.get('item_name') 会给你一个元素,你甚至可以使用像 this.addForm.form.get('item_type').disable() 这样的响应式表单 API。您还可以按照建议的 Benedict 附加空模板参考。我更新了我的 plunker,点击“Focus”按钮
    【解决方案2】:

    只是给出一个用例,您可以将#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。
    【解决方案3】:

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

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

    Stackblitz Example

    另见

    【讨论】:

    • 不错!这也有效。谢谢。这是更标准的方式。
    猜你喜欢
    • 2018-01-14
    • 2018-02-10
    • 2019-04-16
    • 2019-07-06
    • 2019-03-19
    • 2020-10-11
    • 2018-09-28
    • 2019-03-10
    • 1970-01-01
    相关资源
    最近更新 更多