我目前有一个正通过* ngFor的离子输入,因此它会重复多次。当我想向* ngFor循环添加新记录(以添加新的离子输入行)时,出现以下错误:
ExpressionChangedAfterItHasBeenCheckedError:检查表达式后,表达式已更改。先前的值:'model:abc'。当前值:“型号:”。
这是我的代码:
.html
<ion-item *ngFor="let item of values; let i = index;">
<ion-input formControlName="taskDetail" [(ngModel)] = "values[i].answer" type="text"></ion-input>
<ion-icon name="remove-circle" (click)="removeTaskOption(i)" slot="end"></ion-icon>
</ion-item>
.ts
checklistCounter = [];
values = [];
constructor() {
this.checklistCounter = Array(this.numCounter).fill(1).map((x, i) => i + 1);
for (let i = 0; i < this.checklistCounter.length; i++) {
let data = {
id: i,
answer:''
}
this.values.push(data);
}
}
addNewTaskOption(){
let data = {
id: (this.values[this.values.length - 1].id + 1),
answer:''
}
this.values.push(data);
}
removeTaskOption(i:number){
this.values.splice(i, 1);
}
以下是一些图片供您参考:
原始UI的图像(在单击添加或删除离子输入行之前):
UI的图像(在第一个离子输入中输入“ abc”后,单击添加按钮:
错误图片:
即使用户在离子输入字段中输入了某些内容,我仍想实现的目标是,如果他们想添加更多字段,这些字段将仅显示在原始字段下方。我已经阅读了其他解决方案,但是所有这些解决方案都订阅了一项服务,而这些解决方案都是针对该解决方案的,因此我认为我无法将其应用于我的案例。请帮忙!
更新:通过遵循@GaurangDhorda的回答设法解决了该问题。
代码:
.html
<ion-item *ngFor="let item of values; let i = index;">
<ion-input formControlName="taskDetail" [value]="item.answer" (change)="setQuantity($event.target.value, i)" type="text"></ion-input>
<ion-icon name="remove-circle" (click)="removeTaskOption(i)" slot="end"></ion-icon>
</ion-item>
.ts(在新方法中添加)
setQuantity(ev:string, i:number){
this.values[i].answer = ev;
}
答案 0 :(得分:1)
其他警告:
被检查为“正确”的答案只是一种错误解决方法,该方法最初是将模板驱动的表单(ngModel
)与反应形式混合在一起。 (formControlName
)不应将其视为解决方案。
1)您可以使用模板驱动形式或反应驱动形式。混合它们并不能提供真实的价值,可以将其视为“代码异味”,并会导致错误(如您所见)。
当您想进行双向绑定时,建议您像在问题初稿中一样使用[(ngModel)]
。但是然后请删除formControlName=taskDetail
。 (无论如何,在taskDetail
中使用相同的formControlName
*ngFor
是错误的)
2)现在有了解决方案,您基本上可以自己手动进行双向绑定。
3)我有两个示例显示您对template driven forms和reactive forms的问题:
模板驱动
使用name
input
上拥有一个独特的ngModel
属性
<form>
<ion-item *ngFor="let item of values; let i = index;">
<ion-input [(ngModel)]="item.answer" type="text" name="answer_{{i}}"></ion-input>
<button (click)="removeTaskOption(i)">Remove</button>
</ion-item>
<button (click)="addNewTaskOption()">Add answer</button>
</form>
活动表格
反应形式带有更多要在组件类中编写的形式。在那里,我们设置了一个FormArray
来保存值:
<form [formGroup]="myForm">
<div formArrayName="taskDetail">
<ion-item *ngFor="let item of taskDetail.controls; let i = index;">
<ion-input [formControlName]="i" type="text"></ion-input>
<button (click)="removeTaskOption(i)">Remove</button>
</ion-item>
</div>
<button (click)="addNewTaskOption()">Add answer</button>
</form>
export class AppComponent {
myForm = new FormGroup({
taskDetail: new FormArray([
new FormControl('value 1'),
new FormControl('value 2')
])
});
get taskDetail() {
return this.myForm.get('taskDetail') as FormArray;
}
addNewTaskOption(){
this.taskDetail.push(new FormControl('value NEWWW'));
}
removeTaskOption(i:number){
this.taskDetail.removeAt(i);
}
...
}
答案 1 :(得分:0)
import socket
socket_args = {'family': socket.AF_INET, 'type': socket.SOCK_STREAM, 'proto': 0}
# ...
# pickle socket_args here
# ...
# load socket_args
socket_object = socket.socket(**socket_args)
答案 2 :(得分:-1)
在生产模式下不会出现以下错误。
或
在ngAfterViewInit()生命周期模式下添加值代码。