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.

0

1 Answer 1

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;
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Get it... this guy did it with a second array, but i find it a bit weird... 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: stackoverflow.com/questions/35534959/…
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.