Angular2 - Validate and submit form from outside

2019-01-16 19:08发布

I have a simple form that looks like this

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

and need to submit the the form and check its validity from outside

eg. Either submit it programatically, or with a <button type="submit"> that is outside the <form> tags.

6条回答
走好不送
2楼-- · 2019-01-16 19:46

Important: if using Angular material form controls + reactive forms

Call onSubmit(undefined) to properly set submitted = true on the [formGroup] directive

Here's part of the sourcecode for the [formGroup] directive. (for reactive forms)

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

You use it like this:

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

And you can get a reference to ngForm in your ts file with:

@ViewChild('ngForm') 
ngForm: NgForm;

If you were to just call this.ngForm.ngSubmit.emit() as some other answers have suggested you won't get the all important submitted = true set.

Why does this matter?

If you're using any Angular CDK or Angular Material controls the error condition isn't displayed unless the form field has been touched (clicked or gained focus) OR the form as a whole has been submitted.

So if you have a missing required field that the mouse/cursor has never entered then that field won't be shown in red even if you do ngSubmit.emit() (because submitted = false for the form and the control has touched = false).

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

Normally if you have <button type='submit'>Submit</button> (inside the <form> tag) it will trigger the standard HTML <form> to submit (nothing to do with Angular) - and that raises a standard submit event on the form tag.

IF that <form> tag also has a [formGroup] directive on it (as shown above) then the HTML form submit event is 'caught' by the directive and that's what causes the onSubmit() function above to be called.

This in turn raises the ngSubmit event - which you can catch yourself if you need to do further processing - like showing an alert.

So it's very important to call onSubmit and not ngSubmit.emitto get the validation handling to work when using material controls. The $event parameter can just be null or undefined.

Further reading: Look at ErrorStateMatcher (for Angular CDK/Material only) to see the exact rules.

Even more confusing: The [formGroup] directive is NOT the same object as FormGroup which just holds data. Only the directive has submitted on it - whereas FormGroup has things like touched, pristine, dirty.

查看更多
啃猪蹄的小仙女
3楼-- · 2019-01-16 19:55

Found out how to do it:

  • trigger submit with <formname>.ngSubmit.emit()
  • get form status with <formname>.form.valid

Example:

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

<button class="btn-save button primary"
(click)="documentEditForm.ngSubmit.emit()"
[disabled]="!documentEditForm.form.valid">SAVE</button>
查看更多
霸刀☆藐视天下
4楼-- · 2019-01-16 20:08

If you are using Reactive Forms use the formGroup invalid property to disable the submit button:

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

...

<form [formGroup]="editor"  id="ngForm"   (ngSubmit)="save()" novalidate >
...
</form>
查看更多
时光不老,我们不散
5楼-- · 2019-01-16 20:09

Below solution is working in my case, please try this simple solution. I am not sure, if it will be working into all the conditions:

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

The button should be declared outside the form like this:

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

The validation of the form should check into save() by following conditions

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

Hope this simple solution will help you.

查看更多
来,给爷笑一个
6楼-- · 2019-01-16 20:10

A trick that worked for me using

  • Reactive Forms
  • Angular2
  • incl. IE

was this:

<!-- 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>
查看更多
ら.Afraid
7楼-- · 2019-01-16 20:13

The correct way of doing is actually

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

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

The form needs to have an ID id="example-form" and the submit button a matching ID in the form="example-form"

查看更多
登录 后发表回答