Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngFor not working correctly with ngModel (angular 5.1.2)

I am seeing strange behaviour with ngFor in combination with ngModel. Here's an example:

heroes = [
   {
      "name": "Deadpool"
   },
   {
      "name": "Thor"
   },
   {
      "name": "Superman"
   },
   {
      "name": "Batman"
   }
];

With the following code:

<div *ngFor="let hero of heroes;">
  <div class="row">
    <div class="input">
      <label>Superhero</label>
      <input [(ngModel)]="hero.name" name="hero">
    </div>
  </div>
</div>

Result:

Superhero: Batman
Superhero: Batman
Superhero: Batman
Superhero: Batman

Whereas if I don't use ngModel, but just print the value instead, it works correctly:

<div *ngFor="let hero of heroes;">
  <div class="row">
    <div class="input">
      <label>Superhero</label>
      <span>{{hero.name}}</span>
    </div>
  </div>
</div>

Result:

Superhero: Deadpool
Superhero: Thor
Superhero: Superman
Superhero: Batman

Can anyone tell me what I'm doing wrong?

like image 289
Spacejockey Avatar asked Feb 02 '18 11:02

Spacejockey


People also ask

What does [( ngModel )] do?

The ngModel directive is a directive that is used to bind the values of the HTML controls (input, select, and textarea) or any custom form controls, and stores the required user value in a variable and we can use that variable whenever we require that value. It also is used during form validations.

Which module is required for ngModel?

NgModel is used to create a top-level form group Instance, and it binds the form to the given form value. NgModule: Module used by NgModel is: FormsModule.

Can't bind to ngModel since it isn't a known property of input Ng?

To fix Can't bind to 'ngModel' since it isn't a known property of 'input' error in Angular applications we have to import FormModule in app. module. ts file. If you are using FormBuilder class to create reactive form we have to import ReactiveFormsModule as well to avoid below error.

How does ngModel set value?

The two-way data binding.is the recommended way to set the value in the template-driven forms. The following code uses the [(ngModel)]="contact. firstname" to bind the firstname HTML element to the contact. firstname field in the component class.


2 Answers

Only issue here is input same input name :

change name="hero" to name="hero{{i}}"

<div *ngFor="let hero of heroes;let i = index;">
  <input [(ngModel)]="hero.name" name="hero{{i}}">
</div>
like image 152
Vivek Doshi Avatar answered Sep 30 '22 04:09

Vivek Doshi


You are not doing much wrong. Let me show you how to fix, step by step:

1) Use single quotes ' and not double quotes " in your heroes array, it should be like this:

heroes = [
    {
       'name': 'Deadpool'
    },
    {
       'name': 'Thor'
    },
    {
       'name': 'Superman'
    },
    {
       'name': 'Batman'
    }
 ];

2) To just show the values in an input field you can use:

value="{{hero.name}}" OR [value]="hero.name" and same goes with name like this:

<input value="{{hero.name}}" name="{{hero.name}}">
<input [value]="hero.name" [name]="hero">

3) For using ngModel you need to have FormsModule in your imports array in app.module.ts and import import { FormsModule } from '@angular/forms'; like this:

import { FormsModule } from '@angular/forms';
imports: [
    BrowserModule,
    FormsModule
]

Now two way data binding would work:

<div *ngFor="let hero of heroes;">
  <div class="row">
    <div class="col-md-4">
      <div class="input">
        <label>Superhero</label>
        // Just show value in input
        <input value="{{hero.name}}" name="{{hero.name}}">
        // Another way to Just show value in input
        <input [value]="hero.name" [name]="hero.name">
        // This is our boy who make two way data binding easy
        <input [(ngModel)]="hero.name" [name]="hero.name">
        <div></div>
      </div>
    </div>
  </div>
</div>

Hope this helps. Thanks

like image 35
Immad Hamid Avatar answered Sep 30 '22 04:09

Immad Hamid