Search code examples
angulartypescriptangular-reactive-formsangular11

Error: formGroup expects a FormGroup instance. Please pass one in., core.js:6479 ERROR TypeError: Cannot read properties of undefined (reading 'get')


I am trying to get the details of the employee and then edit it. I am getting the correct values for the details in the detail form, but in the edit, I am not able to get the values in the edit form and get the following errors(provided at the end).

Error: formGroup expects a FormGroup instance. Please pass one in. TypeError:Cannot read properties of undefined (reading 'setValue') TypeError: Cannot read properties of undefined (reading 'get')

The values are being set in the edit form using getFormContent(). This is not working

If anyone could explain me the errors please and point me to the direction. Thank you

export class AddEditEmpPersonalComponent implements OnInit {

  form: FormGroup;
  empOfficialDetails: Employee;
  employeePersonalDetails : EmployeePersonalDetails;
  editMode: boolean = false;
  employeeCreatedOrUpdated : boolean = false;
  formTitle : string;
  successMessage: string;
  employeeId : string;
  selectedFile: File = null;
  url : any;

  constructor(
    private fb: FormBuilder, 
    private employeeService : EmployeeService,
    private route : ActivatedRoute) {
      var id = this.route.snapshot.paramMap.get('id');
      this.employeeId = id;
              
              
      this.employeeService.getEmployeePersonalDetails(this.employeeId)
        .subscribe(data => {
          this.employeePersonalDetails = data;
          if (this.employeePersonalDetails = null)
          {
            alert("create");
            this.editMode = false;
            this.createForm();
            this.formTitle ="Add Employee Personal Details";
            this.successMessage = "Employee Personal Details Added";
            this.employeeCreatedOrUpdated = true;
          }
          else
          {
            alert("edit")
            alert("hi");
            alert(this.employeePersonalDetails.id);
            alert(this.employeePersonalDetails.nationality);
            alert("hello");
            this.editMode = true;
            this.getFormContent();
            this.formTitle ="Update Employee Personal Details";
            this.successMessage = "Employee Personal Details Updated";
            this.employeeCreatedOrUpdated = true;
            //edit
          }
        }
      )
  }

This is the create form

createForm(){
  this.form = this.fb.group({
      
    "id": this.employeeId, // why does this say unknown property
    "fullName": this.empOfficialDetails.firstName+ " " +this.empOfficialDetails.middleName + " " + this.empOfficialDetails.lastName,
    "photo": [''],

    "dateOfBirth": [''],
    "nationality": [''],
    ...........
  })
}

This is the getFormContent() which is supposed to prefill the data in the form for edit

getFormContent(){
  this.form.setValue({ 
    fullName: this.employeePersonalDetails.fullName || '',
    photo:this.employeePersonalDetails.photo || '',
    bankName: this.employeePersonalDetails.bankName || '',
    branch: this.employeePersonalDetails.branch  || '',
    .........
  })
} 

I get proper values when I check in Network

But I am getting The following errors

core.js:6479 ERROR Error: formGroup expects a FormGroup instance. Please pass one in.

      Example:

      
  <div [formGroup]="myGroup">
    <input formControlName="firstName">
  </div>

  In your class:

  this.myGroup = new FormGroup({
      firstName: new FormControl()
  });
    at missingFormException (forms.js:1497)
    at FormGroupDirective._checkFormPresent (forms.js:5520)
    at FormGroupDirective.ngOnChanges (forms.js:5293)
    at FormGroupDirective.rememberChangeHistoryAndInvokeOnChangesHook (core.js:1498)
    at callHook (core.js:2536)
    at callHooks (core.js:2495)
    at executeInitAndCheckHooks (core.js:2446)
    at refreshView (core.js:9480)
    at refreshEmbeddedViews (core.js:10590)
    at refreshView (core.js:9489)
defaultErrorLogger @ core.js:6479
handleError @ core.js:6527
(anonymous) @ core.js:29691
invoke @ zone.js:372
run @ zone.js:134
runOutsideAngular @ core.js:28572
tick @ core.js:29691
(anonymous) @ core.js:29539
invoke @ zone.js:372
onInvoke @ core.js:28673
invoke @ zone.js:371
run @ zone.js:134
run @ core.js:28527
next @ core.js:29538
__tryOrUnsub @ Subscriber.js:183
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:25936
checkStable @ core.js:28595
onHasTask @ core.js:28690
hasTask @ zone.js:426
_updateTaskCount @ zone.js:447
_updateTaskCount @ zone.js:274
runTask @ zone.js:195
drainMicroTaskQueue @ zone.js:582
invokeTask @ zone.js:491
invokeTask @ zone.js:1600
globalZoneAwareCallback @ zone.js:1626

core.js:6479 ERROR TypeError: Cannot read properties of undefined (reading 'get')
    at FormGroupDirective.addControl (forms.js:5346)
    at FormControlName._setUpControl (forms.js:5929)
    at FormControlName.ngOnChanges (forms.js:5874)
    at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.js:1498)
    at callHook (core.js:2536)
    at callHooks (core.js:2495)
    at executeInitAndCheckHooks (core.js:2446)
    at refreshView (core.js:9480)
    at refreshEmbeddedViews (core.js:10590)
    at refreshView (core.js:9489)


core.js:6479 ERROR TypeError: Cannot read properties of undefined (reading 'setValue')
    at AddEditEmpPersonalComponent.getFormContent (add-edit-emp-personal.component.ts:146)
    at SafeSubscriber._next (add-edit-emp-personal.component.ts:58)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
    at SafeSubscriber.next (Subscriber.js:122)
    at Subscriber._next (Subscriber.js:72)


Solution

  • With existing code, the form was not initialized before HTML is rendered.

    form: FormGroup;
    

    The form instance is only created after the employeeService returns Observable.

    this.employeeService
          .getEmployeePersonalDetails(this.employeeId)
          .subscribe((data) => {
            this.employeePersonalDetails = data;
            if ((this.employeePersonalDetails = null)) {
              ...
              this.createForm();
              ...
            } else {
              ...
              this.getFormContent();
              ...
            }
          });
    

    Solution

    You have to instantiate the form as first before HTML is rendered.

    .component.ts

    constructor(
      private fb: FormBuilder,
      private employeeService: EmployeeService,
      private route: ActivatedRoute
    ) {
      var id = this.route.snapshot.paramMap.get('id');
      this.employeeId = id;
    
      this.initForm();
    
      this.employeeService
        .getEmployeePersonalDetails(this.employeeId)
        .subscribe((data) => {
          ...
        });
    }
    
    initForm() {
      this.form = this.fb.group({
        id: ['']
        fullName: [''],
        photo: [''],
    
        dateOfBirth: [''],
        nationality: [''],
      });
    }
    

    Sample Demo on StackBlitz

    Note:

    Would suggest moving all the initialization works to ngOnInit() method as suggested by @PardeepJain's answer on Difference between Constructor and ngOnInit.