Angular2:丢弃文本输入更改后更新视图

Angular2: update view after discarding change in text input

我有一组文本区域,它们可以单独更新,并且可以保存或放弃更改。每个文本区域都由一个对象表示,以跟踪更改和 enable/disable 一些按钮。一切正常,但丢弃后,对象没有改变,但视图没有更新。它只会在我更改对象内部的某些内容时更新,因此我尝试制作对象的 'real' 副本并将这些值分配给实际对象,但这也不起作用。 到目前为止我的代码:

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

没有检测到变化,因为实际上列表中没有变化 myMessages。如果将 {{myMessages | json }} 添加到 HTML 并将文本插入文本区域,您会看到列表的内容没有改变。在 discardChanges 中,您只需再次将 "hello" 分配给已经包含字符串 "hello" 的变量。所以没有变化。 如果您在 discardChanges 中的消息中添加空格(如您所述),您实际上会将值从 "hello" 更改为 "hello " -> 值已更改。

但是,您可以通过持有一个 "previous" 列表来跟踪列表的原始条目和 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));
  }
}

我在组件中避免了一些方法,因为它们与这个例子无关。只需将深层副本分配给 ngOnInit 处的变量 previous,如果您按保存,也可以执行此操作。如果要放弃更改,请再次将列表 previous 的深层副本重新分配给 myMessages

这样,您的视图就会更新,因为现在变量值发生了变化。