首页 > 解决方案 > 如何禁用子组件(子表单组)?

问题描述

我有:

如您所见,我的主表单(没有子表单)处于禁用状态,您可以通过单击编辑按钮启用它。我也希望子组件是这样的。因此,整个表单被禁用,并且在单击编辑按钮时它被启用(您可以键入、选择等)。我该怎么做?我试过做这样的事情:

  constructor(private formBuilder: FormBuilder) {
    this.registerForm = this.formBuilder.group({
      username: [{value: '', disabled: this.disableForm}],
      email: [{value: '', disabled: this.disableForm}],
      password: [{value: '', disabled: this.disableForm}],
      confirmpassword: [{value: '', disabled: this.disableForm}],
      dropdown: [{value: '', disabled: this.disableForm}],
      checkbox1: [{value: '', disabled: this.disableForm}],
      rowForm: this.formBuilder.group(
        {
          input1: [''],
          input2: [''],
          input3: [''],
          checkbox2: [''] 
        }
      )
    });
  }

但它根本不起作用。

我的注册表单(主要组件,主要表单组)html文件:

<div class="main-wrapper" fxLayout="row" fxLayoutAlign="center center">
    <mat-card class="box">
        <mat-card-header class="header">
            <mat-card-title>Register</mat-card-title>
        </mat-card-header>

        <form [formGroup]="registerForm" (ngSubmit)="onSubmit()">

            <mat-checkbox class="example-margin" [formControl]="checkbox1">Show hidden option!</mat-checkbox>

            <!-- Username -->
            <mat-card-content>
                <mat-form-field class="example-full-width">
                    <input matInput placeholder="Username" name="username" minlength="5"
                        formControlName="username" required>
                </mat-form-field>
                <mat-error *ngIf="username.touched && !username.valid">
                    <div *ngIf="username.errors?.required">Username is required.</div>
                    <div *ngIf="username.errors?.minlength">Username should be minimum 5 characters.</div>
                </mat-error>

                <!-- Email -->
                <mat-form-field class="example-full-width">
                    <input matInput placeholder="Email"  name="email" minlength="5" [pattern]="emailPattern"
                        formControlName="email" required>
                </mat-form-field>
                <mat-error *ngIf="email.touched && !email.valid">
                    <div *ngIf="email.errors?.required">Email is required.</div>
                    <div *ngIf="email.errors?.pattern">Email is not valid.</div>
                </mat-error>

                <!-- Password -->
                <mat-form-field class="example-full-width">
                    <input matInput placeholder="Password"  name="password" minlength="5"
                        formControlName="password" required>
                </mat-form-field>
                <mat-error *ngIf="password.touched && !password.valid">
                    <div *ngIf="password.errors?.required">Password is required.</div>
                    <div *ngIf="password.errors?.minlength">Password should be minimum 5 characters.</div>
                </mat-error>

                <!-- Repeat Password -->
                <mat-form-field class="example-full-width">
                    <input matInput placeholder="Confirm Password" name="confirmpassword" formControlName="confirmpassword"
                        required>
                </mat-form-field>
                <mat-error *ngIf="confirmpassword.touched && confirmpassword.value != password.value"> Passwords does not match
                </mat-error>


            </mat-card-content> 

            <app-row [rowForm]="registerForm.controls.rowForm"></app-row>

            <button mat-button color="primary" class="btn-block" *ngIf="isEditable; else edit" type="submit"
                [disabled]="!registerForm.valid"> Register
            </button>

            <ng-template #edit>
                <button mat-button color="primary" class="btn-block" type="button" (click)="enableEdit()">
                    Edit
                </button>
            </ng-template>

        </form>
    </mat-card>

我的注册表单(主要组件,主要表单组)ts文件:

import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';

@Component({
  selector: 'app-register-form',
  templateUrl: './register-form.component.html',
  styleUrls: ['./register-form.component.css']
})
export class RegisterFormComponent implements OnInit {

  emailPattern = '^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$'; 
  registerForm;
  disableForm = true;
  isEditable;

  constructor(private formBuilder: FormBuilder) {
    this.registerForm = this.formBuilder.group({
      username: [{value: '', disabled: this.disableForm}],
      email: [{value: '', disabled: this.disableForm}],
      password: [{value: '', disabled: this.disableForm}],
      confirmpassword: [{value: '', disabled: this.disableForm}],
      checkbox1: [{value: '', disabled: this.disableForm}],
      rowForm: this.formBuilder.group(
        {
          input1: [{value: '', disabled: this.disableForm}],
          input2: [{value: '', disabled: this.disableForm}],
          input3: [{value: '', disabled: this.disableForm}],
          checkbox2: [{value: '', disabled: this.disableForm}] 
        }
      )
    });
  }


  ngOnInit(): void {
  }

  enableEdit() {
    this.disableForm = !this.disableForm;
    this.registerForm.enable();
    this.isEditable = true;
  }


  get username() {
    return this.registerForm.get('username');
  }

  get email() {
    return this.registerForm.get('email');
  }

  get password() {
    return this.registerForm.get('password');
  }

  get confirmpassword() {
    return this.registerForm.get('confirmpassword');
  }



  get checkbox1() {
    return this.registerForm.get('checkbox1');
  }


  onSubmit() {
    console.log(this.registerForm.value);
    this.registerForm.disable();
    this.isEditable = false;
  }
}

我的行(子组件,子表单组)html文件:

<form [formGroup]="rowForm">
  <div formArrayName="rows">
    <div *ngFor="let rows of getControls(); let i=index"  [formGroupName]="i">

      <mat-checkbox class="example-margin" formControlName="checkbox2"  name="checkbox2" (click)="toggleInput()">Show hidden option!</mat-checkbox>

      <mat-form-field class="example-full-width">
        <input matInput placeholder="Input1" formControlName="input1"  name="input1" required>
      </mat-form-field>

      <mat-form-field class="example-full-width">
        <input matInput placeholder="Input2" formControlName="input2"  name="input2" required>
      </mat-form-field>

      <mat-form-field *ngIf="showInput"  class="example-full-width">
        <input matInput placeholder="Input3" formControlName="input3"  name="input3" required>
      </mat-form-field>

      <button mat-button color="primary" *ngIf="rowForm.controls.rows.controls.length > 1" (click)="deleteRow(i)" class="btn btn-danger">Delete Button</button>
    </div>
  </div>
  
  <button mat-button color="primary" (click)="addNewRow()" class="btn btn-primary">Add new Row</button><br>

</form>

我的行(子组件,子表单组)ts文件:

import {Component, Input, OnInit} from '@angular/core';
import { FormBuilder, FormGroup, FormControl, Validators, FormArray} from '@angular/forms';

@Component({
  selector: 'app-row',
  templateUrl: './row.component.html',
  styleUrls: ['./row.component.css']
})
export class RowComponent implements OnInit {

  @Input() rowForm: FormGroup;
  showInput = false;


  constructor(private formBuilder: FormBuilder) {}


  ngOnInit() {
    this.rowForm = this.formBuilder.group({
      rows: this.formBuilder.array([this.createRow()])
    });
  }


  createRow(): FormGroup {
    return this.formBuilder.group({
      input1: ['', Validators.required],
      input2: ['', Validators.required],
      input3: ['', Validators.required],
      checkbox2: ['', Validators.required],
    });
  }

  toggleInput(index: number) {
    this.showInput = !this.showInput;
  }

  get formArray() {
    return this.rowForm.get('rows') as FormArray;
  }

  // Adding row function
  addNewRow() {
    this.formArray.push(this.createRow());
  }

  deleteRow(index: number) {
    this.formArray.removeAt(index);
  }

  getControls() {
    return (this.rowForm.get('rows') as FormArray).controls;
  }

}

标签: angular

解决方案


它有点旧,但我喜欢使用指令禁用 FormControl

否则,您可以创建一个禁用/启用 formGroup 及其子项的函数

  enable(form: FormGroup, enable: boolean) {
    Object.keys(form.controls).forEach(key => {
      const control = form.get(key);
      if (control) {
        if ((control as any).controls)
          this.enable(control as FormGroup, enable);
        else {
          if (enable) control.enable();
          else control.disable();
        }
      }
    });
  }

使用指令将指令添加到每个输入并使用变量,例如

<input matInput [enableControl]="toogle" placeholder="Ex. Pizza" formControlName="prop1">

每次更改指令时,输入都会被禁用/启用

该功能在您的 .ts 中,在您的“编辑”按钮中

<button (click)="enable(registerForm,true)">Edit</button>

但是您的代码中有一些错误。管理嵌套表单有多种方法。

1.-更简单的方法是在父级中创建表单并将“formGroup”传递给子级。但你做错了。创建 registerForm 时需要更改

this.registerForm = this.formBuilder.group({
  username: [{value: '', disabled: this.disableForm}],
  email: [{value: '', disabled: this.disableForm}],
  password: [{value: '', disabled: this.disableForm}],
  confirmpassword: [{value: '', disabled: this.disableForm}],
  checkbox1: [{value: '', disabled: this.disableForm}],
  rowForm: this.formBuilder.group({
    rows:this.formBuilder.array([this.createRow(true)])
  })
});

  createRow(disabled:boolean=false): FormGroup {
    return this.formBuilder.group({
      input1: [{value:'',disabled:disabled}, Validators.required],
      input2: [{value:'',disabled:disabled}, Validators.required],
      input3: [{value:'',disabled:disabled}, Validators.required],
      checkbox2: [{value:'',disabled:disabled}, Validators.requiredTrue],
    });
  }

看到你是在 formArray 中创建元素的重复代码 - 你的孩子中有另一个类似的 - 我更改了一些函数来创建禁用的控件。

2.-创建一个 FromGroup 空并在 child 中添加 formGroup。为此,我们将表单组“rowForm”创建为 FromGroup 空

this.registerForm = this.formBuilder.group({
  username: [{value: '', disabled: this.disableForm}],
  ....
  rowForm: this.formBuilder.group({})
});

在孩子中,我们在 ngOnInit 中“更改”这个 formGroup。我包含在 setTimeout() 中以避免错误“ExpressionChangedAfterItHasBeenCheckedError”

  ngOnInit() {
    setTimeout(()=>{
      this.rowForm.addControl("rows",this.formBuilder.array([this.createRow(true)]))

    })
  }

使用这种方法,您无需重复代码

这样就可以使用我在代码中写的启用功能了。

这个 stackblitz中,有第一个选项(在父级中创建整个表单)

这个 stackbliz中是第二个(在 child 中创建 rowForm 并添加到 parent)

(*)为避免重复代码,您可以使用 ViewChild 来获取子项并使用子项的函数“createRow”


推荐阅读