【问题标题】:How to disable Parent Component Form Submit button if child component fields are not valid如果子组件字段无效,如何禁用父组件表单提交按钮
【发布时间】:2019-01-03 03:39:33
【问题描述】:

我正在使用模板驱动表单。

父组件 HTML

<form #BasicForm="ngForm" (ngSubmit)="onBasicDetailsSubmit()" id="BasicForm">

  <app-input-text [(sharedVar)]="dashboardDetails.Text1" [isMandatory]="true" ></app-input-text>
  <app-input-text [(sharedVar)]="dashboardDetails.Text2" [isMandatory]="false"></app-input-text>

  <input type="submit" value="Save" [disabled]="!BasicForm.valid" class="btn btn-success">

</form>

子组件

TS

@Input() sharedVar: number;
@Input() isMandatory: boolean;

@Output() sharedVarChange = new EventEmitter();


change(newValue) {
  this.sharedVar = newValue;
  this.sharedVarChange.emit(newValue);
}

HTML

<input type="text" class="form-control" [(ngModel)]="sharedVar" (ngModelChange)="change($event)" [attr.required]="isMandatory">

提交按钮没有被禁用。我曾尝试在子组件以及父组件选择器中编写required,但它不起作用。请帮忙。

【问题讨论】:

  • 在父组件 html 中你没有访问 sharedVarChange no?
  • 没有。我现在正在尝试
  • 您可以在父母和孩子之间共享相同的formstackoverflow.com/questions/51281527/… 唯一的区别是您有模板驱动的表单。这不应该是一个问题。完成后,您可以获取表单控件以在任一组件中进行验证

标签: angular angular2-forms angular6 angular4-forms angular-validation


【解决方案1】:

父组件 HTML

<app-input-text [(sharedVar)]="dashboardDetails.Text1" (sharedVarChange)="sharedVarChangeHandle($event)" ...

父组件 TS

sharedVarChangeHandle($event) {
    // by evaluating the value passed you can update a variable (ex: disableSubmit)
} 

父组件 HTML

<input type="submit" value="Save" [disabled]="!disableSubmit" class="bt .....

【讨论】:

    【解决方案2】:

    子组件 ts

    valid // this is a public variable
    
    change(newValue) {
      this.sharedVar = newValue;
      this.sharedVarChange.emit(newValue);
      // here conditioanally update the **valid** variable (true or false)
    }
    

    【讨论】:

      【解决方案3】:

      当您使用Template-Driven-Form 时,验证Child components 的最佳方法是创建一个custom-Directive,您将始终将其添加到要在子组件表单中验证的每个字段中:

      你可以用这个:

      import {Directive, OnInit} from '@angular/core';
      import {NgControl, NgForm, NgModel} from "@angular/forms";
      
      /**
       * This attribute directive must be used to each input-field of a childComponent.
       * That input-field must contain a NgModel attribute, else the application must throw an error
       * Usage: (<input class="form-control" type="text" registerChildComponentToForm
       *          [(ngModel)]="testname" name="testname" required />
       */
      
      @Directive({
          selector: '[registerChildComponentToForm]',
          providers: [NgModel]
      })
      export class RegisterTemplateFormModelDirective implements OnInit {
      
          constructor(private form: NgForm, private eltControl: NgControl) {
          }
      
          ngOnInit() {
              if (this.form && this.eltControl) {
                  this.form.form.addControl(this.eltControl.name, this.eltControl.control);
              }
          }
      
      }

      然后将其注册到declarationsexports 中的App-Module

      declarations: [
              RegisterTemplateFormModelDirective,
              ...
      ],
      exports: [
              RegisterTemplateFormModelDirective,
              ...
      ]

      假设您的&lt;app-input-text&gt;HTML 代码,那么您应该像这样使用directive(registerChildComponentToForm):

      <input id="iban" name="iban" [(ngModel)]="bank.iban" #ibanRef="ngModel" 
        [required]="isMandatory" registerChildComponentToForm/>

      【讨论】:

      • 非常感谢。这个解决方案效果很好。只有1个问题。我在控制台中收到以下错误。你能帮忙吗? ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:'ng-valid: true'。当前值:'ng-valid: false'。
      • 我已经用setTimeOut 修复了它,但我认为它不是正确的方法:setTimeout(() => { if (this.form && this.eltControl) { this.form.form. addControl(this.eltControl.name, this.eltControl.control); } }, 1);
      • setTimeOut 的方法也是正确的。我也用它。或者使用 Angular 的 ChangeDetectorRef 的方法 angular.io/api/core/ChangeDetectorRef
      猜你喜欢
      • 2020-04-18
      • 1970-01-01
      • 2019-03-07
      • 2019-12-11
      • 2017-10-24
      • 2019-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多