Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 7 setting values of reactive form on component load enable save button even if the form isn't validated

I have the following issue. Click to check the stack blitz.

I am setting a reactive form in the constructor:

this.formGroup = this.fb.group({
      'family_name_en': new FormControl('', Validators.required),
      'family_name_ar': new FormControl('', [Validators.required, Validators.pattern('[\u0600-\u06FF ]*')]),
      'unit_id': new FormControl({ value: '', disabled: true }, [Validators.required])
});

And in the ngOnInti() hook, I am getting the data related to the unit_id.

As I am migrating data from platform to another, the family name in arabic was not recommended, but it is now. So most of the data will load without the arabic name.

The issue is the button is always enabled, and what I need to do is if a user wants to update this unit_id, he should add the arabic name so the button is enabled then.

If the form is valid, no harm enabling the button on load of the component.

Here is the getData() method that get the data and set the form group controls values:

ngOnInit() {
    this.getDataById();
}

getDataById():

getDataById() {
    this.showSpinner = true;
    this.auth.getDataById(this.unit_id).subscribe(
      (data) => {
        if (data['info'][0]['total'] == 1) {
          this.noDataBool = false;
          this.showSpinner = false;
          this.family_name_en = data['info'][0]['hh_last_name_en'];
          this.formGroup.controls['family_name_en'].setValue(this.family_name_en);
          this.family_name_ar = data['info'][0]['hh_last_name_ar'];
          this.formGroup.controls['family_name_ar'].setValue(this.family_name_ar);
          this.unit_id = data['info'][0]['unit_id'];
          this.formGroup.controls['unit_id '].setValue(this.unit_id);
    }
}

The button:

<button mat-raised-button color="warn" (click)="updateData()" [disabled]="!formGroup.valid">
    <mat-icon>update</mat-icon>Update
</button>
like image 924
alim1990 Avatar asked Jan 27 '23 03:01

alim1990


2 Answers

Instead of directly accessing the FormControls by using controls on the formGroup, you should use the get API on them. This would give you more control and significantly clean up your implementation(especially in case of getting deeply nested elements). You can change the Component Implementation like this:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  formGroup: FormGroup;
  titleAlert: string = 'This field is required';
  post: any = '';
  family_name_en;
  family_name_ar;
  unit_id;
  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.formGroup = this.fb.group({
      'family_name_en': new FormControl('', Validators.required),
      'family_name_ar': new FormControl('', [Validators.required, Validators.pattern('[\u0600-\u06FF ]*')]),
      'unit_id': new FormControl({ value: '', disabled: true }, [Validators.required])
    });
    this.getDataById();
  }

  getDataById() {
    let data: Array<any> = [
      'Ali', '', '123'
    ]
    this.family_name_en = data[0];
    this.formGroup.get('family_name_en').setValue(this.family_name_en);
    this.family_name_ar = data[1];
    this.formGroup.get('family_name_ar').setValue(this.family_name_ar);
    this.unit_id = data[2];
    this.formGroup.get('unit_id').setValue(this.unit_id);
  }

}

Here's an Updated StackBlitz for your ref. You can test it by typing in علي in there which would enable the Update button. Typing Ali will let it stay disabled.

like image 110
SiddAjmera Avatar answered Jan 29 '23 16:01

SiddAjmera


I always use the following code in situations like this:

this.family_name_ar.setValue(data['info'][0]['hh_last_name_ar']);
this.family_name_ar.updateValueAndValidity();

By calling the second method, updateValueAndValidity() we tell Angular to

Recalculate the value and validation status of the control.

More info on the Angular Docs.

Now, the button should be disabled and the form invalid if the data['info'][0]['hh_last_name_ar'] is empty.

You can use the methods above for every field you need.

like image 20
Mihail Stancescu Avatar answered Jan 29 '23 18:01

Mihail Stancescu