12

I am trying to bind an array of strings from my inputs, so in the html file I wrote this:

<div *ngFor="let word of words; let in=index" class="col-sm-3">
      <div class="form-group">
        <input type="text" [(ngModel)]="words[in]"  class="form-control" [attr.placeholder]="items[in]" required>
      </div>
  </div>

But this didn't work as expected because when I log the words variable it show an empty array as initialized in my Component class. Also, I log the variable from another component should that supposed to be the issue for my problem. I have two components:

  • The form component that contains an array of query components.
  • The query child component that has an array of words strings.

So, the words variable is declared into the queries component but I am logging this variable through the form component like this:

console.log(JSON.stringify(this.queries));

While queries is an array of Query in the form component:

queries:Query[] = [];

Thanks for your help!

Mehdi Benmoha
  • 3,694
  • 3
  • 23
  • 43
  • To me, the problem is not clear. if you can specifically tell what you exactly want? – micronyks Jul 17 '16 at 17:13
  • Well after many testings, my problem is to send back the queries words to my form component after they are updated – Mehdi Benmoha Jul 17 '16 at 17:32
  • Each input tag has to have a unique name attribute defined. http://stackoverflow.com/questions/39336708/angular2-ngmodel-inside-ngfor-data-not-binding-on-input – Mate Šimović May 10 '17 at 18:36

3 Answers3

22

The problem is with using an array of primitive values (words) in ngFor.

You can change words to an array of objects like

words = [{value: 'word1'}, {value: 'word2'}, {value: 'word3'}];

and use it like

  <div *ngFor="let word of words; let in=index" class="col-sm-3">
      <div class="form-group">
        <input type="text" [(ngModel)]="words[in].value"  class="form-control" [attr.placeholder]="items[in]" required>
      </div>
  </div>

This might also be solvable using trackBy but I'm not sure.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Hello, there! Could you explain the problem a bit more? Honestly, I don't get what the OP is asking, but both ways (array of primitives or objects) seem to work OK: http://plnkr.co/edit/7ePXDWCwfeI0WglCj3KN?p=preview ... – acdcjunior Jul 17 '16 at 17:22
  • I tried this but still doesn't work. By the way, I tried to add the event keyup on my inputs and logging the words array in the same component. Annnd it worked, so my problem is to communicate back the words array to the form (parent) component. – Mehdi Benmoha Jul 17 '16 at 17:24
  • 1
    @e.m.b "doesn't work" doesn't provide much information. – Günter Zöchbauer Jul 17 '16 at 17:24
  • 2
    @acdcjunior if you write in your plunker, in the first 2 input fields they loose focus after each key press while in the lower inputs you can write normally. With primitive values the row gets recreated after each change because the array value is replaced each time the value changes and the input looses focus because it is removed and another one added instead. While in the lower inputs only the value changes but `*ngFor` doesn't have to recreate the row. – Günter Zöchbauer Jul 17 '16 at 17:28
  • The console.log(this.queries) show an empty words array in the form component. – Mehdi Benmoha Jul 17 '16 at 17:28
  • @e.m.b see the Plunker link provided by acdcjunior (updated a bit http://plnkr.co/edit/CTssFRRoPC0qY83XKaHw?p=preview to show words2) – Günter Zöchbauer Jul 17 '16 at 17:28
  • Oh, I see it now. Thanks! – acdcjunior Jul 17 '16 at 17:31
  • humm.. now my problem is that my queries array (that's is in the form component) is not being updated after user entered words in the query component. – Mehdi Benmoha Jul 17 '16 at 17:33
  • Where should it be updated from? I don't see from the information in your question how `queries` is related to `words`. – Günter Zöchbauer Jul 17 '16 at 17:35
  • The form component contains an Array of Query Components, which contains an array of words (strings). So when I logging the queries array, it always has empty words. You got it ? – Mehdi Benmoha Jul 17 '16 at 17:40
  • Can you please create a Plunker that demonstrates what you try to accomplish. From this prose I'm not able to derive what the problem might be. – Günter Zöchbauer Jul 17 '16 at 17:41
  • Here's the plunker: http://plnkr.co/edit/KZh0OQgKP3fQhWF9Lst2?p=preview I am getting an error but can't see the console log – Mehdi Benmoha Jul 17 '16 at 17:52
  • I fixed a few issues in your Plunker http://plnkr.co/edit/2diBZOOrTStWGu5JxbVN?p=preview. I don't get what `new Queries()` is supposed to do. You don't instantiate components using `new Xxx()`. Components are instantiated by Angular when the selector is found in the template or using `ViewContainerRef.createComponent()`. – Günter Zöchbauer Jul 17 '16 at 17:57
  • The official documentation is not yet ready for this part. Can you give me some examples of using this class ? I think I am going to use the @Output () function to achieve this. – Mehdi Benmoha Jul 17 '16 at 18:04
  • http://stackoverflow.com/questions/36325212/angular-2-dynamic-tabs-with-user-click-chosen-components/36325468#36325468 contains a Plunker that demonstrates it. – Günter Zöchbauer Jul 17 '16 at 18:08
16

Each input tag has to have a unique 'name' attribute defined, as described in:

Angular2 ngModel inside ngFor (Data not binding on input)

Here is the corrected code:

<div *ngFor="let word of words; let in=index" class="col-sm-3">
  <div class="form-group">
    <input type="text" [(ngModel)]="words[in]" name="word{{in}}" class="form-control" [attr.placeholder]="items[in]" required>
  </div>

Community
  • 1
  • 1
Mate Šimović
  • 945
  • 11
  • 11
-2

Solved this by using the @Input() function and passing the queries array + the query index number. Thank you guys for the support.

Mehdi Benmoha
  • 3,694
  • 3
  • 23
  • 43