web-dev-qa-db-fra.com

Angular2 - Validez et envoyez le formulaire de l'extérieur

J'ai un formulaire simple qui ressemble à ceci

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

et il faut soumettre le formulaire et vérifier sa validité de l'extérieur 

par exemple. Soumettez-le par programme ou avec un <button type="submit"> situé en dehors des balises <form>.

27
Philipp

Découvrez comment le faire:

  • déclencher soumettre avec <formname>.ngSubmit.emit()
  • obtenir le statut du formulaire avec <formname>.form.valid

Exemple:

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

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

Edit: Comme @ yuriy-yakovenko l’a fait remarquer, vous devez ajouter dans votre code de composant les éléments suivants:

@ViewChild('documentEditForm') documentEditForm: FormGroupDirective; 

Et n'oubliez pas d'importer la FormGroupDirective si vous ne l'avez pas encore fait

52
Philipp

La bonne façon de faire est réellement

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

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

Le formulaire doit avoir un ID id="example-form" et le bouton d'envoi un ID correspondant dans le form="example-form".

57
Yodacheese

Si vous utilisez des formulaires réactifs, utilisez la propriété formGroup invalid pour désactiver le bouton d'envoi:

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

...

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

Un truc qui a fonctionné pour moi en utilisant 

  • Formes Réactives
  • Angulaire2
  • incl. C'EST À DIRE

était-ce:

<!-- 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>
3
Marcel

Important: si vous utilisez des formes de matériaux angulaires contrôles + formes réactives

Appelez onSubmit(undefined) pour définir correctement submitted = true dans la directive [formGroup]

Voici une partie du code - pour la directive [formGroup] . (pour les formes réactives)

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

Vous le déclarez comme ceci:

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

Et vous pouvez obtenir une référence à ngForm dans votre fichier ts avec:

@ViewChild('ngForm') 
ngForm: NgForm;

Vous l'utilisez comme ceci:

this.formRef.onSubmit(undefined)

Exemple:

// 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);
    }
}

Si vous deviez simplement appeler this.ngForm.ngSubmit.emit() comme certaines réponses l’ont suggéré, vous n’obtiendrez pas l’ensemble important submitted = true.

Pourquoi est-ce important? 

Si vous utilisez des contrôles CDK angulaires ou Matériau angulaire, la condition d'erreur ne s'affiche pas sauf si le champ de formulaire a été touché (clic activé ou focus sélectionné) OR, le formulaire dans son ensemble a été soumis.

Donc, si vous avez un champ obligatoire manquant que la souris/le curseur n'a jamais entré, alors ce champ ne sera pas affiché en rouge, même si vous avez ngSubmit.emit() (car submitted = false pour le formulaire et le contrôle a touched = false).

Alors, comment ça marche normalement avec un bouton de soumission normal?

Normalement, si vous avez <button type='submit'>Submit</button> (à l'intérieur de la balise <form>), cela déclenche l'envoi du <form> HTML standard (rien à voir avec Angular) - et cela déclenche un événement submit standard sur la balise de formulaire.

SI cette balise <form> a également une directive [formGroup] (comme indiqué ci-dessus), l'événement HTML submit du formulaire HTML est «attrapé» par la directive et c'est ce qui explique l'appel de la fonction onSubmit() ci-dessus. 

Cela déclenche à son tour l'événement ngSubmit - que vous pouvez détecter vous-même si vous devez effectuer un traitement ultérieur - comme l'affichage d'une alerte.

Il est donc très important d'appeler onSubmit et non ngSubmit.emit pour que le traitement de validation fonctionne lors de l'utilisation de contrôles de matériaux. Le paramètre $ event peut simplement être null ou non défini.

Autres lectures: Regardez ErrorStateMatcher (pour CDK angulaire/Matériel uniquement) pour voir les règles exactes.

Encore plus déroutant: _ La directive [formGroup] N'EST PAS le même objet que FormGroup qui ne contient que des données. submitted est la seule directive - alors que FormGroup a des éléments tels que touched, pristine, dirty.

2
Simon_Weaver

La solution ci-dessous fonctionne dans mon cas, veuillez essayer cette solution simple. Je ne sais pas si cela fonctionnera dans toutes les conditions:

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

Le bouton doit être déclaré en dehors du formulaire comme ceci:

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

La validation du formulaire doit s’enregistrer dans save () en respectant les conditions suivantes

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

J'espère que cette solution simple vous aidera.

0
ChintanThummar