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

Phi*_*ipp 41 angular2-forms angular

我有一个看起来像这样的简单形式

<form (ngSubmit)="save()" #documentEditForm="ngForm">
...
</form>
Run Code Online (Sandbox Code Playgroud)

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

例如.以编程方式提交,或者<button type="submit"><form>标记之外提交.

Yod*_*ese 69

实际上,正确的做法是

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

<button class="btn-save button primary" form="ngForm" [disabled]="!documentEditForm.form.valid">
    SAVE
</button>
Run Code Online (Sandbox Code Playgroud)

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

  • 我只想补充一点.似乎angular不关心按钮在窗体外部被禁用 - 即如果你在输入元素上按Enter键它仍然会尝试提交它.我不确定这是否真的是Angular本身的错误,或者还有其他解决方案.一个快速的解决方法就是去(ngSubmit)="form.valid && save()" (4认同)
  • `documentEditForm` 还没有定义! (3认同)
  • fyi IE&Edge不支持'button'上的'form'属性,因此在此处不起作用(afaik)。 (2认同)
  • @bob Edge 从 Edge 16 开始支持此功能([有关兼容性,请参阅 MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Browser_compatibility) 详细信息) (2认同)

Phi*_*ipp 65

找到了怎么做:

  • 触发器提交 <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>
Run Code Online (Sandbox Code Playgroud)

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

@ViewChild('documentEditForm') documentEditForm: FormGroupDirective; 
Run Code Online (Sandbox Code Playgroud)

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

  • ngSubmit未定义 (5认同)
  • 如果我调用emit,那么我的ngForm的submited(布尔属性)也不会更改为true.你能帮忙吗? (4认同)
  • @VievChild('documentEditForm')documentEditForm:FormGroupDirective; 也需要 (3认同)
  • this.documentEditForm.onSubmit(事件); //来自TS文件 (2认同)
  • 重要提示:调用 `.ngSubmit.emit` 不会将 `subscribed` 设置为 true。如果您关心处理表单是否已提交,请改用“.onSubmit(null)”,否则“.subscribed”将为 false。 (2认同)

Sim*_*ver 13

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

呼叫onSubmit(undefined)正确设置submitted = true[formGroup]指令

注意:伪指令是不一样的对象作为角形式本身(更下面上)

这是伪指令源代码[formGroup]的一部分。(用于反应形式)

@Directive({
  selector: '[formGroup]',
  providers: [formDirectiveProvider],
  host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},
  exportAs: 'ngForm'
})
export class FormGroupDirective extends ControlContainer implements Form,
    OnChanges {
  /**
   * @description
   * Reports whether the form submission has been triggered.
   */
  public readonly submitted: boolean = false;

 .....

 onSubmit($event: Event): boolean {
    (this as{submitted: boolean}).submitted = true;
    syncPendingControls(this.form, this.directives);
    this.ngSubmit.emit($event);
    return false;
 }
Run Code Online (Sandbox Code Playgroud)

您可以这样使用它:

<form [formGroup]="form" #formRef="ngForm">
Run Code Online (Sandbox Code Playgroud)

你可以得到的一个参考FormGroupDirectivets与文件:

@ViewChild('formRef') 
formRef: FormGroupDirective;
Run Code Online (Sandbox Code Playgroud)
  • 注意:NgForm是创建标签时自动应用的另一条指令<form>
  • 令人困惑的注解:NgForm和和FormGroupDirectiveexportAs: 'ngForm'在其源代码中(并且也都声明submittedngSubmit属性)。但是当我放进#ngForm='ngForm'去时,我得到的对象类型FormGroupDirective不是NgForm(在调试器中验证)。我不确定为什么-但这就是为什么我宣布FormGroupDirective不是NgForm-我认为也许第一个获胜。

您可以这样使用它:

this.formRef.onSubmit(undefined)
Run Code Online (Sandbox Code Playgroud)

例:

// 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您只是打电话给this.formRef.ngSubmit.emit()其他答案,则您将无法获得所有重要的答案submitted = true

为什么这么重要?

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

因此,如果缺少必填字段,而鼠标/光标从未输入过,则即使您这样做,该字段也不会显示为红色ngSubmit.emit()(因为submitted = false表格和控件都有touched = false)。

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

通常,如果您有<button type='submit'>Submit</button>(在<form>标记内),它将触发标准HTML <form>提交(与Angular无关)-并submit在form标记上引发一个标准事件。

如果该<form>标签上也有一个[formGroup]指令(如上所示),则submit该指令会“捕获” HTML表单事件,这就是导致上述onSubmit()函数被调用的原因。

反过来,这引发了ngSubmit事件-如果需要进一步处理,您可以抓住自己-例如显示警报。

因此,使用材质控件时,调用onSubmit而不是ngSubmit.emit使验证处理正常工作非常重要。$ event参数可以为null或未定义。

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

更令人困惑:[formGroup]指令是不是同一个对象作为FormGroup刚刚成立的数据。只有指令有submitted它-而FormGroup有一些事情,如touchedpristinedirty


小智 7

此示例适用于 Angular 6 及更高版本

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

<button type="submit" class="btn-save button primary" form="ngForm">Save</button>
Run Code Online (Sandbox Code Playgroud)


Mar*_*cel 5

一个对我有用的技巧

  • 反应形式
  • 角度2
  • 含税 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>
Run Code Online (Sandbox Code Playgroud)


Jav*_*ano 5

如果您使用的是反应式表单,请使用formGroup invalid属性禁用提交按钮:

<button  
  form="ngForm"
  [disabled]=" editor.invalid>Enviar</button> 
Run Code Online (Sandbox Code Playgroud)

...

<form [formGroup]="editor"  id="ngForm"   (ngSubmit)="save()" novalidate >
...
</form>
Run Code Online (Sandbox Code Playgroud)