Bhr*_*jni 5 angular angular-reactive-forms
您好,我使用反应式表单将对象数组绑定到 formArray,但在这里,如果我选择一个部分中的任何一项,然后单击“向右移动/向左移动”,则整个对象已从一个部分移动到另一部分。但该功能工作正常,但我无法检测到 form.valuechanges() 中从一个部分到其他部分所做的更改。任何人都可以帮助我检测更改,以防项目已从一个部分移动到另一部分,在这里我想要更改检测,但功能必须按原样工作,我的意思是整个对象从一个部分移动到另一部分。
提前致谢。
我这里有工作 demo2,我希望我之前发布的 demo1 能够像这个 demo2 一样工作,并且 formarray 工作。 演示2
演示: 演示 1
TS:
private settingsGroupInfoForm() {
if (!this.agentDetailsList) {
// Add
this.agentGroupViewInfoForm = this.FB.group({
agentGroupView: this.FB.array(
this.agentInView.map(x=>(x))
),
})
} else {
// Edit
if (this.agentDetailsList) {
this.agentGroupViewInfoForm = this.FB.group({
agentGroupView: this.FB.array(this.agentInView.map(x=>(x))),
})
}
this.agentGroupViewInfoForm.valueChanges.subscribe(data => {
this.formEdit = true;
console.log('agentGroupViewInfoForm', this.formEdit)
})
}
}
Run Code Online (Sandbox Code Playgroud)
HTML:
<div class="card-body overflow-auto py-0" *ngIf="agentGroupViewInfoForm"
[formGroup]="agentGroupViewInfoForm">
<ul class="list-group list-group-flush" *ngFor="let child of agentInView" name="agentInGroup" formArrayName="agentGroupView">
<li class="list-group-item {{isInActiveItems(child) ? 'active' : ''}}" (click)="toggleActiveItem(child)">
{{child.value}}
</li>
</ul>
</div>
Run Code Online (Sandbox Code Playgroud)
与 Angular 中几乎所有基于组件的问题一样,您应该首先考虑模型。你的模型是王道,其他一切都是围绕它构建的。
在您的演示中,您正在列表之间移动项目。您正在更新模型并将 HTML 绑定到该模型。没有什么问题——这是正确的方法并且有效。
这里的额外挑战是您还想移动组。我们仍然需要考虑模型优先,但也要考虑在列表之间移动项目的同时移动相关状态。
简而言之,您目前拥有
list1: [];
selected1: [];
list2: [];
selected2: [];
Run Code Online (Sandbox Code Playgroud)
如果您想将项目从 1 -> 2 移动,您的移动方法将从items1到 中删除所有选定的项目items2。简单的。
添加表单后,您将拥有如下结构:
list1: [];
selected1: [];
form1: FormGroup;
formArray1: FormArray;
list2: [];
selected2: [];
form2: FormGroup;
formArray2: FormArray;
Run Code Online (Sandbox Code Playgroud)
当您将项目从 1 -> 2 移动时,您将继续将项目从 移动list1到list2,但现在您还需要从 中删除相关项目formArray1并将其添加到formArray2。
我存储了对表单数组的引用,以便以后更容易使用它们。
使用表单数组可以说是这个答案中最复杂的部分。表单数组的关键是 HTML 结构模仿FormGroup您构建的对象的结构。
我们可以使用FormBuilder数组构建表单并绑定到它,如下所示:
组件.ts
buildForm() {
this.model = [
{ value: 'a' }, { value: 'b' }, { value: 'c' }
];
// create a form group for each item in the model
const formGroups = this.model.map(x => this.formBuilder.group({
value: this.formBuilder.control(x.value)
}));
// create a form array for the groups
const formArray = this.formBuilder.array(formGroups);
// create the top-level form
this.form = this.formBuilder.group({
array: formArray
});
}
Run Code Online (Sandbox Code Playgroud)
并像这样在 HTML 中绑定它:
<form [formGroup]="form1" (submit)="onSubmit()">
<div formArrayName="array">
<div *ngFor="let item of list1; let i = index" [formGroupName]="i">
<input formControlName="value" />
</div>
</div>
<button>Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)
这将为数组中的每个项目生成一个输入,分别包含值“a”、“b”、“c”。
在数组之间移动项目是一个简单的 JavaScript 问题。我们需要splice源数组和push目标数组。
要将项目从列表 1 移动到列表 2:
// move selected items from model 1
this.selected1.forEach(item => {
const index = this.list1.indexOf(item);
this.list1.splice(index, 1);
this.list2.push(item);
});
this.selected1.length = 0;
Run Code Online (Sandbox Code Playgroud)
这将循环遍历列表 1 中的每个选定项,将其从列表中拼接出来,然后将其推送到列表 2。然后它会清除选定的项;
您将在移动项目的同时移动表单组。它在概念上是相似的——从一个中删除并添加到另一个中。您根据模型构建了表单数组,因此您知道索引匹配。
// move selected items from model 1
this.selected1.forEach(item => {
const index = this.list1.indexOf(item);
const formGroup: FormGroup = this.formArray1.controls[index] as FormGroup;
this.list1.splice(index, 1);
// move between form arrays
this.formArray1.removeAt(index);
this.formArray2.push(formGroup);
this.list2.push(item);
});
Run Code Online (Sandbox Code Playgroud)
请注意此处有 2 条线用于在表单数组之间移动,它们看起来与用于在常规数组之间移动的 2 条线类似。
formArray.removeAt(index)并formArray.push(formGroup)正在搬家。与表单数组的区别在于,我们需要首先使用 来获取对它的引用this.formArray1.controls[index] as FormGroup;。
演示: https: //stackblitz.com/edit/angular-3cwnsv
警告
在此设计中,从数组和表单中删除以及添加到数组和表单的顺序很重要。您将 HTML 绑定到数组和表单。您通过循环数组来创建输入数组,并将每个项目绑定到i表单数组中的第 th 组。如果您先从表单中删除,则现在n数组中将包含项目,n - 1表单数组中将包含项目。尝试绑定到未定义的n表单组时,您将遇到错误。
您现在正在执行包含多个操作的事务。
除了确保按正确的顺序删除和添加之外,解决此问题的一种方法是使用OnPush更改检测。请仔细阅读本文,因为对于除最简单的应用程序之外的所有应用程序来说,这都是一个很好的策略。
为了回答的目的,我让我的演示保持简单。它的可扩展性或可重用性并不特别好。有很多重复的代码和错误的命名,试图避免被与应用程序相关的嵌套组件和属性名称分散注意力。
实际上,您可能想要创建一个子组件来负责我复制的许多代码。其设计绝对超出了这个问题的范围。
| 归档时间: |
|
| 查看次数: |
17343 次 |
| 最近记录: |