Angular 角度反应形式-让嵌套子级确定启用/禁用

Angular 角度反应形式-让嵌套子级确定启用/禁用,angular,angular-reactive-forms,Angular,Angular Reactive Forms,我有一个嵌套的反应形式 子项有2个属性,第二个属性根据第一个属性的值启用或禁用 父窗体有一个编辑按钮,通过该按钮启用/禁用字段 this.parentForm.enable() 我的问题是,无论发生什么情况,这都会启用第二个子字段,而不会使用子字段中的逻辑来确定应该启用还是禁用它 对于在子对象中使用启用/禁用逻辑的被动表单,建议采用什么方法?我尝试使用[disabled],但不起作用,并且收到了不应该这样做的警告 下面是一个示例问题 单击edit时,仅当选中Yes时,才应启用最后一次输入。如果选

我有一个嵌套的反应形式

子项有2个属性,第二个属性根据第一个属性的值启用或禁用

父窗体有一个编辑按钮,通过该按钮启用/禁用字段
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>