Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular onBlur和;提交_Angular_Forms_Typescript_Angular Forms - Fatal编程技术网

Angular onBlur和;提交

Angular onBlur和;提交,angular,forms,typescript,angular-forms,Angular,Forms,Typescript,Angular Forms,我正在尝试使用只更新onBlur的输入创建表单([ngFormOptions]=“{updateOn:'blur'}”)。但这样做的一个副作用是,一旦用户点击“回车”,表单就不再提交,因为模型只在模糊时更新。(与问题相同,但没有答案) 因此,表单被标记为无效,因为输入字段中有一个值,但模型尚未使用该值更新 版本: -角度6.0.7 -@angular/forms6.0.7 HTML示例 <form (ngSubmit)="login()" #loginForm="ngForm" [ngF

我正在尝试使用只更新onBlur的输入创建表单(
[ngFormOptions]=“{updateOn:'blur'}”
)。但这样做的一个副作用是,一旦用户点击“回车”,表单就不再提交,因为模型只在模糊时更新。(与问题相同,但没有答案)

因此,表单被标记为无效,因为输入字段中有一个值,但模型尚未使用该值更新

版本: -角度
6.0.7
-@angular/forms
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
上进行验证的方法。我知道自从Angular 5以来,我们有了选项
[ngFormOptions]=“{updateOn:'blur'}”
,但是有没有办法给这个对象指定两个参数

[ngFormOptions]=“{updateOn:['blur','submit']}”
似乎不起作用)


差点忘了,我确实不希望模型在更改时更新(由于用户仍在键入,因此创建的恼人消息不太有用)

在表单中创建第三个不可见的输入,并为其提供一个模板变量。在提交之前,只需聚焦此输入,即可触发
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>


请注意,这是您可以使用的众多变通方法之一,而不是实际的解决方案-表单组件

在遵循@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,我们可以在这个组件的新表单上设置它,以便表单控件被正确地转移(否则Angular无法识别表单控件)。这就是阻止我使用模板驱动表单的问题

当表格提交时,我们现在检查它是否有效。如果不是,那么我们递归地循环所有FormControls(
updateControls()
),并将状态更新为“toucted”(因为我们要对它们设置错误,所以也可以将它们标记为“toucted”)。为了使Angular向其侦听器发送一个
stateChange
事件,我们需要使用
updateValueAndValidity()
。由于我们已经在每个表单控件中循环,我们可以将
onlySelf
标志设置为
true

属于表单的模板:


注意
[formGroup]
标记,Angular使用相同的标记在表单上定义反应表单。从输入中删除标记会导致角度错误,告诉您需要标记才能分配
formControlName
。通过使用相同的标记将表单注入指令,我们可以确保程序员不会遇到这个问题。安格尔会很高兴,你可以得到的形式内的指令,双赢的局面

这不只是更新隐藏输入的值而不是完整表单吗?@Pilatus否,模糊更新是在表单级别定义的(随后在每个输入上定义)。这意味着当用户留下一个输入时,该输入的值将被更新。如果输入用户名,则点击
选项卡
,该值将被更新,然后输入密码。如果然后输入密码并按enter键,则不会保留输入,也不会更新值。如果您决定关注其他内容,您将保留输入,从而更新值。这并非完全正确。当我通过编程更改焦点时(我通过@ViewChild获取隐藏的输入,然后调用此.input.nativeElement.focus()),它不会更新模型,但输入确实会失去焦点。@Mr.wiseguy,那么你应该试试你的输入元素(而不是隐藏的元素)@trichetriche,我尝试在输入字段中调用'blur()',但问题是表单在提交时已经过验证,因此更改afterwords后的值将不起作用(模型更新需要很长时间才能对验证产生影响)
<form (ngSubmit)="submitForm()"
      [formGroup]="form"
      class="no-validate">

  <ng-content></ng-content>

</form>
<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>