Another aproach is improve the enabled directive of this stackoverflow answer
We are going to improve the directive to allow disabled not only the control else all the controls inside a form.
@Directive({
selector: '[disableControl]'
})
export class DisableControlDirective {
@Input() set disableControl(condition: boolean) {
if (this.ngControl) { //if is an ngControl
if (condition)
this.ngControl.control.disable();
else
this.ngControl.control.enable();
}
if (this.controls) { //if is a formGroup, we ask about the inners controls
this.controls.forEach((x: any) => {
let control:boolean=false;
if (this.innerControl) //we check if the control has
//his own DisableControlDirective
control=(this.innerControl.find(inner=>x==inner.ngControl)!=null)
if (!control) { //if it has not a own DisabledControlDirective
if (condition)
x.control.disable();
else
x.control.enable()
}
})
}
}
@ContentChildren(NgControl) controls: QueryList<NgControl>
@ContentChildren(DisableControlDirective)
innerControl:QueryList<DisableControlDirective>
//see that make public ngControl to use when check if a innerControl has
//the directive
constructor(@Optional() public ngControl: NgControl) {}
}
If we apply the directive to a fromGroup, disabled/enabled all the inners controls. For get the inners control we are using @ContentChildren(NgControl)
. When we inject NgControl, we need put @Optional()
because in a FormGroup we has NO NgControl -remember that NgControl is anything that has [formControlName], [NgModel] or [formControl] directive
We need check if our inner controls has no [disableControl] directive. In this case we need leap this control. For this, we need get these controls using @ContentChildren(DisableControlDirective)
and check it.
Our form becomes very "easy", but we pass as @Input
the edit mode to the child
<form [formGroup]="parentForm" [disableControl]="!editMode" (ngSubmit)="onSave()">
<input formControlName="id">
<input formControlName="name">
<app-child-component [editMode]="editMode"></app-child-component>
</form>
//and our children component
<form [formGroup]="identifyForm" [disableControl]="!editMode">
<input type="radio" name="identity" value="yes" formControlName="identity"> Yes
<input type="radio" name="identity" value="no" formControlName="identity" > No
<input formControlName="identityname"
[disableControl]="!editMode || identifyForm.get('identity').value=='no'">
</form>
We can see the final result in this stackblitz