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

问题描述 投票:30回答:7

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

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

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

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

angular angular2-forms
7个回答
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


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


9
投票

重要提示:如果使用Angular材质形式控制+反应形式

调用onSubmit(undefined)submitted = true指令上正确设置[formGroup]

注意:该指令与角形式本身不是同一个对象(更多内容如下)

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

@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;
 }

你这样使用它:

<form [formGroup]="form" #formRef="ngForm">

您可以在FormGroupDirective文件中获取对ts的引用:

@ViewChild('formRef') 
formRef: FormGroupDirective;
  • 注意:NgForm是在创建<form>标记时自动应用的另一个指令。
  • 令人困惑的注意:NgFormFormGroupDirective的源代码中都有exportAs: 'ngForm'(并且它们都声明了submittedngSubmit属性)。但当我把#ngForm='ngForm'我得到一个FormGroupDirective类型的对象而不是NgForm(在调试器中验证)。我不确定为什么 - 但这就是为什么我宣布它为FormGroupDirective而不是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);
    }
}

如果你只是打电话给this.formRef.ngSubmit.emit(),因为其他一些答案建议你不会得到所有重要的submitted = true设置。

为什么这很重要?

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

因此,如果您有一个缺少必需字段,鼠标/光标从未输入过,那么即使您执行ngSubmit.emit(),该字段也不会显示为红色(因为表单和控件的submitted = false具有touched = false)。

So how does it work normally with a regular submit button?

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

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

这反过来引发了ngSubmit事件 - 如果你需要进行进一步的处理,你可以自己捕捉 - 比如显示警报。

所以调用onSubmit非常重要,而不是ngSubmit.emitto在使用材质控件时可以使验证处理工作。 $ event参数可以为null或undefined。

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

更令人困惑的是:[formGroup]指令与FormGroup不同,它只保存数据。只有指令上有submitted - 而FormGroup有像touchedpristinedirty这样的东西。


4
投票

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

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

...

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

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>

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...
    }
}

希望这个简单的解决方案能帮到你。


0
投票

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

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

<button type="submit" class="btn-save button primary" form="ngForm">Save</button>
© www.soinside.com 2019 - 2024. All rights reserved.