web-dev-qa-db-fra.com

Angular 2 - [(ngModel)] ne se met pas à jour après le changement de [valeur]

Je règle la valeur d'une entrée calculant deux autres ngModels, et cela semble fonctionner correctement. Mais si j'inspecte mon ngModel, cela ne change pas du tout. Laisse moi te montrer:

<ion-item>
    <ion-label>Total price: {{product.totalPrice}}</ion-label>
    <ion-input 
        type="number"
        [value]="product.quantity * product.price"
        [(ngModel)]="product.totalPrice" 
        [ngModelOptions]="{ standalone: true }"></ion-input>
</ion-item>

Donc ici {{product.totalPrice}} montre la valeur initiale, ce qui est bien. Si je modifie manuellement cette entrée, les modifications seront répercutées sur l'expression, c'est également correct. Mais cette entrée sera en lecture seule et elle sera définie par la modification de deux autres entrées. Lorsque je les modifie, je constate que la valeur de l'entrée est mise à jour correctement, mais pas l'expression dans l'étiquette. Quel est le problème là-bas?

C'est vraiment bizarre parce que la valeur de l'entrée GETS UPDATED, mais pas l'expression {{product.totalPrice}}, je suppose que la valeur est mise à jour car les autres champs le sont, mais ces modifications n'ont jamais touché le ngModel. 

Au fait, j'utilise Ionic 2

7
Agustín

En fait, [] signifie que lier données et () signifie émettre des modifications/ou laisser déclencher un événement avec ces modifications à partir de ce contrôle d'interface utilisateur <ion-input>. Donc, [()] ne signifie pas liaison de données bidirectionnelle. Ça veut dire: 

  • lier des données en utilisant []
  • déclencher des modifications d’entrée ().

Consultez cet exemple il montre de nombreuses façons de lier des données avec une entrée et de déclencher des modifications.

8
bunjeeb

Je sais donc que je suis en retard pour la soirée, mais comme aucune autre réponse n’est correcte, j’ai pensé ajouter la solution au cas où une autre personne se retrouverait sur cette page. 

Lors de la création d'un composant personnalisé qui accepte ngModel, le composant doit implémenter l'interface ControlValueAccessor. Qui est détaillé ci-dessous

interface ControlValueAccessor {  
  writeValue(obj: any): void
  registerOnChange(fn: any): void
  registerOnTouched(fn: any): void
  setDisabledState(isDisabled: boolean): void
}

Pour enregistrer une modification apportée par le composant, celui-ci doit appeler la méthode onChange fournie par la méthode registerOnChange.

Par exemple, si nous enregistrons notre méthode onChange comme suit:

 onChange: any = () => { };
 registerOnChange(fn) {
   this.onChange = (obj) => fn(obj);
 }

Chaque fois que notre composant modifie la valeur, nous devons exécuter la ligne suivante

this.onChange(this.value)

J'espère que cela aide.

6
Lewis Campbell

Vous pouvez essayer d'utiliser (ngModelChange) pour surveiller efficacement les modifications de valeur et mettre à jour le product.totalPrice. Cela ressemblerait à quelque chose comme ça.

<ion-item>
    <ion-label>Total price: {{product.totalPrice}}</ion-label>
    <ion-input 
        type="number"
        [value]="product.quantity * product.price"
        [(ngModel)]="product.totalPrice" 
        [ngModelOptions]="{ standalone: true }"></ion-input>
        (ngModelChange)="product.totalPrice = $event"
</ion-item>

Si cet élément est encapsulé dans les éléments <form> et ngForm exportAs #someForm="ngForm", vous pouvez utiliser template reference variable et l'utiliser à la place dans l'étiquette. Quelque chose comme ça:

<ion-item>
    <ion-label>Total price: {{product.totalPrice}}</ion-label>
    <ion-input 
        type="number"
        [value]="product.quantity * product.price"
        [(ngModel)]="product.totalPrice" 
        [ngModelOptions]="{ standalone: true }"
        name="totalPrice"
        #totalPrice="ngModel"></ion-input>
</ion-item>

Espérons que cela aide.

3

J'ai également rencontré le problème suivant: la liaison bidirectionnelle n'avait pas mis à jour le modèle lors de la modification de l'entrée du champ d'entrée. Dans mon cas, j'ai découvert que la propriété que je liais était une propriété en lecture seule. Pour le savoir, j'ai dû scinder la liaison bidirectionnelle:

[ngModel]="data.name" (ngModelChange)="testMethod($event)"

et la méthode:

testMethod($event) {data.name = $event}

Ensuite, j'ai l'exception en lecture seule.

3
Gerros