0

I came across the following Stackblitz demo :

https://stackblitz.com/edit/angular-dffny7?file=app

with reference to the below post: https://stackoverflow.com/a/48527939/7429196

Now suppose I have the following JSON

{
 "companies": [
  {
   "company": "ABC",
   "projects": [
     {
     "projectName": "DEF"
     },
     {
     "projectName": "GHI"
     }
    ]
   },
   {
    "company": "JKL",
    "projects": [
     {
     "projectName": "MNO"
     }
   ]
  }
 ]
}

coming from following service:

getCompanies() : Observable<Organization>{
return this.http.get(url).map((response: Response)=> response.json())}

and the Organization class is as following :

export class Organization{
public company: String;
public projects : Project[];
}
export class Project{
public projectName : String;
}

I have the above JSON data in the object of Organization class in my component file and I want to render this data in the form fields in the html file. I tried binding the data using ngModel but read it somewhere that ngModel cannot be used in a model-driven form. How can I achieve it?

Random Guy
  • 51
  • 1
  • 12
  • [The Stack Overflow answer you referenced](https://stackoverflow.com/a/48527939/4877269) seems to cover everything you need, from setting up the `FormGroup` to pre-populating the form with data from the service to rendering the form HTML dynamically. Where specifically are you getting stuck, and do you have any already-written code you can share? – Alex Peters Sep 23 '18 at 13:07

1 Answers1

0

@Random Guy, the key to pass data from json to a FormBuilder is using the "map" method of arrays. But At first, please use HttpClient NOT the old and deprecated http (so, you needn't use this ugly map((response: Response)=> response.json())}

Well, you import in constructor the formBuilder

constructor (private fb:FormBuilder){}

And make a function that receive as argument your json or null and return a fromGroup

  createForm(data: any): FormGroup {
    return this.fb.group({
      //id data.companies, we create a formArray
      companies: data ? this.fb.array(this.createGroupProjects(data.companies)) : []
    })
  }
  //return an array of FormGroups
  createGroupProjects(companies: any[]): FormGroup[] {
    //with each element in companies
    return companies.map(c => {
      //create a formGroup
      return this.fb.group({
        company: c.company,
        //projects will be a form array too
        projects: this.fb.array(this.createProjects(c.projects))
      })
    })
  }
  //return an array of FormGroups
  createProjects(projects: any[]): FormGroup[] {
    //with each project
    return projects.map(p => {
      //return a FormGroup
      return this.fb.group({
        projectName: p.projectName
      })
    })
  }

Of course you can use only a function

  createForm(data: any): FormGroup {
    return this.fb.group({
      //in "companies" if data.companies, we return a FormArray
      //with each element of data.companies we return a formGroup
      companies: data ? this.fb.array(data.companies.map(c => {
        return this.fb.group({
          company: c.company,
          //the propertie projects will be another FormArray
          //with each element in projects
          projects: this.fb.array(c.projects.map(p => {
            //return a formGroup
            return this.fb.group({
              projectName: p.projectName
            })
          }))
        })
      }))
        //If data=null, you return an array
        : []
    })
  }

See that yours FormArray are created using this.bt.array(...a formGroup array...), and this formGroupArray is created using "map".

Eliseo
  • 29,422
  • 4
  • 13
  • 37