Formes réactives de la marque de champs touché
J'ai du mal à trouver comment faire pour marquer tous les champs du formulaire comme touché.
Le principal problème est que si je ne touche pas de champs et d'essayer de soumettre le formulaire de validation de l'erreur de ne pas montré. J'ai réservé pour ce morceau de code dans mon contrôleur.
Mon idée est simple:
- utilisateur clique sur le bouton soumettre
- tous les champs marques comme évoqué
- erreur de formatage, les rediffusions et affiche les erreurs de validation
Si quelqu'un a une autre idée de la façon de montrer les erreurs sur soumettre, sans l'application d'une nouvelle méthode - s'il vous plaît de les partager. Merci!
Ma forme simplifiée:
<form class="form-horizontal" [formGroup]="form" (ngSubmit)="onSubmit(form.value)">
<input type="text" id="title" class="form-control" formControlName="title">
<span class="help-block" *ngIf="formErrors.title">{{ formErrors.title }}</span>
<button>Submit</button>
</form>
Et mon contrôleur:
import {Component, OnInit} from '@angular/core';
import {FormGroup, FormBuilder, Validators} from '@angular/forms';
@Component({
selector : 'pastebin-root',
templateUrl: './app.component.html',
styleUrls : ['./app.component.css']
})
export class AppComponent implements OnInit {
form: FormGroup;
formErrors = {
'title': ''
};
validationMessages = {
'title': {
'required': 'Title is required.'
}
};
constructor(private fb: FormBuilder) {
}
ngOnInit(): void {
this.buildForm();
}
onSubmit(form: any): void {
//somehow touch all elements so onValueChanged will generate correct error messages
this.onValueChanged();
if (this.form.valid) {
console.log(form);
}
}
buildForm(): void {
this.form = this.fb.group({
'title': ['', Validators.required]
});
this.form.valueChanges
.subscribe(data => this.onValueChanged(data));
}
onValueChanged(data?: any) {
if (!this.form) {
return;
}
const form = this.form;
for (const field in this.formErrors) {
if (!this.formErrors.hasOwnProperty(field)) {
continue;
}
//clear previous error message (if any)
this.formErrors[field] = '';
const control = form.get(field);
if (control && control.touched && !control.valid) {
const messages = this.validationMessages[field];
for (const key in control.errors) {
if (!control.errors.hasOwnProperty(key)) {
continue;
}
this.formErrors[field] += messages[key] + ' ';
}
}
}
}
}
Vous devez vous connecter pour publier un commentaire.
La fonction suivante explore par le biais de contrôles dans un formulaire de groupe et doucement la touche. Parce que les contrôles de terrain est un objet, le code Objet d'appel.les valeurs de() sur la forme du groupe de contrôle de terrain.
(<any>Object).values(formGroup.controls)
àObject.keys(formGroup.controls).map(x => formGroup.controls[x])
(à partir de stackoverflow.com/questions/42830257/...)controls
au début de la fonction de sorte qu'il devrait être le suivant à la place:if (control.controls) { markFormGroupTouched(control); }
touched
veut simplement dire que l'entrée était floue une fois. Pour faire des erreurs apparaissent, j'ai également eu aussi appelupdateValueAndValidity()
sur mes contrôles.Quant à @chef-d'œuvre de la réponse.
J'ai essayé cette solution, mais j'ai une erreur lorsque la fonction essayé de creuser, de manière récursive, à l'intérieur d'un FormGroup, parce qu'il est en train de passer un FormControl argument, au lieu d'un FormGroup, à cette ligne:
control.controls.forEach(c => this.markFormGroupTouched(c));
Voici ma solution
Boucle dans les contrôles de formulaire et en les marquant comme évoqué également de travailler:
formGroup
contient d'autresformGroup
sC'est ma solution
J'ai eu ce problème, mais a trouvé la "bonne" façon de le faire, en dépit de ne pas être en aucune Angulaire tutoriel que j'ai jamais trouvé.
Dans votre code HTML, sur la
form
tag, ajouter le même Modèle de Référence Variable#myVariable='ngForm'
('hashtag' variable) que le Modèle axé sur les Formes des exemples d'utilisation, en plus de ce que les Formes Réactives exemples d'utilisation:<form [formGroup]="myFormGroup" #myForm="ngForm" (ngSubmit)="submit()">
Vous avez maintenant accès à
myForm.submitted
dans le modèle qui vous pouvez utiliser au lieu de (ou en plus)myFormGroup.controls.X.touched
:<div *ngIf="myForm.submitted" class="text-error">
<span *ngIf="myFormGroup.controls.myFieldX.errors?.badDate">invalid date format</span>
<span *ngIf="myFormGroup.controls.myFieldX.errors?.isPastDate">date cannot be in the past.</span>
</div>
Sais que
myForm.form === myFormGroup
est vrai... tant que vous n'oubliez pas la="ngForm"
partie. Si vous utilisez#myForm
seul, il ne fonctionnera pas parce que la var sera mis à La place de la Directive sur la conduite de cet élément.Sais que
myFormGroup
est visible dans votre Composant de la machine a ecrire de code par les Formes Réactives de tutoriels, maismyForm
n'est pas, à moins que vous le transmettre par le biais d'un appel de méthode, commesubmit(myForm)
àsubmit(myForm: NgForm): void {...}
. (AvisNgForm
est dans le titre en majuscules dans le texte dactylographié mais chameau cas en HTML.)Une solution sans récursivité
Pour ceux qui s'inquiètent de la performance, j'ai trouvé une solution qui n'utilise pas la récursivité, bien qu'il passe en revue tous les contrôles à tous les niveaux.
Cette solution fonctionne forme à la fois FormGroup et aussi FormArray.
Vous pouvez jouer avec elle ici: angulaire de-marque-comme-touché
markAsTouched()
n'a pas touché les éléments enfants?markAsTouched()
ne pas marquer les éléments enfants - github.com/angular/angular/issues/11774 . TL;DR: C'est pas un bug.Voici comment je le fais. Je ne veux pas l'erreur des champs de montrer qu'après la soumission de la touche est enfoncée (ou la forme est touché).
JS:
HTML:
J'ai rencontré le même problème, mais je ne veux pas "polluer" mes composants avec le code qui gère cela. Surtout depuis que j'ai besoin de ce dans de nombreuses formes et je ne veux pas répéter le code à diverses occasions.
Donc j'ai créé une directive (en utilisant les réponses postées jusqu'à présent). La directive décore NgForm de
onSubmit
-Méthode: Si le formulaire n'est pas valide, il marque tous les champs touché et abandonne la soumission. Sinon, l'habitude onSubmit-Méthode exécute normalement.Utilisation:
C'est le code que j'utilise effectivement.
HTML:
Ce code fonctionne pour moi:
Dans Angulaire 8+ vous pouvez simplement utiliser
pour marquer un contrôle et son descendant contrôles touché.
Je comprends parfaitement l'OP de la frustration. J'utilise la suite:
Fonction d'utilité:
Utilisation:
Notez que cette fonction n'a pas encore de répondre pour les contrôles imbriqués.
Voir ce bijou.
Jusqu'à présent la solution la plus élégante que j'ai vu.
Code complet
Angulaires v8, vous avez ce avec l'aide de la
markAllAsTouched
méthode.Comme un exemple, vous pourriez l'utiliser comme
Voir la doc officielle : https://angular.io/api/forms/AbstractControl#markallastouched