-1

I have attached my code link. I tried create dynamic nested tree format form array. But I don't know how to create. I am new in angular framework. https://stackblitz.com/edit/angular-vytk36?file=src/index.html

9
  • Post your code here. Commented Apr 19, 2023 at 13:45
  • That's a lot of code. It would be better to add the part that is causing you trouble to the question. Commented Apr 19, 2023 at 14:53
  • You want to create a FormArray of a FormAray, see this SO or this another one Commented Apr 19, 2023 at 14:53
  • @Eliseo I am trying to data structures tree format form array. It is possible to create using angular form array? Commented Apr 20, 2023 at 5:49
  • 1
    @Arunkumar, sure! (impossible is nothing) but it's a bit complex. I just added an answer. I hope can help Commented Apr 21, 2023 at 6:44

2 Answers 2

2

Always we have a "infinite level" is work to make a "recursive component"

A recursive component is only a component that call itself (see e.g. this SO)

Mannage a child component that mannage a formGroup from parent it's not very easy. We can use viewProviders or pass the FormGroup in an input (see this another SO)

We are going to choose pass the formGroup. But as our component is a recursive component we need in witch formGroup we are, so I use another input that it's the "name" of the formGroup. (remember that our formArrays are formArrays of formGroups. We need "reach" the formGroup

Puff...!

Before we are going to define a function to create the formGroup. We are export it because the same function can be used by the parent and by the component

export function setNestedMenu(data:any=null){
  data=data || {name: "",displayname: "",id: "",nestedMenu: []}
  return new FormGroup({
      name:new FormControl(data.name),
      displayName:new FormControl(data.name),
      id:new FormControl(data.name),
      nestedMenu:new FormArray(data.nestedMenu.map((x:any)=>this.setNestedMenu(x)))
  })
}

NOTE: I use camelCase to give value to the "properties"

The component

@Component({
  selector: 'form-component',
  standalone: true,
  imports: [CommonModule, FormsModule, ReactiveFormsModule],
  template: `
  <div [style.margin-left.px]="index*10" *ngIf="formGroup" [formGroup]="formGroup" >
  <div formArrayName="nestedMenu">
     <button (click)="addMenu()">add</button>
     <div *ngFor="let group of menuArray?.controls;let i=index" 
                                          [formGroupName]="i">
       <input formControlName="id"/>
       <input formControlName="name"/>
       <input formControlName="displayName"/>
       <button (click)="removeMenu(i)">remove</button>
       <button (click)="addSubMenu(i)">add submenu</button>
       <ng-container *ngIf="getSubMenuArray(i).length">
         <!--here we call again to our component-->
          <form-component [form]="form" 
                          [name]="name+'.'+i+'.nestedMenu'" 
                          [index]="index+1" ></form-component>
       </ng-container>
     </div>
  </div>
  </div>`,
})
export class FormMenuComponent  {
  _index:number=0;
  formGroup:FormGroup
  @Input() form: FormGroup;
  @Input() name:string="nestedMenu";
  @Input('index') set _(value:number){
    this._index=value;
    this.formGroup=(value?this.form.get(this.name).parent:this.form) as FormGroup
  }

  get index()
  {
    return this._index
  }
  get menuArray() {
    return this.form?this.form.get(this.name) as FormArray:null;
  }
  getSubMenuArray(index:number){
    
    return this.form.get(this.name+'.'+index+'.nestedMenu') as FormArray
  }
  
 addMenu()
 {
   this.menuArray.push(setNestedMenu())
 }
 addSubMenu(index:number)
 {
   this.getSubMenuArray(index).push(setNestedMenu())
 }
 removeMenu(index:number)
 {
  this.menuArray.removeAt(index)
 }
}

See how pass the name, the form and the index variables

Our main.component simply

<form-component [form]="form" [index]="0"></form-component>

form: FormGroup=new FormGroup({
    nestedMenu:new FormArray([setNestedMenu()])
  })

See stackblitz

NOTE: sorry for self quoting

Sign up to request clarification or add additional context in comments.

3 Comments

I have tried modification some customize. But I got some issue. stackblitz.com/edit/angular-pezmpp?file=src/form.component.ts Please help me
i have add extra submenu array in this form. But i got issue Please help me. I have attached code URL. I don't know how to fix this error. stackblitz.com/edit/angular-pezmpp?file=src/form.component.ts
@Arunkumar, sorry for the delay (I was very busy the last week). I added a new answer that I hope can help
0

The before answer pass to the form two variables: the "form" and the "name" of the formArray. This complicate the component. There're another better aproach that it's pass the "formGroup".

The first is that our component has an "setter" input like

  formGroup:FormGroup
  @Input('form') set __(value:AbstractControl){
    this.formGroup=value as FormGroup
  }

(It's necessary to "cast" the control)

Now we can use some like

<div *ngIf="formGroup" [formGroup]="formgroup">
  ...
  <div formArrayName="nestedMenu">
     <div *ngFor="let group of nestedMenuArray?.controls;let i=index"
                [formGroupName]="i">
        ...
        <ng-container *ngIf="getNestedMenuArray(i)?.length">
          <!--see we pass as form the "formGroup"-->
          <form-component [form]="nestedMenuArray.at(i)"  [index]="index+1" >
          </form-component>
        </ng-container>
     </div>
  </div>

  get nestedMenuArray() {
     return this.formGroup?this.formGroup.get('nestedMenu') as FormArray:null;
  }

  getNestedMenuArray(index:number){
    return  this.nestedMenuArray?this.nestedMenuArray.at(index) as FormArray:null
  }

stackblitz

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.