简体   繁体   English

模板驱动表单显示的值不正确

[英]Template Driven Form doesn't show correct value

I have a bug when I remove an address and add a new one. 删除地址并添加新地址时出现错误。 The previous address gets overwritten with the new one. 以前的地址将被新地址覆盖。

I created a small demo application to showcase my problem: 我创建了一个小型演示应用程序来展示我的问题:

github: https://github.com/kolomu/HeroDemo github的: https : //github.com/kolomu/HeroDemo
stackblitz: https://stackblitz.com/edit/angular-gitter-5o6ydi stackblitz: https ://stackblitz.com/edit/angular-gitter-5o6ydi

It's not that the model is wrong, somehow the view which angular renders isn't in updated correctly. 并不是模型是错误的,某种程度上角度渲染的视图没有正确更新。

View: 视图:

  <form #heroForm="ngForm">

    <div class="form-group">
      <div class="addresses" *ngFor="let address of model.addresses; let i=index">
        <label for="address-{{i}}">Address {{i}}</label>
        <input type="text" class="form-control" [(ngModel)]="address.location" name="location-{{i}}">
        <button class="btn btn-danger" (click)="remove(address)">Remove Address</button>
      </div>
    </div>

    <button class="btn btn-primary" (click)="add()">Add Address</button>

  </form>

Component Class: 组件类别:

export class HeroFormComponent {

  model = new Hero(18, 'Dr IQ', [new Address(1,'main','Earth'), new Address(9001,'sub','Moon')]);

  remove(address) {
    const index = this.model.addresses.findIndex(
      address => address.id === address.id
    );

    this.model.addresses.splice(index, 1);
  }

  add(){
    this.model.addresses.push(new Address());
  }

}

Data Model: 资料模型:

export class Address {
    constructor(public id?: number, public type?:string, public location?: string) { }
}


export class Hero {

    constructor(
      public id: number,
      public name: string,
      public addresses: Address[]
    ) {  }

}

GIF-Image showcasing the problem: https://gfycat.com/DelightfulSpiffyBetafish 展示问题的GIF图片: https//gfycat.com/DelightfulSpiffyBetafish

One problem is that you use the same name address for the parameter of the remove method and for the parameter in findIndex . 一个问题是,您对remove方法的参数和findIndex的参数使用相同的名称address As a result, the comparison address.id === address.id returns true for the first item tested because it compares the item to itself. 结果,比较address.id === address.id对于测试的第一个项目返回true ,因为它会将项目与其自身进行比较。

remove(address) {
  const index = this.model.addresses.findIndex(
    address => address.id === address.id          <-- Always true!
  );
  ...
}

You should use a different name, for example _address for the parameter in findIndex (as shown in this stackblitz ): 你应该使用不同的名称,例如_address在参数findIndex (如所示这stackblitz ):

remove(address) {
  const index = this.model.addresses.findIndex(
    _address => _address.id === address.id
  );
  ...
}

Or you could pass the index as a parameter to remove , as suggested by Embrioka . 或者,可以按照Embrioka的建议将索引作为要remove的参数传递


In your code sample, when you add a new address after deleting the first one, the two fields show the same data (the value of the new address). 在您的代码示例中,当您在删除第一个地址后添加新地址时,这两个字段将显示相同的数据(新地址的值)。 That is strange, since everything looks fine in the template and in the code. 这很奇怪,因为在模板和代码中一切看起来都很好。 According to my tests, the problem comes from the fact that the name of the new input element is the same as the one used previously for the other element. 根据我的测试,问题出在以下事实:新输入元素的名称与先前用于其他元素的名称相同。 In your template, if you replace: 在模板中,如果您替换:

name="location-{{i}}"

with

name="location-{{address.id}}"

the problem disappears, as long as each address.id is unique. 只要每个address.id是唯一的,问题就会消失。 Apparently, reusing the same name for a different item prevents the input content from being updated correctly by Angular. 显然,为不同的项目重用相同的名称会阻止Angular正确更新输入内容。

Do not pass the whole address, only the index: 不传递整个地址,仅传递索引:

<div class="form-group">
      <div class="addresses" *ngFor="let address of model.addresses; let i=index">
        <label for="address-{{i}}">Address {{i}}</label>
        <input type="text" class="form-control" [(ngModel)]="address.location" name="location-{{i}}">
        <button class="btn btn-danger" (click)="remove(i)">Remove Address</button>
      </div>
</div>

And in the ts: 在ts中:

remove(index) {
    this.model.addresses.splice(index, 1);
}

With this solution you don't even have to find the index. 使用此解决方案,您甚至不必查找索引。

The problem with your solution what the previous commenter mentioned and also you id will be undefined, so in the add method just define an ID or pick an another property when looking for the index! 您的解决方案所存在的问题将是不确定的,即先前的评论者提到的ID以及您的ID,因此在add方法中只需定义ID或在寻找索引时选择另一个属性即可!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM