双方的onblur及的onsubmit NgModel更新(NgModel update on bo

2019-09-25 19:14发布

我想创建与输入的形式,只更新的onblur( [ngFormOptions]="{updateOn: 'blur'}" )。 但一个副作用是,一旦用户点击“确认”,因为模型仅更新的onblur形式不再提交。 (同这个问题,但一直无人接听)

由于这种形式的结果被标记为无效,因为在输入字段中的值,但该模型尚未与该值进行更新。

版本: -角6.0.7 - @角/形成6.0.7


例如HTML

<form (ngSubmit)="login()" #loginForm="ngForm" [ngFormOptions]="{updateOn: 'blur'}" [validate-on-submit]="loginForm">
  <input type="text" ([NgModel])="user.username"/>
  <input type="password" ([NgModel])="user.password"/>
</form>

当在两个字段中输入一个有效的文本并点击“确认”键,表单验证,标志着密码为无效(即有焦点的输入),因为NgModel尚未更新,因此值无效。


我想要什么

所以,我在找的是验证两个办法onBlur藏汉作为onSubmit 。 我知道,因为角5,我们可以选择[ngFormOptions]="{updateOn: 'blur'}" ,但有没有办法给2个参数到这个对象?

[ngFormOptions]="{updateOn: ['blur', 'submit']}"似乎不工作)

差点忘了,我不想更新模型onChange (创建不是非常有益的烦人的信息,因为用户仍然打字..)

Answer 1:

创建表单第三,无形的投入,并给它一个模板变量。 之前提交,单纯强调此输入,将触发onBlur更新:

<form (ngSubmit)="focuser.focus(); login()" #loginForm="ngForm" [ngFormOptions]="{updateOn: 'blur'}">
  <input type="text" ([NgModel])="user.username"/>
  <input type="password" ([NgModel])="user.password"/>
  <input type="hidden" #focuser>
</form>

请注意,这是众多解决方法,你可以使用的一个,而不是一个实际的解决方案



Answer 2:

该解决方案-甲形式部件

以下@trichetriche的建议(创建保存形式的逻辑分离的组件),并让模板驱动形式有利于反应性形式的去后,我发现以下解决方案:

@Component({
  selector: "val-message-form",
  templateUrl: "./message-form.html"
})
export class MessageFormComponent {

  /**
   * The form group that holds all the input fields and the logic of the input fields
   * @type {FormGroup}
   */
  @Input()
  public formGroup: FormGroup;

  /**
   * The function that will be called when the form is valid
   * The template that includes this component can listen to this event for the submit action
   * @type {EventEmitter}
   */
  @Output()
  private onSubmit = new EventEmitter();

  /**
   * Notify all listeners that the form has been submitted
   * NOTE: Notify will only work if the form is valid
   */
  public submitForm(): void {
    if (this.formGroup.valid) {
      this.onSubmit.emit();
    } else {
      this.updateControls(this.formGroup);
    }
  }

  /**
   * Recursively update all form controls, since we are going to display error messages
   */
  private updateControls(formGroup: FormGroup): void {
    Object.keys(formGroup.controls).forEach(field => {
      const control = formGroup.get(field);

      if (control instanceof FormControl) {
        control.markAsTouched({onlySelf: true}); // Otherwise validation color is not shown
        control.updateValueAndValidity({onlySelf: true})
      } else if (control instanceof FormGroup) {
        this.updateControls(control);
      }
    });
  }
}

请注意,被注入的formgroup,我们可以在此组件设置它的新形式,使表单控件正确transcluded(否则角度不识别表单控件)。 这是用模板驱动的形式阻止了我的问题

当表单提交现在我们检查,如果它是有效的。 如果不是,那么我们递归循环槽全部FormControls( updateControls()并更新到“感动”(因为我们要对他们设置错误,我们也可以将它们标记为“感动”)的状态。 为了使角发出的stateChange事件,这是我们需要使用监听器updateValueAndValidity() 既然我们已经在循环槽每formControl我们可以设置onlySelf标志true

属于表单模板:

<form (ngSubmit)="submitForm()"
      [formGroup]="form"
      class="no-validate">

  <ng-content></ng-content>

</form>

通过确保角发射和事件当窗体是无效的,我们已经创建了可用于自定义消息钩子(记得ng-messages从角1.x的?)。 对更多信息可以在[这里] [2]找到。

如果你想在模板中使用,这将如下所示:

<val-message-form (onSubmit)="login()" [formGroup]="form">
  <fieldset>
    <!-- Username -->
    <div class="form-group">
      <input type="email"
             formControlName="username">
    </div>

    <!-- Password -->
    <div class="form-group">
      <input type="password"
             formControlName="password">
    </div>

    <button type="submit" class="btn btn-success shadow-none">
      {{'LOGIN_PAGE.LOGIN.SHORT' | translate}}
    </button>
  </fieldset>
</val-message-form>

注意[formGroup]标签,角使用相同的标记定义窗体上的反应性形式。 除去在角度误差的输入结果的标签告诉你,它需要以指定标签formControlName 。 我们可以确保程序员不会使用相同的标签的形式注入指令遇到这个问题。 角会很高兴,你可以得到指令里面的形式,共赢!



文章来源: NgModel update on both onBlur & onSubmit