2
votes

I'm working in a team on an Angular 9 project with a lot of components that use reactive forms, and I've been tasked with refactoring some code so as to preserve existing functionality but eliminate this annoying message from the dev console:

 It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
      when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
      you. We recommend using this approach to avoid 'changed after checked' errors.
       
      Example: 
      form = new FormGroup({
        first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
        last: new FormControl('Drew', Validators.required)
      });

The disabled attribute is currently only being used on the "Save" (submit) button html, which is set up like this (where componentForm is the name of the FormGroup that's built in the component.ts ngOnit):

<button class="btn btn-primary btn-sm" type="submit" [disabled]="!componentForm.dirty || !componentForm.valid"><i class="fa fa-save" aria-hidden="true"></i>Save
</button>

Here's the setup for the form group in the component.ts (just one example; multiple components in the app use this same setup):

componentForm: FormGroup;

constructor(private fb: FormBuilder,
        //other stuff) {
        super();
    }

    ngOnInit(): void {
        
        this.componentForm = this.fb.group({
            title: ['', [Validators.required, Validators.maxLength(100)]],
            description: ['', [Validators.maxLength(500)]],
            program: ['', [Validators.maxLength(100)]],
            draftNumber: ['', [Validators.maxLength(100), Validators.pattern('^([zZ]-)([0-9][0-9][0-9][1-9])\\.([1-9][0-9][0-9]|[0-9][1-9][0-9]|[0-9][0-9][1-9]|[1-9]|0[1-9])')]],
            agencyRequestStatusName: ['']
        });

So, the functionality I need to preserve is that the Save button should be disabled as long as the form is either untouched (pristine) or invalid (according to the validators passed into the formbuilder).

[disabled] works great for this, buuuuuut... we get that message.

My immediate thought for getting around this was, ok, maybe I can subscribe to an Observable (also in ngOnit?) that tracks the valid/invalid state of the FormGroup (componentForm), and then use the .disable() and .enable() methods on the save button whenever the Observable changes.

But, if this is a thing, I can't seem to find the syntax for it. And, the other top hits on SO and elsewhere that I've seen don't really offer very clean ways of getting around this message, either (I tried swapping [disabled] for [attr.disabled], but that just straight-up didn't work... maybe that's been deprecated by Angular 9, I don't know).

So, does anyone know how to subscribe to a reactive FromGroup's validation state? Or, is there a better way to enable/disable a control based on this kind of reactive form's validation state?

Thanks!

1

1 Answers

0
votes

Try adding the attr. to your disabled attribute like this [attr.disabled]

<button class="btn btn-primary btn-sm" type="submit" [attr.disabled]="!componentForm.dirty || !componentForm.valid"><i class="fa fa-save" aria-hidden="true"></i>Save
</button>