Angular2 - 从外部验证并提交表单

时间:2016-06-27 12:57:59

标签: angular angular2-forms

我有一个看起来像这样的简单表格

<form (ngSubmit)="save()" #documentEditForm="ngForm">
...
</form>

并且需要提交表单并从外部检查有效性

例如。以编程方式提交,或使用<button type="submit">标记之外的<form>提交。

9 个答案:

答案 0 :(得分:62)

正确的做法实际上是

<form (ngSubmit)="save()" id="ngForm" #documentEditForm="ngForm"> 
    ... 
</form>

<button class="btn-save button primary" form="ngForm" [disabled]="!documentEditForm.form.valid">
    SAVE
</button>

表单需要具有ID id="example-form",并且提交按钮在form="example-form"

中具有匹配的ID

答案 1 :(得分:58)

了解如何操作:

  • 触发提交<formname>.ngSubmit.emit()
  • 使用<formname>.form.valid
  • 获取表单状态

示例:

<form (ngSubmit)="save()" #documentEditForm="ngForm">
...
</form>

<button class="btn-save button primary"
(click)="documentEditForm.ngSubmit.emit()"
[disabled]="!documentEditForm.form.valid">SAVE</button>

编辑:正如@ yuriy-yakovenko指出的那样,您应该在组件代码中添加以下内容:

@ViewChild('documentEditForm') documentEditForm: FormGroupDirective; 

如果你还没有完成,请不要忘记导入FormGroupDirective

答案 2 :(得分:6)

重要提示:如果使用Angular材质表单控件+反应表单

调用<fieldType name="price" class="solr.IntPointField" sortMissingLast="true" omitNorms="true"/> 以在Caused by: java.lang.NumberFormatException: For input string: "7.5" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) at org.apache.solr.schema.IntPointField.createField(IntPointField.java:181) at org.apache.solr.schema.PointField.createFields(PointField.java:216) at org.apache.solr.update.DocumentBuilder.addField(DocumentBuilder.java:72) at org.apache.solr.update.DocumentBuilder.toDocument(DocumentBuilder.java:179) 指令上正确设置onSubmit(undefined)

重要提示:该指令与角度形式本身不一样(更多信息见下文)

这是sourcecode for the [formGroup] directive的一部分。 (用于反应形式)

submitted = true

您这样声明:

[formGroup]

您可以通过以下方式在 onSubmit($event: Event): boolean { (this as{submitted: boolean}).submitted = true; syncPendingControls(this.form, this.directives); this.ngSubmit.emit($event); return false; } 文件中获得对<form [formGroup]="form" #ngForm="ngForm"> 的引用:

ngForm

您可以这样使用它:

ts

示例:

@ViewChild('ngForm') 
ngForm: NgForm;

如果您只是打电话给this.formRef.onSubmit(undefined) ,因为其他一些答案表明您不会获得所有重要的// html <form [formGroup]="form" #formRef="ngForm"> // ...Form Controls </form> // component.ts export class MyComponent { @ViewChild('formRef') formRef: FormGroupDirective; form: FormGroup = new FormGroup({ myInput: new FormControl(''), //etc... }); submitFormProgrammatically() { this.formRef.onSubmit(undefined); } } 设置。

为什么这很重要?

如果您使用任何Angular CDK或Angular Material控件,则除非触摸表单字段(单击或获得焦点)或提交整个表单,否则不会显示错误条件。

因此,如果缺少必填字段鼠标/光标从未输入,那么即使您进行this.ngForm.ngSubmit.emit(),该字段也不会显示为红色(因为{{1 }}用于表单,而控件具有submitted = true)。

那么如何使用常规的提交按钮正常工作?

通常,如果您有ngSubmit.emit()(在submitted = false标记内),它将触发标准HTML touched = false提交(与Angular无关)-这会引发标准{{ 1}}事件在表单标签上。

如果<button type='submit'>Submit</button>标签上还带有<form>指令(如上所示),则该指令会“捕获” HTML表单<form>事件,这就是导致{上面的{1}}函数被调用。

这又引发了submit事件-如果您需要做进一步的处理,就可以抓住自己,例如显示警报。

因此,使用材质控件时,调用<form>而不是[formGroup]非常重要,以使验证处理正常工作。 $ event参数可以为null或未定义。

进一步阅读:查看submit(仅适用于Angular CDK / Material)以了解确切的规则。如果解决默认值的限制变得过于复杂,则可以创建自己的

更令人困惑的是: onSubmit()指令与仅保存数据的ngSubmit是不同的对象。仅指令上有onSubmit-ngSubmit.emit上有ErrorStateMatcher[formGroup]FormGroup之类的东西。

答案 3 :(得分:4)

如果您使用的是Reactive Forms,请使用formGroup invalid属性来禁用提交按钮:

<button  
  form="ngForm"
  [disabled]=" editor.invalid>Enviar</button> 

...

<form [formGroup]="editor"  id="ngForm"   (ngSubmit)="save()" novalidate >
...
</form>

答案 4 :(得分:2)

使用

对我有用的技巧
  • 反应表格
  • Angular2
  • 含。 IE

是这样的:

<!-- real button will simulate click on invisible button (cf. form) -->
<button onclick="document.getElementById('hiddenSaveButtonForMicrosoftWithLove').click()">
  The Real Button outside forms
</button>

<form>
  <!-- will be called in the background and is never visible -->
  <button id="hiddenSaveButtonForMicrosoftWithLove" type="submit" style="display: none;">hiddenSaveButtonForMicrosoftWithLove</button>
</form>

答案 5 :(得分:2)

这对我有用。

<form #editForm="ngForm">
  <button type="button" (click)="editForm.submitted = true; editForm.ngSubmit.emit(); anotherMethod();">
    Submit programatically
  </button>
</form>

关键是同时设置submitted = true和发出ngSubmit事件。

答案 6 :(得分:0)

在我的情况下,以下解决方案有效,请尝试以下简单解决方案。我不确定它是否可以在所有条件下正常工作

<form #documentEditForm="ngForm" id="ngForm" (ngSubmit)="save(documentEditForm.valid)"> 
    ...Your Input Elements... 
</form>

按钮应在表单外部声明,如下所示:

<button form="ngForm">Submit</button>

表单的验证应通过以下条件检入 save()

save(isValid:boolean){
    if(isValid) {
        ...Your code to save details...
    }
}

希望这个简单的解决方案对您有所帮助。

答案 7 :(得分:0)

此示例将在Angular 6及更高版本中工作

<form (ngSubmit)="save()" id="ngForm" [formGroup]="form"> 
    ... 
</form>

<button type="submit" class="btn-save button primary" form="ngForm">Save</button>

答案 8 :(得分:0)

我写这个答案是希望它可以帮助某人。我花了一整天的时间试图解决这个问题,遵循其中的每个答案和评论......但我仍然收到错误消息,即找不到#documentEditForm(我的等价物)(无法读取未定义的属性 x ......) ,无论我尝试什么。

我之所以认为在表单标记的“外部”有问题,是因为一旦我将提交/验证按钮放在 </form> 标记内,这个问题就消失了。我去了这个兔子洞,但后来意识到我需要在表格之外的正当理由。

但后来我意识到我必须做两件事来解决这个问题,方法是 (1) 在验证时将 ? 添加到 ngForm 的名称中,以及 (2) 实现 ViewChild(NgForm) documentEditForm!: NgForm

<form #documentEditForm="ngForm">
...
</form>

<button class="btn-save button primary" (click)="save()" [disabled]="documentEditForm?.invalid">
   SAVE
</button>

component.ts 内部:

import { Component, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';

export class XYZComponent implements OnInit {

  @ViewChild(NgForm) documentEditForm!: NgForm;

...

当在 Angular 中使用模板驱动的表单时,并且您使用 #form_name="ngForm" 语法,您将其暴露给表单内部。但是,当您使用 ViewChild 时,您会将表单公开给整个组件,而不仅仅是在表单内部。请记住,如果应用无法编译或出现意外输出/错误,请尝试使用旧的 ?