I try to control a mat-slide-toggle, with a form, controlled by a FormControl.
It means that the disabled
attribute of my mat-slide-toggle depends on the FormControl value. More precisely, I want to disable the toggle if the FormControlValue is not set.
The form is as follow:
<mat-form-field>
<mat-label i18n="@@main.level">Level</mat-label>
<mat-select [formControl]="levelControl" >
<mat-option *ngFor="let level of levelList" [value]="level.value">
{{level.viewValue | titlecase}}
</mat-option>
</mat-select>
</mat-form-field>
I cannot directly use levelControl.value to set disabled or not my toggle, because this toggle generates a dynamic component, and this methods generates ChangedAfterItHasBeenChecked Errors.
So I defined an Observable in my component:
disableToggle: Observable<boolean>;
ngOnInit() {
this.disableToggle = this.levelControl.valueChanges.pipe(filter(next => next.level === ''));
}
I use it into the toggle as it follows:
<mat-slide-toggle [disabled]="(disableToggle | async)"> </mat-slide-toggle>
But nothing happens, the toggle is always enabled. Has anybody a solution ? Thanks for your help !
CodePudding user response:
You can use ReactiveForms and add the toggle to the form and bind it. Once you've done that you can listen to the changes like:
form.toggle.value.subscribe((flag: boolean) => form.field.disable(flag));
If you don't use reactive forms and only have the levelControl as a property of type FormControl you'll need to add another one for your toggle field and pretty much do the same as above
CodePudding user response:
You are using filter
to actually filter out non-values, thus it won't be disabled as the code will not be executed after filter if there is not a value. What you want to do, is to use map
instead and return true
or false
based on if there is a value. Below I also trigger the initial valueChanges
with the current value of the form control:
ngOnInit() {
this.disableToggle = this.levelControl.valueChanges.pipe(
startWith(this.levelControl.value),
map(value => value ? false : true)
);
}
Now it should work as you want.