1

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
  }
1
  • Can you reproduce this problem in stackblitz? I'm having trouble understanding the question. What is your intention with the merge method? Commented Jan 19, 2018 at 18:42

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

2 Comments

I have not tried this but it looks great so I will accept it as the answer.. it will for sure help me figure it out
Epic Answer!! just checked it there and had to change very little.. top work man

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.