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;
}
}