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
。
这样,您的视图就会更新,因为现在变量值发生了变化。
我有一组文本区域,它们可以单独更新,并且可以保存或放弃更改。每个文本区域都由一个对象表示,以跟踪更改和 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
。
这样,您的视图就会更新,因为现在变量值发生了变化。