我在组件中有一组对象。我将在模板中进行迭代。
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'sample-app';
classesData = [];
constructor() {
}
ngOnInit() {
this.classesData = [
{title: 'Hello0'}, {title: 'Hello1'}, {title: 'Hello2'}
];
}
duplicate() {
const newData = JSON.parse(JSON.stringify(this.classesData[1]));
newData.title += 'Copy';
this.classesData.splice(1, 0, newData);
}
}
<form #testingFrom="ngForm">
<p>{{classesData | json}}</p>
<div *ngFor="let classData of classesData; let i=index">
<input [(ngModel)]="classData.title" name="{{'title-' + i}}" type="text">
</div>
<button (click)="duplicate()">Duplicate</button>
</form>
我的目标是当用户单击重复按钮时,我只是在数组的 index 1 中添加了一个新元素。我的初始状态看起来像(用户点击之前)
用户单击重复按钮后的状态
在上方第3个输入字段的图像中,我们得到的是 Hello1Copy ,而不是 Hello1 。
答案 0 :(得分:1)
问题是您正在使用表单。由于您使用的是表格,因此,如果您打算更改现有数据源,则需要指定角度应如何跟踪表格项的更改。您可以使用trackBy
管道执行此操作:
<form #testingFrom="ngForm">
<p>{{classesData | json}}</p>
<div *ngFor="let classData of classesData; let i=index; trackBy: trackByFn">
<input [(ngModel)]="classData.title" [name]="'title-' + i" type="text">
</div>
<button (click)="duplicate()">Duplicate</button>
</form>
打字稿相关部分:
trackByFn(index: any) {
return index;
}
请注意,将添加元素添加到集合中将在您的原始示例中起作用。
答案 1 :(得分:1)
我完全怀疑这种行为是由于name
属性值中的冲突而发生的。仅在这种情况下,如果您在第一个位置splice
newItem
,它只会添加该变量,而其他DOM不会重新呈现。对于交叉验证,您可以尝试将input
元素替换为{{classData.title}}
这样的简单绑定,然后一切正常。
可以通过始终不冲突name
属性值来轻松解决此问题。这意味着为每个收集项分配一个唯一的id
变量并使用它。
this.classesData = [
{ id: 1, title: 'Hello0' },
{ id: 2, title: 'Hello1' },
{ id: 3, title: 'Hello2' }
];
duplicate() {
const newData = JSON.parse(JSON.stringify(this.classesData[1]));
newData.title += 'Copy';
newData.id = Date.now()
this.classesData.splice(1, 0, newData);
}
模板
<div *ngFor="let classData of classesData;let i=index">
<input [(ngModel)]="classData.title" [name]="'title_'+classData.id" type="text">
</div>
您还可以通过从每个输入字段中删除name
属性来验证相同内容。但这还不够,它会抛出
错误错误:如果在表单标签中使用ngModel,则名称 必须设置属性或将表单控件定义为 ngModelOptions中的“独立”。
因此,在每个输入字段上添加[ngModelOptions]="{standalone: true}"
,以使没有name
属性的输入正常工作。如@briosheje的另一个答案所建议,您还可以使用trackBy
来强制执行渲染。
PS:我正在研究为什么在name
和input
组合使用时,这种方法为何工作不同的原因,我怀疑使用form
元素的input
API接线。知道后,我会立即更新答案。
答案 2 :(得分:0)
制作另一个变量,然后对该变量进行迭代以创建输入框
import { Component,OnInit } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
title = 'sample-app';
originalData=[];
classesData = [];
constructor() {
}
ngOnInit() {
this.classesData = [
{title: 'Hello0'}, {title: 'Hello1'}, {title: 'Hello2'}
];
this.originalData=[...this.classesData]; // changed here
}
duplicate() {
const newData = JSON.parse(JSON.stringify(this.classesData[1]));
newData.title += 'Copy';
this.classesData.splice(1, 0, newData);
}
}
答案 3 :(得分:0)
您可以使用“ trackBy”功能解决问题。请参见下面的代码示例。
app.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'sample-app';
classesData = [];
constructor() {}
ngOnInit() {
this.classesData = [
{ title: 'Hello0' },
{ title: 'Hello1' },
{ title: 'Hello2' }
];
}
duplicate() {
const newData = JSON.parse(JSON.stringify(this.classesData[1]));
newData.title += 'Copy';
this.classesData.splice(1, 0, newData);
}
trackByIndex(index: number, obj: any): any {
return index;
}
}
app.component.html
<form>
<p>{{classesData | json}}</p>
<div *ngFor="let classData of classesData; let i=index;trackBy:trackByIndex;">
<input [(ngModel)]="classesData[i].title" name="{{'title-' + i}}" type="text" />
</div>
<button (click)="duplicate()">Duplicate</button>
</form>
请让我知道该解决方案是否适合您!