Angular2 ngМодель против переменных ngFor

Возможно ли (или еще не возможно) использовать ngModel для значений из ngFor? Является ли Angular пытаться защитить меня от плохой производительности?

Отлично работает: http://jsfiddle.net/langdonx/n5pjgev6/

<input type="text" [(ng-model)]="value">{{value}}

Не работает так хорошо: http://jsfiddle.net/langdonx/n5pjgev6/1

<li *ng-for="#name of names">
    <input type="text" [(ng-model)]="name">{{name}}
</li>

ИСКЛЮЧЕНИЕ: Невозможно переназначить имя привязки переменных

Я также попытался привязать к массиву, который... вроде работает, но захватывает фокус, а также генерирует исключение: http://jsfiddle.net/langdonx/n5pjgev6/2/

<li *ng-for="#name of names; #i = index">
    <input type="text" [(ng-model)]="names[i]">{{name}}
</li>

ИСКЛЮЧЕНИЕ: LifeCycle.tick называется рекурсивно

Edit:

Я могу обойти проблему LifeCycle.tick, используя более прямой подход, но фокус все равно украден, потому что ngFor перерисовывает вещи: http://jsfiddle.net/langdonx/n5pjgev6/3/ p >

<li *ng-for="#name of names; #i = index">
    <input type="text" [value]="names[i]" (input)="names[i] = $event.target.value">{{names[i]}}
</li>

Ответы

Ответ 1

Я думаю, что ngFor не нравится отслеживать элементы массива, которые являются примитивными значениями, имеющими ngModel.

Если вы удалите ngModel внутри цикла, он работает.

Он также работает, когда я обновляю jsfiddle с помощью

this.names = [{name: 'John'}, {name: 'Joe'}, {name: 'Jeff'}, {name: 'Jorge'}];

и

<li *ng-for="#n of names"><input type="text" [(ng-model)]="n.name">{{n.name}}</li>

Ответ 2

Решение состоит в том, чтобы ссылаться на значение внутри ngModel по его индексу. Поэтому [(ngModel)]="names[index]".

Но этого недостаточно, потому что *ngFor отслеживает элементы по значению. Как только значение будет изменено, старое значение не может быть отслежено. Поэтому нам нужно изменить функцию отслеживания, чтобы вернуть индекс, таким образом trackBy: trackByIndex.

Эта проблема объясняется здесь.

Решение:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <input type="text" 
        *ngFor="let name of names; let nameIndex = index; trackBy: trackByIndex"
        [(ngModel)]="names[nameIndex]"/>
      <br/>
      {{ names | json }}
    </div>
  `,
})
export class App {

  names: string[];

  constructor() {
    this.names = ['a', 'b', 'c'];
  }

  public trackByIndex(index: number, item) {
    return index;
  }
}