vigamage
vigamage

Reputation: 2125

Fire form valid event with initial async data from parent - Angular Reactive forms

In my project, from the parent component, I am passing some async data to the child component. In the child component, I have a form of which the initial data are from the data passed by the parent.

The form in the child, initially does not have any data. However, as the data comes from the parent, it starts to have some default set of data.

parent component

  formDataFromParent;

  async ngOnInit() {
    await new Promise(resolve => setTimeout(resolve, 5000)); 
    this.formDataFromParent = {name: 'John', age: 25};
  }

child component

  @Input() formDataFromParent: any;
  public dataForm: FormGroup;

  constructor(private _formBuilder: FormBuilder) { }

  ngOnInit(): void {
    this._initializeForm();
    this._setupListner();
  }

  _initializeForm() {

    this.dataForm = this._formBuilder.group({
      name: [this.formDataFromParent?.name, [Validators.required]],
      age: [this.formDataFromParent?.age, [Validators.required, Validators.min(10), Validators.max(50)]]
    });

  }

  _setupListner() {
    this.dataForm.statusChanges.pipe(filter(() => this.dataForm.valid))
      .subscribe(() => alert('Form is valid'));
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes.formDataFromParent) {
      this._initializeForm();
      this._setupListner();
    }
  }

(Note that I have added a timeout before passing data to the child. What happens actually there is, parent fetches some data from the back end and then pass.)

Now this implementation works. But I need to catch the from valid event just after the data is set to the form. That event does not fire in that scenario. It fires when data is typed into the form fields in the template only.

Is that the nature/expected behavior? If so, is there any way that I can fire the form valid event?

Thank You..!

Stackblitz

Upvotes: 0

Views: 280

Answers (1)

Moshezauros
Moshezauros

Reputation: 2593

you are registering the listener after the form is ready, so it won't trigger until another change happens on the form (which happens when the first change is introduced by the user).

You could check the form is valid after you set the data (either in ngOnChanges or in _initializeForm)

something like:

   _setupListner() {
    this.dataForm.statusChanges
    .pipe(filter(()=> this.checkFormValid()))
      .subscribe(() => this.actOnValidForm());
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes.formDataFromParent) {
      this._initializeForm();
      if (this.checkFormValid()){
        this.actOnValidForm();
      }
      this._setupListner();
    }
  }

  private checkFormValid(): boolean {
    return this.dataForm.valid;
  }

  private actOnValidForm() {
    alert('Form is valid');
  }

I've extracted the logic to two functions to make it extendable without repeating checks\actions.

See stackblitz

Upvotes: 0

Related Questions