Angular2 Inline редактирование с использованием ngModel и ngFor

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

Рабочий пример можно найти здесь.

Вот код компонента, в котором я использую ngModel и ngFor вместе:

import {Component} from '@angular/core'
import {InlineEditComponent} from './inline.component';
@Component({
  selector: 'inline-app',
  providers: [],
  template: `
    <div>
      <h2>Inline Editing with Angular 2</h2>
      <inline-edit [(ngModel)]="editableText" (onSave)="saveEditable($event)"></inline-edit>
    </div>
    <div>
      <ul style="margin:5px;">
      <li ngFor #arr [ngForOf]="array" [ngForTrackBy]="customTrackBy">
      <inline-edit [(ngModel)]="arr" (onSave)="saveEditable($event)"></inline-edit>
   </li>
        // <li style="margin:5px;" *ngFor="let arr of array ; let i=index">
        //   <inline-edit [(ngModel)]="array[i]" (onSave)="saveEditable($event)"></inline-edit>
        // </li>
      </ul>
    </div>
  `,
  directives: [InlineEditComponent]
})
export class InlineApp {
customTrackBy(index: number, obj: any): any {
    return index;
  }
  editableText = "Click to edit me!";
  // Save name to the server here.  
  saveEditable(value){
      console.log(value);
  }
  array=['bmw','benz','honda'];
}

Если бы кто-нибудь мог мне помочь, было бы здорово.


person Varun    schedule 05.07.2016    source источник


Ответы (3)


Вы редактируете строки, которые являются как неизменяемыми, так и прямыми элементами массива. Это означает, что всякий раз, когда строковое значение изменяется, будет создан новый строковый объект, который заменит старую строку в массиве, что, в свою очередь, приведет к тому, что *ngFor повторно инициирует новый компонент для этой строки, чтобы заменить старый. Если вы поместите console.log('on-constructor') в конструктор InlineEditComponent, вы увидите, что он вызывается каждый раз, когда вы добавляете символ.

Чтобы решить вашу проблему, не используйте строку напрямую. Оберните их внутри класса следующим образом:

export class Data {
  name: string;
}

тогда ваше объявление массива будет:

array: Data[] = [
  {name:"bwm"},
  {name:"benz"},
  {name:"honda"}
];

При этом изменения коснутся только поля имени, а объекты-оболочки останутся прежними; Поэтому ngFor не будет запускаться повторно.

Измененный plnkr: https://plnkr.co/edit/WwGcLlisjGe1cmZOMHhD?p=preview

person Harry Ninh    schedule 06.07.2016
comment
Я думал, что это то, что происходит с проблемой @Varun... ваше решение довольно хорошее, однако действие по отмене больше не отменяется... оно по-прежнему сохраняет любые внесенные изменения - person Jarod Moser; 06.07.2016
comment
Да, я не проверял работоспособность всех других функций, должен был поставить предупреждение. Мои изменения были направлены исключительно на решение проблемы, с которой он столкнулся :) - person Harry Ninh; 06.07.2016
comment
По сути, его решение включает в себя создание модели — класса Data. Это рекомендуемый путь при реализации любого повторяемого объекта данных. - person BrianRT; 06.07.2016
comment
Спасибо за ответ, но я опубликовал общий ответ, который можно использовать для любого списка. Рабочий код: plnkr.co/edit/7SSpZDec2N2zjrSUM04X?p=preview. @HarryNinh - person Varun; 06.07.2016

Вы можете напрямую привязываться к элементу массива, а не к переменной шаблона:

<li *ngFor="let arr of array; let idx=index; ngForTrackBy:customTrackBy">
      <inline-edit [(ngModel)]="array[i]" (onSave)="saveEditable($event)"></inline-edit>

Кстати: ваш синтаксис ngFor можно использовать только для тегов <template>. Если вы используете его для других элементов, необходимо использовать синтаксис, использованный выше.

См. также https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngFor

person Günter Zöchbauer    schedule 06.07.2016

Это должно быть изменено в tamplate.

<ul>
            <li style="margin:5px;" *ngFor="let arr of array ; let i=index; trackBy:customTrackBy">
            <inline-edit [(ngModel)]="array[i]" (onSave)="saveEditable($event)"></inline-edit>
            </li>
</ul>

Эти функции должны быть добавлены в класс:

export class{

customTrackBy(index: number): any {
    return index;
  }
}

Окончательный рабочий код:
https://plnkr.co/edit/7SSpZDec2N2zjrSUM04X?p=preview

person Varun    schedule 06.07.2016