*ngFor 在添加新输入元素时重置所有表单值

Posted

技术标签:

【中文标题】*ngFor 在添加新输入元素时重置所有表单值【英文标题】:*ngFor resetting all form values when adding new input element 【发布时间】:2017-09-25 15:15:37 【问题描述】:

我有一个带有按钮的 Angular2 应用程序,可以将另一笔贷款添加到我的贷款中。我的 *ngFor 也很简单:

    <div *ngFor="let loan of myLoans">
      <label>loan.name</label>
      <input type="text" name="loan.name" [(ngModel)]="loan.amount">
    </div>

myLoans 是一个带有 nameamount 参数的 Loan 对象数组。我的按钮也很简单。

<button id="addLoan" type="button" (click)="addLoan()">Legg til lån</button>

addLoan() 函数:

addLoan(): void
    var newLoan = new Loan();
    this.myLoans.push(newLoan);

我的问题是,当我在列表中添加新贷款时,我在其他贷款的输入字段中的任何值都会返回 0,或者我在贷款对象的构造函数中设置的任何值。

加载应用会显示此图片

ngModel 在输入数字时工作

按下“Legg til lån”按钮后,第一个输入的值被重置

如果我尝试输入另一个数字,ngModel 仍在为第一个输入工作

有人知道这里发生了什么吗?

【问题讨论】:

看起来很奇怪。如果数组中的值是对象,这通常才有效。你试过什么浏览器?你能在 Plunker 中重现吗? 【参考方案1】:

AJT_82 接近问题所在,因为非唯一名称会导致您出现问题,但是您可以通过将模板 html 更改为这个

<div *ngFor="let loan of myLoans">
  <label>loan.name</label>
  <input type="text" [name]="loan.name" [(ngModel)]="loan.amount">
</div>

注意在 [ ] 中输入名称的变化。这将确保模板维护到名称的链接,并且只要每笔贷款的名称是唯一的,标识符也是如此。

更新: 如果名称不是唯一的,您可以将索引添加到它以使其唯一。

<div *ngFor="let loan of myLoans; let i=index">
  <label>loan.name</label>
  <input type="text" [name]="loan.name + '_' + i" [(ngModel)]="loan.amount">
</div>

【讨论】:

好一个,+1,尽管我提到loan.name 是 OP 代码中的原始类型:D 谢谢你们两位。你实际上可以添加几个相同类型(/名称)的贷款,并且由于类型与贷款名称直接相关,那么我也应该使用索引。 我也面临着类似的问题。为“名称”属性赋予唯一名称。我仍然面临这个问题。这是 plunker 网址:plnkr.co/edit/SU9XqcP3eDPZQD3A。谁能帮忙:-)【参考方案2】:

我 99% 确定您使用的是表单,但没有唯一的 name 属性,因为 ngModel 有效。

name 属性必须是唯一的,才能作为单独的字段进行评估。 Angular 并不真正关心表单中的ngModel,而是查看name 属性。

请注意,您当前设置的名称属性:name="loan.name" 实际上只包含字符串文字 loan.name,而不是模型的实际值,因此名称不是唯一的。

因此,当您推送新的loan 时,所有其他贷款都会获得与新推送的值相同的值,因为所有字段都被评估为相同。

这可以通过在名称属性中添加索引来轻松解决,例如:

<div *ngFor="let loan of myLoans; let i=index">
  <label>loan.name</label>
  <input type="text" name="loan.namei" [(ngModel)]="loan.amount">
</div>

【讨论】:

【参考方案3】:

我已经尝试过您的代码,它对我来说很好用。我假设这可能是编译器问题。尝试将您的 ng2 和 typescript 库更新到最新版本。这是一个示例部分 tsconfig 文件:


  "compilerOptions": 
    "target": "es5",
    "typeRoots": ["node_modules/@types/"],
    "types": [
      "node",
      "es6-shim"
    ]
  

同时避免使用“var”进行变量声明。使用“let”来保持变量范围。我认为你的问题可能是因为使用了 var。如果您使用的是旧编译器,它可能会弄乱您的对象。

【讨论】:

【参考方案4】:

输入的值变为零,因为您已将 [(ngModel)] 声明为 *ngFor 的迭代器对象。当您将一个空白对象推送到 myLoans 的数组时,ngModel 会将输入更改为零(金额的默认值)

例子:

myLoans = [0, 1, 2, 3]

当您刷新页面时,[(ngModel]) 将数组的最后一个值绑定到输入 (3)。

如果你在输入上写 125,

那么你也改变了最后一个数组的值

myLoans = [0, 1, 2, 125]

如果你推送一个新元素,Angular 将使用最后一个数组值刷新输入

myLoans = [0, 1, 2, 125, 0]

Input.value 现在 = 0


我的意见:在 *ngFor 中使用 ngModel 是一种不好的做法,还有另一种方法可以使用 (click) 事件和 Angular Selector 来完成相同的任务。试试这个:

<input #loan ..>
<button (click)="addLoan(loan.value)">Add Loan</button>

【讨论】:

【参考方案5】:

@Joo_Beck 建议使用[name]=loan.name 而不是name='loan.name'。但这对我不起作用。我刚刚添加了一个索引i,其名称如下所示,它运行良好。

<div *ngFor="let loan of myLoans; let i=index">
  <label>loan.name</label>
  <input type="text" name="loan.namei" [(ngModel)]="loan.amount">
</div>

@AJT_82 建议了对我有用的解决方案。谢谢!

感谢@Cassiano,你很好地解释了原因!

【讨论】:

以上是关于*ngFor 在添加新输入元素时重置所有表单值的主要内容,如果未能解决你的问题,请参考以下文章

将表单重置为默认值

Chrome 表单重置不更改显示选择元素

Reactstrap Form 重置输入值 MERN 堆栈

如何在引导模式框中重置表单主体?

将表单的所有输入重置为默认值而不重新加载

Chrome - 在向 *ngFor 视图添加元素时,始终向下滚动到最后一个元素