2017-03-15 60 views
0

我想添加一个脏标志到我的淘汰赛js模型(我期望它是一个简单的任务),该标志将更新时,任何属性被更改。当任何属性更改使用与ko.mapping时淘汰js更新脏标记

我在这里发布之前完成了一些研究,发现大多数答案指向this blog post这里也有一个提示链接到帖子,我试图遵循,但没有成功。

我也尝试过使用jquery来监听输入或select元素的变化,但是当输入被填充时触发onpage加载,因此标志将始终设置为dirty。

我的模型和例子之间的区别是我使用自动映射器

在这个例子就说明Itemdirty标志。如何在使用自动映射器时复制此内容? (我已经加入我的JSON模式的情况下,它有助于提供一个 “最佳” 的解决方案)的例子

的JS

ko.dirtyFlag = function(root, isInitiallyDirty) { 
var result = function() {}, 
    _initialState = ko.observable(ko.toJSON(root)), 
    _isInitiallyDirty = ko.observable(isInitiallyDirty); 

result.isDirty = ko.computed(function() { 
    return _isInitiallyDirty() || _initialState() !== ko.toJSON(root); 
}); 

result.reset = function() { 
    _initialState(ko.toJSON(root)); 
    _isInitiallyDirty(false); 
}; 

return result; 
}; 

function Item(id, name) { 
    this.id = ko.observable(id); 
    this.name = ko.observable(name); 
    this.dirtyFlag = new ko.dirtyFlag(this); 
} 

var ViewModel = function(items) { 
this.items = ko.observableArray([ 
    new Item(1, "one"), 
    new Item(2, "two"), 
    new Item(3, "three") 
]); 

this.save = function() { 
    alert("Sending changes to server: " + ko.toJSON(this.dirtyItems)); 
}; 

this.dirtyItems = ko.computed(function() { 
    return ko.utils.arrayFilter(this.items(), function(item) { 
     return item.dirtyFlag.isDirty(); 
    }); 
}, this); 

this.isDirty = ko.computed(function() { 
    return this.dirtyItems().length > 0; 
}, this); 
}; 

ko.applyBindings(new ViewModel()); 

我的JSON对象

{"PropertyID":0,"BulletPoints":["test 1","test 2","test 3"],"BriefDescription":"Some test desc","TakeOnAppointmentDate":"0017-03-02T12:05:00","Rooms":null,"TenureLengthOfLease":10,"TenureLengthOfService":10,"GroundCharges":11.0,"Directions":"go here then there","KeyHolderName":"Name","KeyHolderReference":"very nice","IsDisplayToPublic":true,"UploadToRightMove":false,"UploadToOnTheMarkert":false,"UploadToPrimeLocation":false,"RightMoveCost":1000.0,"EpcCost":100.0,"FloorPlanCost":2.0,"RoomIdentifier":null,"CoverIdentifier":null,"CoverPath":null,"PreviewUrl":null,"EpcReportPdf":null,"FloorPlan1":null,"FloorPlan2":null,"DisplayFrom":185.000,"DisplayTo":200.000,"SelectedSalePriceOptionId":3,"IsHidden":null,"AddressLine1":null,"NumberOfBedrooms":5,"NumberOfBathrooms":3,"NumberOfReceptionrooms":2,"Tenures":[{"Id":1,"Description":"Freehold"},{"Id":2,"Description":"LeaseHold"}],"SelectedTenureId":2,"ViewingInstructions":[{"Id":1,"Description":"Accompanied viewings with prior notice"},{"Id":2,"Description":"Vacant property"},{"Id":3,"Description":"Vendor to do viewings"}],"SelectedViewingInstructionId":2,"SaleStates":[{"Id":1,"Description":"For Sale"},{"Id":2,"Description":"Sold"},{"Id":3,"Description":"SSTC"},{"Id":4,"Description":"To Let"}],"SelectedSaleStateId":2,"UnderOffers":[{"Id":0,"Description":"No"},{"Id":1,"Description":"Yes"}],"SelectedUnderOfferId":1,"SalePriceOptions":[{"Id":1,"Description":"Asking Price"},{"Id":2,"Description":"Guide Price"},{"Id":3,"Description":"Offers Over"},{"Id":4,"Description":"In the region of"},{"Id":5,"Description":"Auction guide"}],"BlobItems":[]} 

回答

1

在所有你需要的全球脏旗的最基本的实现是三件事

  • 状态变量(布尔标志)以保持脏状态
  • 根对象上使用ko.toJS或ko.toJSON
  • 订阅功能时所计算的属性改变
以更新状态变量计算属性

如果您的视图模型是建立与ko.mapping它可能是这个样子:

var viewModel = function(jsonData){ 
    var self = this; 

    ko.mapping.fromJS(jsonData, {}, this); 

    self.isDirty = ko.observable(false); 
    self.toJS = ko.computed(function(){ 
    return ko.toJS(self); 
    }); 
    self.toJS.subscribe(function(value){ 
    self.isDirty(true); 
    }); 
} 

jsFiddle

之后,您可以添加额外的复杂性来存储初始toJS()结果,并将其与新值进行比较,以查看数据是否真的发生了更改或者是否只是将其设置回相同的数据。

正如博客继续说,但它不是最好的方式来做到这一点。任何更改都会导致计算结果通过遍历ViewModel中的整个可观察树来重新计算,这会导致代价高昂。

这是我刚才使用的另一个版本,它只评估第一次更改,然后在之后返回dirty = true。我很确定我也从Ryan Niemeyer那得到了这个,但我不记得在哪里。我在你引用的博客上看不到一个非常喜欢它的人。

var viewModel = function(jsonData){ 
    var self = this; 

    ko.mapping.fromJS(jsonData, {}, this); 

    this.dirtyCheck = ko.computed({ 
    read: function() { 
     if (!self.isDirty){ //property doesn't exist yet 
     var json = ko.toJSON(self); //trigger a subscription to all observable properties. 
     } else { 
     self.isDirty(true); //If this is being evaluated then by definition something has changed. 
     } 
     return; 
    } 
    }); 
    this.isDirty = ko.observable(false); //only add the property after the computed has been initialized 
} 
+0

感谢您的帮助。此行'self.toJS = ko.computed((=){> { return ko.toJS(self); });'需要改为'self.toJS = ko.computed(function(){ return ko.toJS(self); },this);'让它为我工作。我很想知道它们之间有什么不同,以及为什么需要更改(当你在jsfiddle中显示它工作时) – tony09uk

+1

哎呦,我以为我抓住了所有这些,但我错过了那一个。这是一个ecma脚本6的箭头函数,可能在您使用的JavaScript版本中不受支持。 –