Angular 2 表单验证器弄乱了取消按钮

Posted

技术标签:

【中文标题】Angular 2 表单验证器弄乱了取消按钮【英文标题】:Angular 2 form validators messing with the cancel button 【发布时间】:2017-12-14 09:16:03 【问题描述】:

我有一个数据收集组件,其中包括用于取消整个过程的“取消”按钮。问题是,如果某些由 Angular 2 验证器验证的 html 输入字段具有焦点且无效,并且我按下取消按钮,则不会删除该组件。相反,验证器将触发并且取消按钮按下将被忽略。在验证器抱怨之后,我必须第二次按下它,以使组件消失。取消按钮本身只会触发远离组件的路由。相关代码:

component.html

<form [formGroup]="addReminderForm" (ngSubmit)="onSubmit(addReminderForm.value)">
  <input type="text" [formControl]="addReminderForm.controls['text']" />
  <div class="error" *ngIf="addReminderForm.controls['text'].hasError('required') &&
  addReminderForm.controls['text'].touched">You must enter reminder text</div>

  <button type="submit" [disabled]="!addReminderForm.valid" >Add Reminder</button>
</form>
<button (click)="cancel()">Cancel</button>

component.ts:

ngOnInit() 
  this.addReminderForm = this.fb.group(  
      'text': ['', Validators.compose([Validators.required, Validators.maxLength(20)])]
  );

cancel() 
    // Simply navigate back to reminders view
    this.router.navigate(['../'],  relativeTo: this.route ); // Go up to parent route     
 

我不知道为什么会这样。有什么想法吗?

【问题讨论】:

类似问题,在带有取消按钮的模态表单中显示相同的问题:***.com/questions/46411390/… 谢谢,我注意到了这个问题。当我考虑这个问题时,我的表单实际上有处理模糊事件的处理程序——它修剪了模糊的输入字段。我现在想知道这是不是这个原因? 不,这不是原因。原因是一旦模糊触发表单验证就会触发。所以它发生在取消点击注册之前。我将发布有关如何解决的答案。 你最后找到解决办法了吗? 【参考方案1】:

将事件从 (click) 更改为 (mousedown)。在 blur 事件之前调用 Mousedown。

所以不是这个&lt;button (click)="cancel()"&gt;Cancel&lt;/button&gt;

试试这个:&lt;button (mousedown)="cancel()"&gt;Cancel&lt;/button&gt;

【讨论】:

我现在无法检查这个,但我确信这是问题的真正解决方案。 @mikel - 谢谢! 这是不可访问的,(mousedown) 不会在用户按下空格键或回车时触发。如果您选择此方法,请使用 keydown 操作来保持此行为。【参考方案2】:

尝试使用 button type="reset" 之类的:

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

  ...       
  <div>
    <button type="submit" [disabled]="heroForm.pristine">Save</button>
    <button type="reset" (click)="revert()"[disabled]="heroForm.pristine">Revert o Cancel</button>
  </div>

</form>

在你的组件类中:

revert()  this.ngOnChanges(); 

更多信息请关注https://angular.io/guide/reactive-forms

希望能帮到你。

【讨论】:

我不是要重置表单,而是要完全取消整个组件(删除它)。我确实尝试将按钮类型声明为重置,但没有任何改变。【参考方案3】:

原因是一旦触发模糊事件,表单验证就会触发。所以它发生在取消点击注册之前。

我只能找到一种解决方法 - 在您的组件中设置一个标志,该标志最初设置为 false 以了解何时显示错误。

仅当您希望验证“触发”时才将其设置为 true。

因此,如果表单加载并且用户单击字段然后单击取消,则标志仍然为 false,因此不会显示任何验证。如果用户单击提交,您将打开标志,从而显示验证。

例如,此表单有一个 span 块,用于显示验证错误,并由标志 *ngIf 保护。同样受保护的是输入本身的“检查字段”类 - 如果出现错误,这只会在输入周围添加一个红色边框。所以标志必须为真,红色边框和验证错误才会出现。

  <form [formGroup]="form" (ngSubmit)="onSubmit(form.value)">
    <div class="modal-body">
      <input #nameElement id="template-name" (blur)="onBlur($event.target)" 
        [formControl]="name" (keyup)="keyUp($event)" class="form-control"
        [ngClass]="'checking-field': isShowError" 
        placeholder="Name this template">
      <span class="help-block" *ngIf="isShowError">
        <span class="text-danger" *ngIf="form.get('name').hasError('minlength')">Name is required</span>
        <span class="text-danger" *ngIf="form.get('name').hasError('noDifference')">Name must be different</span>
      </span>
    </div>
  </form>

OnSubmit 是这样开始的:

  onSubmit(data: any):void 
    this.isShowError = true;
    if (this.form.valid) ...

确保在用户单击提交时显示验证错误。当字段失去焦点时它们不会出现,因为标志将是假的。

但是,您可以通过一个丑陋的 hack 来解决这个问题,如下所示(也很麻烦,因为您需要一个模糊处理程序来处理表单上的所有字段!)。

添加另一个标志来跟踪用户何时单击取消按钮,并且对于表单上的每个字段,在(模糊)处理程序中,在超时内检查它,如下所示:

setTimeout(() => if (!userClickedCancel) this.isShowError = true, 500);

然后在取消点击处理程序中:

this.userClickedCancel = true;

这意味着取消代码应该在处理程序中的超时到期之前更改标志以检查它的值。

** 注意:如果您“关闭”表单而不是离开 **

此外,如果您不是在导航,而是可能“隐藏”表单(或关闭模式),您还应该在取消处理程序中将 isShowError 标志设置为 false(对于用户点击提交的情况,表单是无效,然后他们单击取消,然后您再次重新加载表单)。

【讨论】:

【参考方案4】:

你能做的就是把按钮改成一个好的、老式的

    <input type="submit" value="submit" .... /> tag.

并将取消按钮更改为:

    <input type="button" value="cancel" (click)="your event here" />

提交按钮将触发表单,因为您已经调用了提交事件。

这应该可以解决您的问题或遇到此问题的任何其他人。

【讨论】:

【参考方案5】:

我知道我已经迟到了,但它可能会对某人有所帮助!

如果有人使用 ReactiveForm 并在 formGroup 中添加一个清除按钮并使用 click 方法,那么它肯定会清除表单!但它也会将空白表单提交给服务器!为了防止这种情况,我使用了 2 种方法!

1. Use <i> tag instead of <button>
2. use type = "Reset"

在这两种情况下,单击取消按钮时它都不会调用服务器 API。

例子:

 <button class="example-button-row" type="reset" mat-flat-button color="primary"
        (click)="sendEmailGroup.reset()"><i class="material-icons">cleaning_services</i> Clear </button>

【讨论】:

以上是关于Angular 2 表单验证器弄乱了取消按钮的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2008 表单设计器弄乱了布尔属性值

Angular 2 提交时触发表单验证

如何在不弄乱下拉值的情况下使 Angular Reactive Formarray 中的级联下拉菜单工作

如何修复 Bootstrap 使其不会弄乱登录表单和页脚?

从组件调用的 angular 4 指令的多个实例弄乱了输入值

Angular 2+多部分表单验证,如何检查单个输入的有效性