【问题标题】:Value Binding problem on input text generated by *NgFor*NgFor 生成的输入文本的值绑定问题
【发布时间】:2019-11-15 21:43:34
【问题描述】:

当尝试 *ngFor 在角度数组上生成输入文本元素并绑定到数组中的值时,我遇到了一些问题。当用户在文本输入中输入内容时,该值未正确绑定。

我尝试在更新数组后运行 changeDetection 但没有帮助。

在下面的代码示例中,我使用字符串值“test”的数据数组单击添加按钮时生成输入元素。输入的 [ngModel] 绑定到 Array 中的值。所以我希望所有输入都具有“测试”的价值。

但是当我们尝试在输入中输入一些值然后单击添加按钮时,生成的输入不会绑定到数组中的值。

https://stackblitz.com/edit/angular-uywkxr

import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  template: `
    <button (click)="onAdd()">Add</button>
    <br/><br/>
    <input
      *ngFor="let d of data;let i = index;trackBy:trackByfn" 
      type="text"
      [ngModel]="data[i]"
    > 
    <br/><br/>
    data: {{data|json}}
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  data = ['test'];  
  onAdd() {  
    this.data.push('test');
  }
  trackByfn = (index) => index;
}

【问题讨论】:

  • 您错过了数据的两种方式绑定[(ngModel)]="data[i]"
  • 我们可以不使用双向绑定吗?我不希望输入修改数据,只想要一种方式更新。单击“添加”按钮时,所有输入都需要在数组中具有值。单向绑定不是这样工作的吗?
  • @San:有任何答案对你有用吗?如果是,请考虑接受/支持他们。 What should I do when someone answers my question?

标签: angular typescript data-binding ngfor


【解决方案1】:

工作示例stackblitz

这是双向绑定语法--->[(ngModel)] 保持变量获取新值

  import { Component } from '@angular/core';
    @Component({
      selector: 'my-app',
      template: `

    <br/><br/>
    <input *ngFor="let d of data;let i = index;trackBy:trackByfn" 
    type="text" [value]="data[i]" [(ngModel)]="dataarray"> 
     <button (click)="onAdd(data[i])">Add</button>
    <br/><br/>
    data: {{data|json}}
      `,
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {

       data = ["ssdsdsd"];
       datatosave:any;  
      onAdd(data1) {  
        this.data.push(this.datatosave);

      }
      trackByfn = (index) => index;
    }

【讨论】:

    【解决方案2】:

    您必须将[ngModel] 更改为[(ngModel)] 才能进行双向数据绑定。

    有关角度数据绑定的更多信息:https://blog.thoughtram.io/angular/2016/10/13/two-way-data-binding-in-angular-2.html

    import { Component } from '@angular/core';
    @Component({
      selector: 'my-app',
      template: `
        <button (click)="onAdd()">Add</button>
        <br/><br/>
        <input 
          *ngFor="let d of data;let i = index;trackBy:trackByfn" 
          type="text"
          [(ngModel)]="data[i]"
        /> 
        <br/><br/>
        data: {{data|json}}
      `,
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      data = ['test'];  
      onAdd() {  
        this.data.push('test');
      }
      trackByfn = (index) => index;
    }
    

    更新:使用表单组

    import { Component } from '@angular/core';
    import { FormGroup, FormControl, Validators, AbstractControl } from '@angular/forms';
    
    @Component({
      selector: 'my-app',
      template: `
        <button (click)="onAdd()">Add</button>
        <div [formGroup]="form" *ngFor="let f of fields">
          <input type="text" [formControlName]="f" /> 
        </div>
        <div *ngFor="let f of fields">
          {{form.controls[f].value}}
        </div>
      `,
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      form: FormGroup = new FormGroup({
        test: new FormControl('test')
      });
      fields = ['test'];
      onAdd() {
        const length = this.fields.length;
        this.fields.push('test'+length);
        this.form.addControl('test'+length, new FormControl('test'));
      } // length to dynamically name the field
    }
    

    注意:不要忘记在 app.module.ts 的导入依赖项中添加 ReactiveFormsModule

    我分叉了你的堆栈闪电战: https://stackblitz.com/edit/angular-2t157s

    【讨论】:

    • 是否可以在没有双向绑定的情况下做到这一点?因为我不想通过绑定来实际更新数据。在我原来的 senario 数据来自其他来源。我正在使用 ngrx 并从选择器获取数据。
    • 使用 FormGroup 而不是双向绑定更新了我的答案。
    【解决方案3】:

    利用@ViewChildren 指令。在onAdd() 中,inputs 的最后一个元素被推送到data[]。这是相同的stackblitz

    代码:

    import { Component, ViewChildren, ElementRef, 
             QueryList, AfterViewInit } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
      <button (click)="onAdd()">Add</button>
      <br/><br/>
      <input #inputRef type="text" 
      *ngFor="let d of data; let i = index; trackBy:trackByfn"> 
      <br/><br/>
      data: {{data | json}}
      `,
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
      data = ['test'];
    
      @ViewChildren("inputRef") inputs: QueryList<ElementRef>;
    
      onAdd() {
        let domElement = this.inputs.last as ElementRef;
        this.data.push(domElement.nativeElement.value);
      }
    
    }
    

    有关@ViewChildren 的更多信息,请访问Angular docs

    【讨论】:

      猜你喜欢
      • 2016-08-01
      • 2019-12-06
      • 2018-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多