3 votes

ExpressionChangedAfterItHasBeenCheckedError from Angular

Ceci est la suite de mon problème initial

stackoverflow.com/questions/44596418/angular-throws-expressionchangedafterithasbeencheckeder-with-textarea

qui n'est toujours pas résolue. J'ai recréé le plunkr original pour simuler le projet réel et j'ai constaté que le problème n'est pas lié au textarea.

Lorsque j'accède à la page de détails en cliquant sur un élément de la liste, l'exception suivante s'affiche ExpressionChangedAfterItHasBeenCheckedError est lancé. Cela ne se produit que lorsque le CodeView de src/detailitems.ts a plus d'un élément dans le tableau. Les éléments du CodeView définissent les champs dans le formulaire détaillé.

import { FormBase } from './formbase'
import { ItemBase, TextboxItemBase } from './itembase'

export class CodeView extends FormBase {

    static getItems() :ItemBase[] {

    let items: ItemBase[] = [

        new TextboxItemBase(
            {
                key: 'id',
                label: 'ID',
                value: '',
                required: true,
                enabled: false,
                readOnly: true,
                size: 36
            }
        )
,
        new TextboxItemBase(
            {
                key: 'description',
                label: 'Description',
                required: true,
                size: 20

            }
        )            
    ];

    return items;
}

}

Si je modifie le code pour que le CodeView ne contienne qu'un seul élément, l'exception disparaît.

Exception Plunkr

Pas d'exception Plunkr (Un seul point dans detailitems)

3voto

yurzui Points 85802

Votre erreur provient de A-Item plus précisément à partir de ce nœud

<div [formGroup]="form"

lorsque vous avez une telle liaison, angular crée automatiquement NgControlStatusGroup qui définit les classes CSS en fonction de l'état du contrôle (valide/invalide/dirty/etc).

export const ngControlStatusHost = {
  '[class.ng-untouched]': 'ngClassUntouched',
  '[class.ng-touched]': 'ngClassTouched',
  '[class.ng-pristine]': 'ngClassPristine',
  '[class.ng-dirty]': 'ngClassDirty',
  '[class.ng-valid]': 'ngClassValid', // you get error in this binding
  '[class.ng-invalid]': 'ngClassInvalid',
  '[class.ng-pending]': 'ngClassPending',
};

Dans un premier temps, vous n'apportez aucune valeur ajoutée à vos contrôles. C'est pourquoi valid de votre formulaire est false . Ensuite, vous l'alimentez en utilisant ngModel pendant le cycle de détection des changements et le formulaire devient valide. Propriété valide pour form est calculé à partir de tous vos contrôles. Si vous n'avez qu'un seul contrôle, la propriété valide ne dépendra que d'un seul contrôle. A-Item ne soulèvera pas d'erreur.

Je préparerais les données avant le rendu.

Vous pouvez ouvrir form.component.ts et trouver le code suivant

this.formItems.forEach(item => {
   group[item.key] = item.BuildControl();
   this.items.push(new formObjectItem(item, this.getData(item.key)));
});

vous devez alors patcher les données pour le formulaire

this.formItems.forEach(item => {
   group[item.key] = item.BuildControl();
   this.items.push(new formObjectItem(item, this.getData(item.key)));
   group[item.key].patchValue(this.getData(item.key)); // <== this line
});

o

this.formItems.forEach(item => {
   group[item.key] = item.BuildControl();
   const value = this.getData(item.key);
   this.items.push(new formObjectItem(item, value));
   group[item.key].patchValue(value);
});

De cette façon, votre formulaire sera synchronisé avec votre valeur et aura un statut correct.

Dans ce cas, vous pouvez également supprimer itemValue et ngModel de A-Item puisque le modèle réactif fera tout le travail.

Plunker en fourche

Vous n'obtenez pas ce type d'erreur

Encore un conseil :

import * as Rx from 'rxjs/Rx'

vous livrerez toutes les bibliothèques rxjs dans votre bundle

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X