0

I am not able to create dynamically form control when I get a data. and the value in particular formControl like task and template name . Thanks in advance.

{
  "items": [
    {
      "templatename": "Defult",
      "tasks": [
        "task-1",
        "task-2 ",
        "task-3",
      ]
    },
    {
      "templatename": "Eccormce",
      "tasks": [
        "task-1 ",
        "task-2",

      ]
    },
    {
      "templatename": "co-oprate",
      "tasks": [
        "task-1",
        "task-2",
        "task-3"
      ]
    }
  ]
}

2 Answers 2

2

What I suggest you is to iterate over your json values and then create the different controls.

On your initialisation you can create the first FormArray, then you get it and push in it all the items of your json, and finally do the same for your other FormArray which represent your tasks

ngOnInit(){
  const items = this.json.items
  this.form = new FormGroup({
    items : new FormArray([])
  })
  let itemsForm = (<FormArray>this.form.get('items'))
  for (let i = 0; i < items.length; i++){
    itemsForm.push(this.initItem(items[i]))
  } 
}

initItem(item){
  let itemGroup = new FormGroup({
    templatename : new FormControl(item.templatename),
    tasks : new FormArray([])
  })
  let tasksItem = (<FormArray>itemGroup.get('tasks'))
  for (let i = 0; i < item.tasks.length; i++){
    tasksItem.push(new FormControl(item.tasks[i]))
  }
  return itemGroup;
}

Of course this is two times the same iteration, just the FormArray and what you put in it change so you can factorize it in a single method probably, but here is just to show you how you can do nested FormArray

Here is a working stackblitz where you can test the example

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

2 Comments

your code is good, but you can improve a bit using map to create the forms and using auxiliars function. This help you to add items and task (sorry if I had step on your toes with my answer)
@Eliseo yes using map is probably much more better, as you do in your solution. By auxiliar do you mean just to use more method and to not do the job in a bigger one ? No prob, we are here to help people, so if your solution is better, it's better to use it ^^
1

The process to create a FormArray of FormArrays is equal that other. The only is take account how referred to the formArrays. So, first create two auxiliar functions

//it's a typical getter
//if you manage the formArray directly it's not necesary(*)
get itemsArray()
{
    return this.form.get("items") as FormArray
}

//see that this function is NOT a getter -has as argument an index-
getTasks(index:number)
{
    this.itemsArray.at(index).get('tasks') as FormArray
}

And, in case the outer formArray a typical function that return a formGroup

setItemsArray(data: any = null): FormGroup {
    data = data || { templatename: null, tasks: null };
    return new FormGroup({
      templatename: new FormControl(data.templatename, Validators.required),
      tasks: data.tasks
        ? new FormArray(data.tasks.map(x => new FormControl(x)))
        : new FormArray([])
    });
  }

So, we can create the formArray using

const items=new FormArray(alldata.map(x=>this.setItemsArray(x))

Now, we are ready to mannage the formArray

<form  [formGroup]="form">
    <div formArrayName="items">
        <div *ngFor="let group of itemsArray.controls;let i=index"
                      [formGroupName]="i">
           <!--here we has a inner formGroup--->
           <input formControlName="templatename">
           <div formArrayName="tasks">
                <div *ngFor="let control of getTasks(i).controls;let j=index">
                      <input [formControlName]="j">
                </div>
           </div>
        </div>
    </div>
</form>

BONUS:

To add/remove a new task in a position it's only

addTask(index:number)
{
    this.getTask(index).push(new FormControl())
}
removeTask(index:number,indexTask:number)
{
    this.getTask(index).removeAt(indexTask)
}

To add/remove a item

addItem()
{
    this.itemsArray.push(this.setItemsArray())
}
removeItem(index:number)
{
    this.itemsArray.removeAt(index)
}

(*)If you want, you can also mannage teh formArray standalone -not in a FormGroup-

if you define directly

this.formArray=new FormArray(alldata.map(x=>this.setItemsArray(x))

And change the function getTasks(index) by

getTasks(index)
{
    return this.formArray.at(i).get('tasks') as FormArray
}

You can use a form like

<form  [formGroup]="formArray">
    <div *ngFor="let group of formArray.controls;let i=index"
                  [formGroupName]="i">
       <!--here we has a inner formGroup--->
       <input formControlName="templatename">
       <div formArrayName="tasks">
            <div *ngFor="let control of getTask(i).controls;let j=index">
                  <input [formControlName]="j">
            </div>
       </div>
    </div>
</form>

You can see a stackblitz

2 Comments

Thanks for your time but problem is that is I get different JSON but I want to convert after that Patch My get JSON is Like { "data":{ "id": 10, "Default":[ "Task 1 ", "Task 2", "Task 3" ], "E-commerce":[ "Task 1", "Task 2", "Task 3" ], "Corporate":[ "Task 1" ] }, "message": "success", "status": 200 }
Then, you can "transform" your data using data.tasks=[data.Default,data['E-comerce'],data.Corporate] or simply use a FormGroup with three FormsArrays

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.