3
votes

TL,DR; A FormGroup is not considered dirty when a nested FormControl is changed from disabled to enabled, or vice versa.

Detail; What is a good way of getting all form controls belonging to a FormGroup, that have changed from enabled to disabled, or vice versa?

As this Stackblitz shows, the pristine, dirty, touched, and untouched properties remain unchanged when a control changes from enabled to disabled, or vice versa.

export class AppComponent implements OnInit {
  person: FormGroup;
  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.person = this.fb.group({
      name: this.fb.control(''),
      age: this.fb.control(100),
    });
  }
}

The Typescript above defines a single FormGroup (person) with two FormControls (name and age).

The HTML below allows the name control to be enabled and disabled by clicking a button. Some properties are output too.

<form [formGroup]="person">
    <input type="text" placeholder="Name" formControlName="name">
    <button (click)="person.controls['name'].disable()">Disable</button>
    <button (click)="person.controls['name'].enable()">Enable</button>
    <br />
    <br />
    <input type="text" placeholder="Age" formControlName="age">
</form>

<pre>{{person.value | json}}</pre>

disabled: {{ person.disabled }}<br />
pristine: {{ person.pristine }}<br />
dirty: {{ person.dirty }}<br />
touched: {{ person.touched }}<br />
untouched: {{ person.untouched }}<br />

enter image description here

I'd expected it to be easy to detect when a control is:

  • enabled (where it was previously disabled)
  • disabled (where it was previously enabled)

Unlike the pristine, dirty, touched, and untouched properties, the enabled and disabled state seems transient.

It seems there is no property of a FormGroup that reflects if child controls have been enabled or disabled away from their original state? The FormGroup remains pristine and untouched.

It has been suggested to use statusChanges. However, this only provides four possible validation status values (VALID, INVALID, PENDING, DISABLED). There is no clear way to map the status to a control and subsequently determine whether is has changed from enabled to disabled or vice versa. I've created another Stackblitz demonstrating this.

EDIT

I've opened a bug FormGroup not dirty when a nested FormControl changes from disabled to enabled, or vice versa.

1
isnt there an observable for that ?Antoniossss
You can always hook into ngDetectChanges and do it manually there.Antoniossss
@antoniossss - that would require manually tracking the enabled/disabled state of all controls. Doable, but this seems OTT given this approach is not needed for any of the properties cited in my question (IMO).Jack
have you tried? person.statusChanges.pipe(map(()=>person.disabled)).subscribe(value => console.log(value));Reactgular

1 Answers

2
votes

You can try to give a shot to listen for control status changes - one of them is disabled

https://angular.io/api/forms/AbstractControl#status

https://angular.io/api/forms/AbstractControl#statusChanges

EDIT:

There is obvious method for that, but it is called registerOnDisabledChange

https://angular.io/api/forms/FormControl#registerOnDisabledChange

Showcase forked form your stackblitz https://stackblitz.com/edit/formbuilder-soydhk

If you need to listen for that on controll level, nothing stands in your way to write aggregating listener.