45
votes

Le groupe Formbuilder est obsolète

J'ai migré mon projet vers Angular 11 et j'ai remarqué que les validations globales que j'ai ajoutées font formbuilder.group déprécié avec le message:

class ValidateThirdNumber {
  static validate(control: AbstractControl): void {
      if (control) {
      const isMultiFlavor = control.get('isMultiFlavor')?.value;
      const ingredientFlavor = control.get('ingredientFlavor')?.value;
      const ingredientBrand = control.get('ingredientBrand')?.value;
      const ingredientName = control.get('ingredientName')?.value;
      if (isMultiFlavor && ingredientFlavor.trim().length === 0) {
        control.get('ingredientFlavor')?.setErrors({required_if: true});
      } else {
        control.get('ingredientFlavor')?.setErrors(null);
      }
      if (!ingredientFlavor && !ingredientBrand && !ingredientName) {
        control.get('ingredientName')?.setErrors({required_at_least: true});
        control.get('ingredientFlavor')?.setErrors({required_at_least: true});
        control.get('ingredientBrand')?.setErrors({required_at_least: true});
      } else {
        control.get('ingredientName')?.setErrors(null);
        control.get('ingredientFlavor')?.setErrors(null);
        control.get('ingredientBrand')?.setErrors(null);
      }
      if (ingredientBrand && ingredientName && ingredientName === ingredientBrand) {
        control.get('ingredientName')?.setErrors({not_the_same: true});
        control.get('ingredientBrand')?.setErrors({not_the_same: true});
      }
    }
  }
}

C'est donc déprécié:

  ingredientForm = this.fb.group({
    ingredientType: ['', Validators.required],
    ingredientFlavor: [''],
    isMultiFlavor: [''],
    ingredientBrand: [''],
    ingredientName: [''],
    imageFile: ['']
  }, {validators: [ValidateThirdNumber.validate]});

et sans l'option validators ce n'est pas.

mon validatethirdNumber validator:

group is deprecated: This api is not typesafe and can result in issues with Closure Compiler renaming.
Use the `FormBuilder#group` overload with `AbstractControlOptions` instead.

Comment le surcharger avec AbstractControloptions?


3 commentaires

Je pense que vous pouvez trouver la solution ici dans la section où la dépréciation est expliquée: angular.io/api/forms / Formbuilder


@Ploppy J'ai lu les documents avant de poster cette question, je n'ai malheureusement pas beaucoup aidé, je ne sais pas quoi faire


Veuillez essayer ceci - stackoverflow.com/a/70944514/4402335


4 Réponses :


45
votes

DESCRIPTION DU PROBLÈME

à partir du documentation Nous voyons deux lignes différentes avec le Group () Fonction

Groupe (ControlsConfig: {[Key: String]: any;}, Options ?: AbstractControlOptions): formgroup

et

Groupe (ControlsConfig: {[Key: String]: any;}, Options: {[key: String]: any;}): formgroup p >

La 2ème définition est ce qui est obsolète

La différence dans ces lignes est Options ?: AbstractControloptions et Options: {[clé: chaîne] : n'importe quel; }

Pour comprendre pourquoi Angular lance cette erreur, nous allons maintenant considérer AbstractControloptions

class ValidateThirdNumber {
  static validate(control: AbstractControl): ValidationErrors | null {
      if (control) {
      const isMultiFlavor = control.get('isMultiFlavor')?.value;
      const ingredientFlavor = control.get('ingredientFlavor')?.value;
      const ingredientBrand = control.get('ingredientBrand')?.value;
      const ingredientName = control.get('ingredientName')?.value;
      if (isMultiFlavor && ingredientFlavor.trim().length === 0) {
        control.get('ingredientFlavor')?.setErrors({required_if: true});
        return ({required_if: true});
      } else {
        control.get('ingredientFlavor')?.setErrors(null);
      }
      if (!ingredientFlavor && !ingredientBrand && !ingredientName) {
        control.get('ingredientName')?.setErrors({required_at_least: true});
        control.get('ingredientFlavor')?.setErrors({required_at_least: true});
        control.get('ingredientBrand')?.setErrors({required_at_least: true});
        return ({required_at_least: true});
      } else {
        control.get('ingredientName')?.setErrors(null);
        control.get('ingredientFlavor')?.setErrors(null);
        control.get('ingredientBrand')?.setErrors(null);
      }
      if (ingredientBrand && ingredientName && ingredientName === ingredientBrand) {
        control.get('ingredientName')?.setErrors({not_the_same: true});
        control.get('ingredientBrand')?.setErrors({not_the_same: true});
        return ({not_the_same: true});
      }
    }
    return null;
  }
}

Nous continuons à décomposer le problème en notant que la différence entre cette structure et votre structure est validatorfn []

type ValidationErrors = {
    [key: string]: any;
};

solution

Dans la description du problème, la solution consiste à modifier simplement le validatorfn

assurez-vous que votre validatorfn renvoie un validationerror ou si aucune erreur ne renvoie null De Définition de validationrrors

interface ValidatorFn {
  (control: AbstractControl): ValidationErrors | null
}


1 commentaires

Que se passe-t-il si le validateur personnalisé a une logique complexe qui ne serait pas en mesure de dire si le bloc SetErrors fonctionnera jusqu'à l'exécution? par exemple. quelque chose.ForEach (ctl => {si xxx alors seterror, else ...}), à quoi s'attendre à revenir dans ce scénario?



2
votes

Je reçois également la même erreur, je fais les modifications suivantes.

  • Assurez-vous que la signature de votre fonction Validator correspond comme celle-ci. (Une fonction qui reçoit un contrôle et renvoie de manière synchrone une carte des erreurs de validation si elle est présente, sinon nul.)

    • Fonction your_function_name (ObjectName: AbstractControl): ValidationErrors | nul { }
  • et vous pouvez changer de code dans le générateur de formulaire comme celui-ci.

    • const formOptions : abstractControloptions = {validators: your_function_name};
  • et dans l'objet Formbuilder passe au-dessus de l'objet FormOptions comme celui-ci

    • this.formObject = this.formbuilder.group ({ fullname: ['', [validators.requure]]] }, formOptions );

2 commentaires

Hé, pouvez-vous s'il vous plaît ajouter un exemple de code de travail ??


@Noahlubko, j'ai répondu à cela avec un exemple.



1
votes

Alors que Owen Kelvin Pour avoir:

  • Lors de la spécification de la fonction Validator, spécifiez uniquement le nom de la fonction ( c'est-à-dire , sans aucun paramètre)
  • Cette fonction validatrice doit accepter un et un seul paramètre de type AbstractControl
  • La fonction Validator doit retourner {key: value} ou null , mais pas juste null tous les temps. Return null quand il n'y a pas d'erreur à afficher.
  • Voici un exemple du formulaire déclaré dans le registre.ts :

    <div *ngIf="form.get('matchEmail.confirmEmail').hasError('mismatch')
        && (form.get('matchEmail.confirmEmail').dirty ||
        form.get('matchEmail.confirmEmail').touched)">
        <small>Confirmation email doesn't match</small>
    </div>
    

    La fonction Validator créera un nouveau Type d'erreur nommé comissent et peut être inséré dans le fichier registre.ts :

    matchEmail(group: AbstractControl) {
        let email: string = group.get('email').value;
        let confirmEmail: string = group.get('confirmEmail').value;
        if (email.localeCompare(confirmEmail) != 0) {
            //error
            group.get('confirmEmail')?.setErrors({ mismatch: true });
            return { mismatch: true };
        } else {
            //no error, return null (don't return { mismatch: false })
            return null;
        }
    }
    

    Votre HTML peut être quelque chose comme quelque chose comme Ceci (vous ne pouvez pas accéder à confirmMail directement, il doit être via le groupe dont il fait partie de matchmail.confirmEmail ):

    import { Component, OnInit } from '@angular/core';
    
    import {
      AbstractControl,
      FormBuilder,
      FormControl,
      FormGroup,
      Validators,
    } from '@angular/forms';
    
    @Component({
      selector: 'app-register',
      templateUrl: './register.page.html',
      styleUrls: ['./register.page.scss'],
    })
    export class RegisterPage implements OnInit {
      form: FormGroup;
    
      constructor(private fb: FormBuilder) {}
    
      ngOnInit() {
        this.createForm();
      }
    
      createForm() {
        this.form = this.fb.group({
          matchEmail: this.fb.group(
            {
              //email textfield
              email: new FormControl(
                '',
                Validators.compose([
                  Validators.required,
                  Validators.maxLength(64),
                  Validators.email,
                ])
              ),
              //confirm email textfield
              confirmEmail: new FormControl(''),
            },
            { validators: this.matchEmail }
          ),
        });
      }
    }
    
    


    0 commentaires

    0
    votes

    J'ai eu le même problème, et ma solution était la suivante:

    Créez une nouvelle variable comme celle-ci:

    form: formGroup = this.fb.group({
      controls...
    }, formOptions)
    

    puis insérez-le dans votre groupe de formulaires:

    const formOptions: AbstractControlOptions = {
       validators: your validator...,
       asyncValidators: your validators...
    }
    

    Cela supprime l'avertissement obsolète de mon code.

    J'espère que cela vous aide.


    0 commentaires