1

I have a form to create a "question", which is an object containing an array of strings for answers. My issue is that I can’t find a way to bind those answers to the question model

A naive implemenation would be:

import { Component  } from '@angular/core';
class Question {
  question: string;
  answers: Array<string>;
}

@Component({
  selector: 'app',
  template: `
<input type="text" [(ngModel)]="question.question">
<input type="text" *ngFor="let answer of question.answers" [(ngModel)]="answer">
`
})

export class AppComponent {
  question: Question = new Question;
  question.answers = new Array(4);
  constructor(){};
}

Issue is on the second ngModel. With this solution I get the error:

zone.js:388 Unhandled Promise rejection: Cannot assign to a reference or variable! ; Zone: <root> ; Task: Promise.then ; Value: Error: Cannot assign to a reference or variable!

I guess we can’t bind a generated value from an ngFor to a model.

I also tried these options:

  • [(ngModel)]="question.answers[index]" -> With this I added let index=index; on ngFor and a corresponding name to the input. Here I have the error I’m describing on the next paragraph
  • [(ngModel)]="question.answers[] -> Trying to do the same you do using pure HTML. This doesn’t work at all

None of these worked as I expected: when you change value on an input it seems to reload the ngFor loop. And when I extended my solution to allow user to append or delete an answer, adding an answer would delete content of the first one.

Ulysse BN
  • 10,116
  • 7
  • 54
  • 82

1 Answers1

4

As far as I can see you have two options:

1 Use an Object instead of an array

You can iterate over the object using ngFor and a pipe like described here: Iterate over TypeScript Dictionary in Angular 2

@Pipe({ name: 'values',  pure: false })
export class ValuesPipe implements PipeTransform {
  transform(value: any, args: any[] = null): any {
    return Object.keys(value).map(key => value[key]);
  }
}

<div *ngFor="#value of object | values"> </div>

2 Use a second array for the ngFor loop like here http://plnkr.co/edit/PO9ujHLWfzvYD67nDCwT?p=preview

import { Component } from '@angular/core';

export class Hero {
  id: number;
  name: string;
}

@Component({
  selector: 'my-app',
  template: `<h1>Hello {{name}}</h1>
  <div *ngFor="let count of dummyArr; let i=index">
     <input type="number" [(ngModel)]="data[i]">
  </div>
  `
})
export class AppComponent implements OnInit { 
  name = 'Angular';
  data:number[]=[];
  dummyArr:number[]=[];

  ngOnInit(){
    this.data.length=6;
    this.dummyArr.length=6;
  }
}
Community
  • 1
  • 1
Riscie
  • 3,775
  • 1
  • 24
  • 31
  • 1
    Get it... this guy did it with a second array, but i find it a bit weird... http://plnkr.co/edit/PO9ujHLWfzvYD67nDCwT?p=preview Do you really need an array or could you also iterate over an object maybe? You can write a pipe to do so: http://stackoverflow.com/questions/35534959/access-key-and-value-of-object-using-ngfor – Riscie Nov 28 '16 at 21:06
  • Both solutions are really nice tweak and could fix my issue (not nicely though). Please edit your answer accordingly so I can validate it. I really need an array since I’m adding, deleting elements and I need to have an index from 0 to length - 1. I could do it with an object but it seems overkill – Ulysse BN Nov 29 '16 at 07:12