如何根据 Angular 响应式表单重新分配嵌套数组键?
How to reassign the nested array keys based on Angular Reactive Forms?
我正在努力为 Angular 响应式表单重新创建嵌套数组。
现有嵌套数组。
nestedArray = [{
id:'abc',
required:true,
children:[{
id:"bcd",
parentId:"abc",
required:true,
children:[{
id:"cde",
parentId:"bcd",
required:false,
children:[{
id:"def",
parentId:"cde",
required:true,
children:[{
id:"efg",
parentId:"def",
required:false,
}]
},
{
id: "xyz",
parentId: "cde",
required: true,
}]
}]
}]
}]
为 Angular 反应形式重新创建此数组
nestedArray= this.fb.group({
abc: [''],
bcd: this.fb.group({
cde: [''],
efg: [''],
}),
});
以上数组不正确,正在寻找以 Angular 反应形式创建子项的正确方法。
谢谢
下面只是一个伪代码,但您需要迭代并创建最终的键值对象以获得类似的结构...
无论如何,有一些工具可以解决类似的问题,考虑一下:https://jsonforms.io/ - 我会先考虑这些。
function patch (array: any[]): any {
let res: any = {};
for (let a of array) {
res[a.id] = a;
if (a.children && a.children.length) res[a.id]['children'] = patch(a.children)
}
return res;
}
您需要创建一个递归函数 return 一个 FormControl 或一个 FormGroup
form = new FormArray(this.nestedArray.map(x=>{
const group=new FormGroup({})
group.addControl(x.id,this.getGroup(x))
return group
}));
getGroup(data: any) {
if (!data.children)
return new FormControl()
const group = new FormGroup({});
if (data.children) {
data.children.forEach(x=>{
group.addControl(x.id,this.getGroup(x))
})
}
return group;
}
Update 确实答案是错误的,因为我们没有对“parents”的表单控制。函数必须像
form = new FormArray(this.nestedArray.map(x=>this.getGroup(x)))
getGroup(data: any) {
if (!data.children)
{
return new FormControl)
}
const group = new FormGroup({});
group.addControl(data.id,new FormControl())
if (data.children) {
data.children.forEach(x=>{
group.addControl(x.id,this.getGroup(x))
})
}
return group;
}
嗯,问题是如何控制这种疯狂的形式。我们可以尝试创建一个“递归模板”,但我认为另一种方法更好。假设您有一组元素,每个元素都具有三个属性:“索引”、“标签”和“控件”。而control是对我们窗体的FormControl的引用。然后我们可以构造一个 .html like
<div *ngFor="let item of controls">
<span [style.margin-left]="item.index*10+'px'">{{item.label}}</span>
<input [formControl]="item.control">
<span *ngIf="item.control.errors?.required">*</span>
</div>
容易不?直接使用 [formControl]
和 item.control.errors
或 item.control.touched
嗯,为此先声明一个空数组
controls:any[]=[];
并更改功能,因此我们分两步添加组:1.-创建 formControl,2.-添加到组,第三步是将 object 与 {label ,控制和“指数”}。好吧,当我们有一个递归函数想知道递归的“索引”时,这很典型。
//we pass as index 0 at first
form = new FormArray(this.nestedArray.map(x=>this.getGroup(x,0)))
getGroup(data: any,index:number) {
if (!data.children)
{
//create the control
const control=new FormControl('',data.required?Validators.required:null)
//add to the array this.controls
this.controls.push({control:control,label:data.id,index:index})
//return control
return control
}
const group = new FormGroup({});
index++
//create the control
const control=new FormControl('',data.required?Validators.required:null)
//add to the array this.controls
this.controls.push({control:control,label:data.id,index:index})
//add the control to the group
group.addControl(data.id,control)
if (data.children) {
data.children.forEach(x=>{
group.addControl(x.id,this.getGroup(x,index++))
})
}
return group;
}
好吧,在 stackblitz 中,将 属性“值”添加到我们的复合体 object,以展示如何做到这一点,我们将“id”用作“标签”-perhafs复杂 object 需要一个新的 属性 标签-
我正在努力为 Angular 响应式表单重新创建嵌套数组。
现有嵌套数组。
nestedArray = [{
id:'abc',
required:true,
children:[{
id:"bcd",
parentId:"abc",
required:true,
children:[{
id:"cde",
parentId:"bcd",
required:false,
children:[{
id:"def",
parentId:"cde",
required:true,
children:[{
id:"efg",
parentId:"def",
required:false,
}]
},
{
id: "xyz",
parentId: "cde",
required: true,
}]
}]
}]
}]
为 Angular 反应形式重新创建此数组
nestedArray= this.fb.group({
abc: [''],
bcd: this.fb.group({
cde: [''],
efg: [''],
}),
});
以上数组不正确,正在寻找以 Angular 反应形式创建子项的正确方法。
谢谢
下面只是一个伪代码,但您需要迭代并创建最终的键值对象以获得类似的结构...
无论如何,有一些工具可以解决类似的问题,考虑一下:https://jsonforms.io/ - 我会先考虑这些。
function patch (array: any[]): any {
let res: any = {};
for (let a of array) {
res[a.id] = a;
if (a.children && a.children.length) res[a.id]['children'] = patch(a.children)
}
return res;
}
您需要创建一个递归函数 return 一个 FormControl 或一个 FormGroup
form = new FormArray(this.nestedArray.map(x=>{
const group=new FormGroup({})
group.addControl(x.id,this.getGroup(x))
return group
}));
getGroup(data: any) {
if (!data.children)
return new FormControl()
const group = new FormGroup({});
if (data.children) {
data.children.forEach(x=>{
group.addControl(x.id,this.getGroup(x))
})
}
return group;
}
Update 确实答案是错误的,因为我们没有对“parents”的表单控制。函数必须像
form = new FormArray(this.nestedArray.map(x=>this.getGroup(x)))
getGroup(data: any) {
if (!data.children)
{
return new FormControl)
}
const group = new FormGroup({});
group.addControl(data.id,new FormControl())
if (data.children) {
data.children.forEach(x=>{
group.addControl(x.id,this.getGroup(x))
})
}
return group;
}
嗯,问题是如何控制这种疯狂的形式。我们可以尝试创建一个“递归模板”,但我认为另一种方法更好。假设您有一组元素,每个元素都具有三个属性:“索引”、“标签”和“控件”。而control是对我们窗体的FormControl的引用。然后我们可以构造一个 .html like
<div *ngFor="let item of controls">
<span [style.margin-left]="item.index*10+'px'">{{item.label}}</span>
<input [formControl]="item.control">
<span *ngIf="item.control.errors?.required">*</span>
</div>
容易不?直接使用 [formControl]
和 item.control.errors
或 item.control.touched
嗯,为此先声明一个空数组
controls:any[]=[];
并更改功能,因此我们分两步添加组:1.-创建 formControl,2.-添加到组,第三步是将 object 与 {label ,控制和“指数”}。好吧,当我们有一个递归函数想知道递归的“索引”时,这很典型。
//we pass as index 0 at first
form = new FormArray(this.nestedArray.map(x=>this.getGroup(x,0)))
getGroup(data: any,index:number) {
if (!data.children)
{
//create the control
const control=new FormControl('',data.required?Validators.required:null)
//add to the array this.controls
this.controls.push({control:control,label:data.id,index:index})
//return control
return control
}
const group = new FormGroup({});
index++
//create the control
const control=new FormControl('',data.required?Validators.required:null)
//add to the array this.controls
this.controls.push({control:control,label:data.id,index:index})
//add the control to the group
group.addControl(data.id,control)
if (data.children) {
data.children.forEach(x=>{
group.addControl(x.id,this.getGroup(x,index++))
})
}
return group;
}
好吧,在 stackblitz 中,将 属性“值”添加到我们的复合体 object,以展示如何做到这一点,我们将“id”用作“标签”-perhafs复杂 object 需要一个新的 属性 标签-