Angular2: обновить представление после отмены изменения ввода текста

У меня есть массив текстовых областей, которые можно обновлять индивидуально, а изменения можно сохранить или отменить. Каждое текстовое поле представлено объектом для отслеживания изменений и включения / отключения некоторых кнопок. Все работает нормально, но после сброса объект не меняется, а представление не обновляется. Он обновляется только тогда, когда я что-то меняю внутри объекта, поэтому я попытался сделать «настоящую» копию объекта и присвоить эти значения фактическому объекту, но это тоже не работает. Мой код на данный момент:

HTML:

   <ng-container *ngFor="let itemId of itemIds">
  <div>
        <div>
            <textarea #message (keydown)="enableButton(itemId)" rows="5" cols="50"[(value)]="getMessageDetails(itemId).message"></textarea>
        </div>
    </div>
    <div>
        <button [disabled]="!getMessageDetails(itemId).changedText" (click)="saveMessageChanges(itemId, message.value)">Save Changes</button>
        <button [disabled]="!getMessageDetails(itemId).changedText" (click)="discardChanges(itemId)">Discard Changes</button>
    </div>
</ng-container>

Составная часть:

    itemIds = [2,4];

  myMessages = [
    {
      id: 2,
      message: 'hello',
      changedText: false
    },
    {
      id: 4,
      message: 'world',
      changedText: false
    }
  ]

enableButton(itemId){
    this.myMessages.map( y => {if (y.id === itemId) {
      y.changedText = true;
    }});
  }

getMessageDetails(itemId){
    let myMessage = this.myMessages.find(y => y.id === itemId);
    return myMessage;
  }

saveMessageChanges(itemId, message){
    this.myMessages.map( y => {if (y.id === itemId) {
      y.message = message;
      y.changedText = false;
    }});
  }
discardChanges(itemId){
    let tempMessage = Object.assign({},(this.myMessages.find(y => y.id === itemId)));

    let myMessage = this.myMessages.find(y => y.id === itemId);

    myMessage.changedText = false;
    myMessage.message =  tempMessage.message; // <- no object change detected
    //myMessage.message = " " + tempMessage.message; // <- this works
    return myMessage;
  }

Всякий раз, когда я добавляю в сообщение пробел, он будет работать.

Я создал stackblitz здесь: https://stackblitz.com/edit/angular-m5dbj4

0
0
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Изменений не обнаружено, поскольку фактически изменений в списке myMessages нет. Если вы добавите {{myMessages | json }} в свой HTML и вставите текст в текстовую область, вы увидите, что содержимое списка не изменилось. В discardChanges вы просто снова присваиваете «привет» переменной, которая уже содержит строку «привет». Так что изменений нет. Если вы добавляете пробел к сообщению в discardChanges (как вы описали), вы фактически меняете значение с «hello» на «hello» -> значение изменено.

Однако вы можете решить эту проблему, удерживая «предыдущий» список, чтобы отслеживать исходные записи вашего списка и использование ngModel.

Измените текстовую область на

<textarea #message (keydown)="enableButton(itemId)" rows="5" cols="50" [(ngModel)]="getMessageDetails(itemId).message"></textarea>

И ваш компонент:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit { 
  itemIds = [2,4];
  myMessages = [
    {
      id: 2,
      message: 'hello',
      changedText: false
    },
    {
      id: 4,
      message: 'world',
      changedText: false
    }
  ]

  previous = []

  ngOnInit() {
    this.previous = this.getDeepCopy(this.myMessages);
  }

  saveMessageChanges(itemId, message){
    this.myMessages.map( y => {if (y.id === itemId) {
      y.message = message;
      y.changedText = false;
    }});

    this.previous = this.getDeepCopy(this.myMessages);
  }

  discardChanges(itemId){
    this.myMessages = this.getDeepCopy(this.previous);
    let myMessage = this.myMessages.find(y => y.id === itemId);

    return myMessage;

  }

  getDeepCopy( list ) {
    return list.map(x => Object.assign({}, x));
  }
}

Я избегал некоторых методов в компоненте, потому что они не имеют отношения к этому примеру. Просто назначьте глубокую копию переменной previous в ngOnInit и также сделайте это, если вы нажмете «Сохранить». Если вы хотите отменить изменения, вы снова переназначаете глубокую копию списка previous на myMessages.

При этом ваше представление обновляется, потому что теперь есть изменение значения переменной.

Спасибо, сработало! Я тоже думал о копировании, но подумал, может быть, есть способ обойти это, о чем я не думал.

D. K. 31.10.2018 14:22

Другие вопросы по теме