Kravitz
Kravitz

Reputation: 2859

Angular 5 formBuilder - Nested Array and For loop

Im working on a profile editing page in an ionic app everything works as fine with all the top level items of the users profiles info (name, email, sex etc..)

I have hobbies stored in an array off this main json node (using Firestore) so its 1 level deep off the main node..

I cant seem to figure out how to use form builder with it. I suspect I am going wrong on 2 points, 1 being how I am using formbuilder and 2 on the merge fuction as it doesnt take into account nested structures which I am also unsure how to approach.. any help would be awesome.

  _buildForm() {

    this.form = this.formBuilder.group({
      displayName: [this.options.displayName] || '',
      dob: [this.options.dob] || '',
      sex: [this.options.sex] || '',
      city: [this.options.city] || '',
      country: [this.options.country] || '', 
      bio: [this.options.bio] || '',   
      hobbies: this.formBuilder.group( this.options.hobbies )  
    });

    // Watch the form for changes, and
    this.form.valueChanges.subscribe((v) => {
      this.merge(this.form.value);
    });
  }  


  merge(settings: any) {

    for (let k in settings) {
      this.settings[k] = settings[k];
    }
    return this._save();
  }


  _save() {
     // this function then save the data back to firestore using a simple update of the entire json output
  }

Upvotes: 1

Views: 1068

Answers (1)

Sachin
Sachin

Reputation: 2765

You need these

 _buildForm() {
    this.form = this.formBuilder.group({
      displayName: [this.options.displayName] || '',
      dob: [this.options.dob] || '',
      sex: [this.options.sex] || '',
      city: [this.options.city] || '',
      country: [this.options.country] || '', 
      bio: [this.options.bio] || '',   
      hobbies: this.formBuilder.group([])  
    });
    if(this.options.hobbies.length>0){
      this._setHobbiesForm(this.options.hobbies);
    }
  }  

  //To build the hobby gorm
  _buildHobbyForm(hobby) {
    var hobbyForm = this.fb.group({
      Name: hobby.Name||''
    });
    return hobbyForm ;
  }

  //To attach the hobbies form with data back to main form
  _setHobbiesForm(hobbies) {
    const hobbiesFGs = hobbies.map(hobby=> this._buildHobbyForm(hobby));
    const hobbiesFR = this.fb.array(hobbiesFGs);
    this.form.setControl('hobbies', hobbiesFR);
  }

 //To get form values for saving
 _prepareSaveInfo(){
    const formModel = this.form.value;
    //deep copy of hobbies
    const hobbiesDeepCopy= formModel.hobbies.map(
      (hobby) => Object.assign({}, hobby)
    );
    const profile={
      displayName: formModel.displayName as string,
      sex: formModel.sex as string,
      dob: formModel.dob as string,
      city: formModel.city as string,
      country: formModel.country as string,
      hobbies:hobbiesDeepCopy
    }
    return profile;
  }

  _save() {
    let dataToSave=this._prepareSaveInfo();
    console.log(dataToSave);
  }

This is the way to handle array inside forms in angular , if it doesn't fits your code logic exactly , take it as a example and build your logic from it , definitely this example will help you .

Iam posting an example for html also here (basically to show how to handle arrays inside the form in html)

<div formArrayName="hobbies">
    <div *ngFor="let hobby of form.get('hobbies').controls; let i=index" [formGroupName]="i">
    <!-- your code for hobby-->
    </div>
</div>

Upvotes: 1

Related Questions