Angular 角度反应形式-让嵌套子级确定启用/禁用
我有一个嵌套的反应形式 子项有2个属性,第二个属性根据第一个属性的值启用或禁用 父窗体有一个编辑按钮,通过该按钮启用/禁用字段Angular 角度反应形式-让嵌套子级确定启用/禁用,angular,angular-reactive-forms,Angular,Angular Reactive Forms,我有一个嵌套的反应形式 子项有2个属性,第二个属性根据第一个属性的值启用或禁用 父窗体有一个编辑按钮,通过该按钮启用/禁用字段 this.parentForm.enable() 我的问题是,无论发生什么情况,这都会启用第二个子字段,而不会使用子字段中的逻辑来确定应该启用还是禁用它 对于在子对象中使用启用/禁用逻辑的被动表单,建议采用什么方法?我尝试使用[disabled],但不起作用,并且收到了不应该这样做的警告 下面是一个示例问题 单击edit时,仅当选中Yes时,才应启用最后一次输入。如果选
this.parentForm.enable()
我的问题是,无论发生什么情况,这都会启用第二个子字段,而不会使用子字段中的逻辑来确定应该启用还是禁用它
对于在子对象中使用启用/禁用逻辑的被动表单,建议采用什么方法?我尝试使用[disabled],但不起作用,并且收到了不应该这样做的警告
下面是一个示例问题
单击
edit
时,仅当选中Yes
时,才应启用最后一次输入。如果选中了No
,则应禁用该功能。因此,请在控制器中添加如下功能:
private setChildState() {
// this function gets the ctrl to enable/disable and does so based on the value
const v = this.parentForm.get('typeDetails').get('identity').value;
let ctrl = this.parentForm.get('typeDetails').get('identityname');
if (v === 'yes') {
ctrl.enable();
} else {
ctrl.disable();
}
}
这是为了设置子窗体的启用/禁用状态,然后只需添加以下几行:
这在您的ngOnViewInit()中
然后在编辑功能中执行以下操作:
this.setChildState();
修正闪电战:
编辑:
如果您想将所有(大部分)内容保存在孩子中,请将孩子更改为:
ngOnInit() {
this.identifyForm.get('identity').valueChanges.subscribe(v => {
this.setState();
})
}
setState() {
const v = this.identifyForm.get('identity').value;
let ctrl = this.identifyForm.get('identityname');
if (v === 'yes') {
ctrl.enable();
} else {
ctrl.disable();
}
}
然后将其添加到父级中的编辑功能:
this.childComponent.setState();
将无线电组码移动到父组件并订阅更改 基于值是或否 启用和解除子组件窗体控件
归档stackblitz:另一个方法是改进该指令的启用指令 我们将改进指令,不仅允许禁用控件,还允许禁用表单中的所有控件
@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) {}
}
我们可以在这里看到最终结果。你应该把你的代码放在你的问题中。@bryan60而不是放在堆栈闪电战中?这两种方法都是推荐的,链接将来可能会坏,但现在很有用。这确实有效,但会将子链接的逻辑泄漏到父链接中。此子级每次都将在多个位置使用相同的启用/禁用逻辑,因此我必须在每个父级中复制setChildState。是否可以在每个父级中都没有子逻辑的情况下执行此操作?这会将子级的验证逻辑泄漏到父级中。当孩子以多种形式使用时,会成为一个真正的问题。
@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) {}
}
<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>