简体   繁体   中英

Angular 2+ formgroup setValue in child component form from parent

I have a form component that I want to share between an add member component and an edit member component. Everything works fine if I put the form code in each component but, well, I don't want to be banned from coding forever because my code isn't DRY. I'm new at coding.

The problem to be solved is this message in my IDE, Webstorm:

Property 'setValue' does not exist on type 'AddEditFormComponent'.

This message comes from the parent component EditMemberComponent. First I'll present the form code that I'm trying to share between the edit and add components.

This is the child component, the basic form:

add-edit-form.component.ts

import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';

@Component({
selector: 'app-add-edit-form',
templateUrl: './add-edit-form.component.html'
})

export class AddEditFormComponent implements OnInit {

  addEditMemberForm: FormGroup;

  constructor(
    private fb: FormBuilder
  ) { }

  ngOnInit() {
    this.createForm();
  }

  createForm() {
    this.addEditMemberForm = this.fb.group({
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      mainSkillTitle: ['', Validators.required],
      mainSkills: ['', Validators.required],
      otherSkills: ['', Validators.required],
      links: ['', Validators.required],
      country: ['', Validators.required]
    });
  }
}

With a little Angular Material 2 styling the form looks good.

This is the problem parent component:

edit-member.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

import { MembersAdminService } from './member-admin.service';
import { Member } from './member-admin.model';
import { AddEditFormComponent } from './add-edit-form.component';

@Component({
  selector: 'app-edit-member',
  templateUrl: './edit-member.component.html'
})

export class EditMemberComponent implements OnInit {

  private memberId: string;
  private memberData;
  private addEditMemberForm: AddEditFormComponent;

  constructor(
      private membersAdminService: MembersAdminService,
      private successService: SuccessService,
      private route: ActivatedRoute,
      private router: Router
  ) {}

  ngOnInit() {
    this.fetchMember();
  }

  fetchMember() {
    this.route.params.forEach((urlParameters) => {
      this.memberId = urlParameters['id'];
      console.log(this.memberId); // Perfect
    });

    // Display the data retrieved from the data model to the form model.
   this.membersAdminService.getMemberById(this.memberId)
      .subscribe(dataLastEmittedFromObserver => {
          this.memberData = dataLastEmittedFromObserver;
          console.log(this.memberData);  // This works fine.  Now to post to form...

          this.addEditMemberForm.setValue({ // HERE IS THE PROBLEM
            firstName: this.memberData.firstName,
            lastName: this.memberData.lastName,
            mainSkillTitle: this.memberData.mainSkillTitle,
            mainSkills: this.memberData.mainSkills,
            otherSkills: this.memberData.otherSkills,
            links: this.memberData.links,
            country: this.memberData.country
          })
      });
   }

}

I expected this line to bring all the form code into the parent:

private addEditMemberForm: AddEditFormComponent;

Along with this import I expected .setValue to be available in the parent to the addEditMemberForm property. I expected setValue to populate the child form with the member data so I can edit it. That isn't happening and I suspect I have an incomplete mental map of how this works.

Help is appreciated of course!

To get hold of AddEditFormComponent i would use @ViewChild

import { ViewChild } from '@angular/core';

...
@ViewChild(AddEditFormComponent)
private addEditMemberComponent: AddEditFormComponent;

and then we can write

this.addEditMemberComponent.addEditMemberForm.setValue({ // THIS SHOULD WORK
  ...

yurzui's response is very good and helped me go in the right direction. There are a variety of ways of getting data in and out of forms and for my app the @ViewChild is the best option.

However, I still couldn't get data into the form and it was crashing when I tried. My comments above reflect that struggle.

The final part of the answer is that I can not use ngOnInit() in the parent class. I must use this life cycle hook:

ngAfterViewInit() {

  this.fetchMember();
}

This issue is that the form needed time to render before trying to load data. Dah! :-) Hope all this helps some other lost puppy. The other issue is that I'm going to have to figure out how to use Plunker someday. So much to learn on my first app!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM