J'ai un formulaire réactif pour lequel aucun champ n'est requis lors du chargement. Si une option est ajoutée qui ajoutera des éléments de formulaire supplémentaires dans le groupe formGroup, les nouveaux champs affichés seront tous obligatoires. Si le champ de surnom est masqué, vous devriez pouvoir envoyer le formulaire correctement. Si le pseudo est affiché, le champ pseudo est obligatoire et le bouton d'envoi est désactivé jusqu'à ce que le champ pseudo soit plein ..__ Voici un exemple de ce que je veux faire.
Ma question est, comment puis-je activer/désactiver la validation une fois que l'élément de formulaire est affiché/masqué?
App.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
@NgModule({
imports: [ BrowserModule, FormsModule, ReactiveFormsModule ],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
App.component.ts
import { Component, OnInit } from '@angular/core';
import { Validators, FormControl, FormGroup, FormBuilder } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'My Reactive Form';
constructor(
private fb: FormBuilder
) {}
myForm: FormGroup;
showNick: boolean = false;
ngOnInit() {
this.myForm = this.fb.group({
'firstName': new FormControl(),
'nickName': new FormControl('', Validators.required),
'lastName': new FormControl()
})
}
toggleNick() {
this.showNick = !this.showNick;
}
}
app.component.html
<form [formGroup]="myForm">
<div class="my-box">
<label>
First Name
<input type="text" formControlName="firstName">
</label>
</div>
<div class="my-box nickname">
Nickname? <a (click)="toggleNick()">yes / no</a>
</div>
<div class="my-box" *ngIf="showNick">
<label>
Nickname
<input type="text" formControlName="nickName">
<span class="validation-message" *ngIf="!myForm.controls['nickName'].valid && myForm.controls['nickName'].dirty">
This field is invalid
</span>
</label>
</div>
<div class="my-box">
<label>
Last Name
<input type="text" formControlName="lastName">
</label>
</div>
<button [disabled]="myForm.invalid">Submit</button>
</form>
Dans ma demande, j'ai une exigence similaire. Si l'utilisateur demande à être averti par SMS, le téléphone est requis. Sinon, le numéro de téléphone est facultatif.
J'ai écrit cette méthode:
setNotification(notifyVia: string): void {
const phoneControl = this.customerForm.get('phone');
if (notifyVia === 'text') {
phoneControl.setValidators(Validators.required);
} else {
phoneControl.clearValidators();
}
phoneControl.updateValueAndValidity();
}
Il est appelé à partir de ce code qui se trouve dans le ngOnInit:
this.customerForm.get('notification').valueChanges
.subscribe(value => this.setNotification(value));
Si l'utilisateur modifie le champ de notification (qui est un bouton radio), il appelle la méthode setNotification
en transmettant la valeur. Si la valeur est notification par 'texte', la validation du téléphone est définie sur Requise.
Sinon, la validation du champ de téléphone est effacée.
Ensuite, il doit appeler updateValueAndValidity
pour mettre à jour les informations du formulaire avec cette nouvelle validation.
Même les champs sont cachés de l'utilisateur, les champs sont actifs dans le réactif. Donc, vous devez simplement désactiver le champ de réactif en utilisant le code suivant
this.myForm.get("nickName").disable();
Changer la fonction toggleNick () comme indiqué ci-dessous
toggleNick() {
this.showNick = !this.showNick;
if(showNick) {
this.myForm.get("nickName").enable();
} else {
this.myForm.get("nickName").disable();
}
}
Je pense que la meilleure option pour ce faire est d'intégrer les champs de la forme initiale à toutes les validations et lorsque vous souhaitez désactiver et activer les champs ou les formulaires imbriqués par programmation.
Exemple: https://stackblitz.com/edit/angular-ojebff
https://stackblitz.com/edit/angular-ojebff?embed=1&file=app/input-errors-example.html
Je n'ai pas trouvé ces solutions viables si vous avez beaucoup de champs optionnels dans un formulaire complexe.
Ce que j'ai fait est comme ça:
export class MyComponent implements AfterViewChecked {
@ViewChildren(FormControlName) allFormControlInDOM: QueryList<FormControlName>;
// ...
ngAfterViewChecked(): void {
// We must disable the controls that are not in the DOM
// If we don't, they are used for validating the form
if (this.allFormControlInDOM) {
const controls: { [p: string]: AbstractControl } = this.myForm.controls;
for (const control in controls) {
if (controls.hasOwnProperty(control) && controls[control] instanceof FormControl) {
const found = this.allFormControlInDOM.find((item: FormControlName) => item.name === control);
if (found) {
controls[control].enable();
} else {
controls[control].disable();
controls[control].setValue(null);
}
}
}
}
}
// ...
}
J'espère que ça peut aider :)