3gwebtrain
3gwebtrain

Reputation: 15303

Angular Dynamic Reactive Form `Error: Cannot set properties of undefined (setting 'value')`

In my reusable form component I am getting following error:

Error: Cannot set properties of undefined (setting 'value')

I have created a form with json schema, when user required to update the form from app component, I am trying to update the schema what is sent.

here i am finding 2 errors.

  1. on submit form clears itself
  2. my update is not working

getting above error. aswell initial value not able to editted.

please help me to understand the issue.

If my approach is wrong, please let me know the correct approach to create and handle the schema based form.

thanks in advance.

Live Demo

Upvotes: 0

Views: 671

Answers (1)

Naren Murali
Naren Murali

Reputation: 58602

You can use patchValue to load the values into the form, I didnt get the form clearing issue at all and for refresh I used viewChild and called a reload method to sync the form with the schema.

app.com.ts

import { Component, VERSION, ViewChild } from '@angular/core';
import {
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from '@angular/forms';
import { FormSchema } from './form.schema';
import { SharedForm } from './shared/shared.form';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  @ViewChild('sharedForm') sharedForm: SharedForm;
  name: string;
  details = { name: 'chennai' };
  newFormSchema;
  constructor() {
    this.newFormSchema = FormSchema;
  }

  update() {
    this.details = { name: 'sholing' };
  }

  formSubmited(formValue) {
    const update = formValue;
    console.log('formValue', formValue);
    this.newFormSchema = this.newFormSchema.map((item) => {
      item.value = update[item.name] + new Date();
      return item;
    });
    this.sharedForm.reloadForm();
  }
}

app.com.html

<h1>Original the Form</h1>

<shared-form
  #sharedForm
  [schema]="newFormSchema"
  (userFormOnSubmit)="formSubmited($event)"
></shared-form>

<h1>Update the Form</h1>
<!-- 
<shared-form
  #sharedForm
  [schema]="newFormSchema"
  (userFormOnSubmit)="formSubmited($event)"
></shared-form> -->

{{ newFormSchema | json }}

sharedForm.com.ts

import {
  Component,
  EventEmitter,
  Input,
  OnDestroy,
  OnInit,
  Output,
  VERSION,
} from '@angular/core';
import {
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from '@angular/forms';

import { FormSchema } from '../form.schema';

@Component({
  selector: 'shared-form',
  templateUrl: './shared.form.html',
})
export class SharedForm implements OnInit, OnDestroy {
  @Input() schema = FormSchema;
  @Output() userFormOnSubmit = new EventEmitter();
  userForm: FormGroup;
  constructor(private fb: FormBuilder) {
    this.userForm = this.fb.group({
      name: new FormControl('', [Validators.required]),
      username: new FormControl('', [Validators.required]),
    });
  }

  ngOnInit() {
    this.loadValues();
  }

  loadValues() {
    const updateObj = {};
    this.schema.forEach((data) => {
      updateObj[data.name] = data.value;
    });
    this.userForm.patchValue(updateObj);
  }

  updateForm($event) {
    $event.preventDefault();
    console.log(this.userForm.value);
    this.userFormOnSubmit.emit(this.userForm.value);
  }
  ngOnDestroy() {
    console.log('callss');
  }

  updateValue(controlName) {
    return controlName;
  }

  reloadForm() {
    this.loadValues();
  }

  ngAfterViewInit() {
    // this.schema.forEach((item) => {
    //   if (item.formControl === controlName) {
    //     this.userForm.controls[controlName].setValue(item.value);
    //   }
    // });
  }
}

sharedForm.com.html

<div>
  <form [formGroup]="userForm" (ngSubmit)="updateForm($event)">
    <div *ngFor="let element of schema">
      <label>{{ element.name }}</label>
      <input
        [type]="'element.type'"
        [formControlName]="updateValue(element.formControl)"
      />
    </div>
    <button type="submit">Submit</button>
  </form>
</div>

stackblitz

Upvotes: 1

Related Questions