web-dev-qa-db-fra.com

* ngPour réinitialiser toutes les valeurs de formulaire lors de l'ajout d'un nouvel élément d'entrée

J'ai une application Angular2 avec un bouton qui peut ajouter un autre prêt à mes prêts. Mon * ngFor est assez simple aussi:

    <div *ngFor="let loan of myLoans">
      <label>{{loan.name}}</label>
      <input type="text" name="loan.name" [(ngModel)]="loan.amount">
    </div>

myLoans est un tableau d'objets Loan avec les paramètres name et amount. Mon bouton est aussi très simple.

<button id="addLoan" type="button" (click)="addLoan()">Legg til lån</button>

La fonction addLoan ():

addLoan(): void{
    var newLoan = new Loan();
    this.myLoans.Push(newLoan);
}

Mon problème est que, lorsque j'ajoute un nouveau prêt dans la liste, la valeur que j'avais dans le champ de saisie pour mes autres prêts revient à 0 ou à la valeur que j'ai définie dans le constructeur de l'objet de prêt. 

Chargement de l'application montre cette image

 What now

ngModel fonctionne lors de la saisie d'un nombre

 enter image description here

Après avoir appuyé sur le bouton "Legg til lån", la valeur de la première entrée est réinitialisée

 enter image description here

ngModel fonctionne toujours pour la première entrée si j'essaie de saisir un autre numéro

 enter image description here

Quelqu'un a une idée de ce qui se passe ici?

7

AJT_82 est proche du problème, en ce que les noms non uniques vous causent un problème, mais vous pouvez faire un correctif encore plus simple, et un de plus, dans le sens de ce que vous vouliez probablement, en changeant votre template html en ceci

<div *ngFor="let loan of myLoans">
  <label>{{loan.name}}</label>
  <input type="text" [name]="loan.name" [(ngModel)]="loan.amount">
</div>

Remarquez le changement de mise du nom dans []. Cela garantira que le modèle maintiendra un lien vers le nom, et tant que le nom de chaque prêt sera unique, l'identifiant le sera également.

Mise à jour: Si name n'est pas unique, vous pouvez y ajouter l'index pour le rendre unique, comme ceci.

<div *ngFor="let loan of myLoans; let i=index">
  <label>{{loan.name}}</label>
  <input type="text" [name]="loan.name + '_' + i" [(ngModel)]="loan.amount">
</div>
14
Joo Beck

Je suis sûr à 99% que vous utilisez un formulaire sans avoir d'attribut name unique, puisque ngModel fonctionne. 

L'attribut name doit être unique pour être évalué en tant que champs séparés. Angular ne se soucie pas vraiment de la ngModel dans les formulaires, mais examine plutôt l'attribut name

Notez que l'attribut name que vous aviez actuellement défini: name="loan.name" contient en fait uniquement le littéral chaîne loan.name et non la valeur réelle de votre modèle. Par conséquent, le nom n'est pas unique.

Ainsi, lorsque vous transmettez une nouvelle variable loan, tous les autres prêts obtiennent la même valeur que la valeur nouvellement transmise, car tous les champs sont évalués comme étant identiques.

Cela peut facilement être corrigé en ajoutant l'index dans l'attribut name, par exemple:

<div *ngFor="let loan of myLoans; let i=index">
  <label>{{loan.name}}</label>
  <input type="text" name="loan.name{{i}}" [(ngModel)]="loan.amount">
</div>
4
AJT_82

J'ai essayé votre code et cela fonctionne bien pour moi. Je suppose que cela pourrait être un problème de compilateur. Essayez de mettre à jour vos bibliothèques ng2 et TypeScript vers la dernière version. Voici un exemple de fichier partiel tsconfig: 

{
  "compilerOptions": {
    "target": "es5",
    "typeRoots": ["node_modules/@types/"],
    "types": [
      "node",
      "es6-shim"
    ]
  }
}

Évitez également d'utiliser "var" pour la déclaration de variable. Utilisez "let" pour conserver la portée de la variable. Je pense que votre problème pourrait être dû à l'utilisation de var. Si vous utilisez un ancien compilateur, il se peut que cela gâche votre objet.

0
Merih Taze

La valeur de l'entrée devient zéro car vous avez déclaré que [(ngModel)] était l'objet itérateur de * ngFor. Et lorsque vous poussez un objet vide dans le tableau de myLoans, le ngModel modifie l'entrée à zéro (valeur par défaut pour le montant)

Exemple:

myLoans = [0, 1, 2, 3]

Lorsque vous actualisez la page, le [(ngModel]) lie la dernière valeur du tableau à l'entrée (3). 

Si vous écrivez 125 sur l'entrée,

Ensuite, vous modifiez également la valeur du dernier tableau

myLoans = [0, 1, 2, 125]

Si vous poussez un nouvel élément, Angular actualisera l'entrée avec la dernière valeur de tableau

myLoans = [0, 1, 2, 125, 0]

Valeur d'entrée maintenant = 0


Mon opinion: utiliser ngModel dans un * ngFor est une mauvaise pratique, il existe un autre moyen de faire la même tâche en utilisant (click) event et Angular Selector. Essayez ceci à la place:

<input #loan ..>
<button (click)="addLoan(loan.value)">Add Loan</button>
0
Cassiano

@Joo_Beck a suggéré d'utiliser [name]=loan.name au lieu de name='loan.name'. Mais cela n'a pas fonctionné pour moi. Je viens d'ajouter un index {{i}} avec le nom indiqué ci-dessous et cela a parfaitement fonctionné.

<div *ngFor="let loan of myLoans; let i=index">
  <label>{{loan.name}}</label>
  <input type="text" name="loan.name{{i}}" [(ngModel)]="loan.amount">
</div>

La solution qui a fonctionné pour moi est suggérée par @ AJT_82. Merci pour!

Merci @ Cassiano, vous avez très bien expliqué la raison!

0
MKJ