2012-05-16 42 views
61

確定這是一個非常容易回答的問題,但有沒有簡單的方法可以確定淘汰賽視圖模型的任何屬性是否已更改?檢測對淘汰賽視圖模型的更改

+5

退房這個帖子:創建智能,骯髒的一面旗幟KnockoutJS(http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs。html) – Homer

回答

48

您可以訂閱你想要監控的屬性:

myViewModel.personName.subscribe(function(newValue) { 
    alert("The person's new name is " + newValue); 
}); 

這將提醒時PERSONNAME變化。

好了,你想知道什麼時候你的模型中有什麼變化......

var viewModel = … // define your viewModel 

var changeLog = new Array(); 

function catchChanges(property, value){ 
    changeLog.push({property: property, value: value}); 
    viewModel.isDirty = true; 
} 

function initialiseViewModel() 
{ 
    // loop through all the properties in the model 
    for (var property in viewModel) { 

     if (viewModel.hasOwnProperty(property)) { 

      // if they're observable 
      if(viewModel[property].subscribe){ 

       // subscribe to changes 
       viewModel[property].subscribe(function(value) { 
        catchChanges(property, value); 
       }); 
      } 
     } 
    } 
    viewModel.isDirty = false; 
} 

function resetViewModel() { 
    changeLog = new Array(); 
    viewModel.isDirty = false; 
} 

(沒有測試它 - 但你應該明白我的意思)

+0

感謝您的迴應 - 是的,正在尋找能夠檢測到任何屬性的任何更改的東西,最好使用upshot屬性 - 一些如何? – user1389723

+0

好的 - 剛回家 - 我會爲你編一段代碼 - 我想你想要某種記錄或Model.IsDirty解決方案? –

+0

這是我心中所想的那種,再次感謝您的幫助。 – user1389723

92

使用擴展:

ko.extenders.trackChange = function (target, track) { 
    if (track) { 
     target.isDirty = ko.observable(false); 
     target.originalValue = target(); 
     target.setOriginalValue = function(startingValue) { 
      target.originalValue = startingValue; 
     }; 
     target.subscribe(function (newValue) { 
      // use != not !== so numbers will equate naturally 
      target.isDirty(newValue != target.originalValue); 
     }); 
    } 
    return target; 
}; 

然後:

self.MyProperty= ko.observable("Property Value").extend({ trackChange: true }); 

現在你可以檢查這樣的:

self.MyProperty.isDirty() 

你也可以寫一些通用視圖模型遍歷是否有任何的改變:

self.isDirty = ko.computed(function() { 
    for (key in self) { 
     if (self.hasOwnProperty(key) && ko.isObservable(self[key]) && typeof self[key].isDirty === 'function' && self[key].isDirty()) { 
      return true; 
     } 
    } 
}); 

...然後只檢查在視圖模型水平

self.isDirty() 
+8

我推薦使用'target.isDirty(!(newValue> = target.originalValue && newValue <= target.originalValue));'而不是'!='在Date對象上不起作用。 – TDaver

+4

感謝這個例子 - 我一直在試圖找到一種方法來改變跟蹤方式,以便原始值和更改後的值可以顯示給用戶。如果有人正在尋找相同的東西,這裏是一個小提琴:http://jsfiddle.net/dKk9P/ –

+0

如果你沒有財產的價值呢? –

2

我有同樣的問題,我需要觀察viewModel的任何變化,爲了發送數據回到服務器, 如果有人仍位數的,我做了一些研究,這是iv'e設法聚集了最好的解決辦法:

function GlobalObserver(viewModel, callback) { 
    var self = this; 
    viewModel.allChangesObserver = ko.computed(function() { 
     self.viewModelRaw = ko.mapping.toJS(viewModel); 
    }); 
    viewModel.allChangesObserver.subscribe(function() { 
     callback(self.viewModelRaw); 
    }); 
    self.dispose = function() { 
     if (viewModel.allChangesObserver) 
      viewModel.allChangesObserver.dispose(); 
     delete viewModel.allChangesObserver; 
    }; 
}; 

爲了使用這種「全球觀察者」:

function updateEntireViewModel() { 
    var rawViewModel = Ajax_GetItemEntity(); //fetch the json object..  
    //enter validation code here, to ensure entity is correct. 
    if (koGlobalObserver) 
     koGlobalObserver.dispose(); //If already observing the older ViewModel, stop doing that! 
    var viewModel = ko.mapping.fromJS(rawViewModel);   
    koGlobalObserver = new GlobalObserver(viewModel, Ajax_Submit); 
    ko.applyBindings(viewModel [ ,optional dom element]); 
} 

注意,給出的回調(在這種情況下爲'Ajax_Submit')將在視圖模型上發生的任何更改上觸發,因此我認爲建議使用某種延遲機制僅在用戶完成編輯屬性時才發送實體:

var _entitiesUpdateTimers = {}; 

function Ajax_Submit(entity) { 
    var key = entity.ID; //or whatever uniquely related to the current view model.. 
    if (typeof _entitiesUpdateTimers[key] !== 'undefined') 
     clearTimeout(_entitiesUpdateTimers[key]);  
    _entitiesUpdateTimers[key] = 
     setTimeout(function() { SendEntityFunction(entity); }, 500);   
} 

我是新來的JavaScript和淘汰賽框架,(只有我開始這個完美的事情,框架工作yestarday),所以不要生我的氣,如果我做錯了什麼。( - :

希望這有助於!

+0

有趣,您正在使用淘汰賽以獲得更快的使用體驗。然後在客戶端的每一個變化你承諾服務器:)你更好的與常規綁定,更簡單,更容易;) – lordkain

3

您可以使用下面的這個插件:

https://github.com/ZiadJ/knockoutjs-reactor

例如將讓你保持的任何視圖模型內的所有變化跟蹤代碼:

ko.watch(someViewModel, { depth: -1 }, function(parents, child) { 
    alert('New value is: ' + child()); 
}); 

PS:由於現在,這不適用於嵌套在數組中的可訂閱書,但支持它的新版本正在開發中。

更新:示例代碼已升級到v1.2b版本,該版本添加了對數組項目和可訂閱的可訂閱屬性的支持。

+0

嘿,只是想知道......你有沒有想過構建數組功能? –

+0

我在knockout.reactor.latest.js中做了一些快速的改變,希望這能解決數組問題,但我還沒有時間去測試它。所以,請隨時自己檢查一下,如果你仍然有問題,請告訴我。 – Ziad

+0

這很酷,我實際上一直在研究類似的功能,並且很快就會發布關於它的博客,所以我們可以比較一下注釋。 –

2

我已經調整了@Brett Green代碼並對其進行了擴展,以便我們可以接受AcceptChanges,將模型標記爲不髒並且將模型標記爲可追蹤的。下面是代碼:

var viewModel = { 
    name: ko.observable() 
}; 

ko.track(viewModel); 

http://jsfiddle.net/david_freire/3HZEu/2/

+0

小提琴死了。 – Will

+0

@仍然會在這裏工作得很好.. –

+0

一定是暫時的。 – Will

1

我採取視圖模型的快照頁面加載時,再後來該快照比較當前視圖模型這樣做。我不關心哪些屬性發生了變化,只要有變化。

拍攝快照:

var originalViewModel = JSON.stringify(ko.toJS(viewModel)); 

後比較:

if(originalViewModel != JSON.stringify(ko.toJS(viewModel))){ 
    // Something has changed, but we don't know what 
} 
+3

以供將來參考,'JSON.stringify(ko.toJS(VM))'與'ko.toJSON(vm)'相同。 – nategood

1

考慮視圖模型如下

function myViewModel(){ 
    var that = this; 
    that.Name = ko.observable(); 
    that.OldState = ko.observable(); 
    that.NewState = ko.observable(); 

    that.dirtyCalcultions - ko.computed(function(){ 
    // Code to execute when state of an observable changes. 
}); 
} 

您綁定您的數據後,您可以存儲使用KO狀態.toJS(myViewModel)函數。

myViewModel.Name("test"); 
myViewModel.OldState(ko.toJS(myViewModel)); 

您可以將您的視圖模型內聲明一個變量作爲計算觀察到的一樣

that.dirtyCalculations = ko.computed(function() {}); 

在有變化的任何視圖模型內的其他可觀察的這個計算功能將被輸入。

然後,你可以比較兩個視圖模式狀態爲:

that.dirtyCalculations = ko.computed(function() { 
    that.NewState(that); 

    //Compare old state to new state 
    if(that.OldState().Name == that.NewState().Name()){ 
     // View model states are same. 
    } 
    else{ 
     // View model states are different. 
    } 

});

**注意:此計算的可觀察函數也在視圖模型初始化時第一次執行。 **

希望這有助於! 乾杯!

5

考慮使用Knockout-Validation plug-in

它實現了以下內容:

yourProperty.isModified() - 如果用戶修改的值檢查。

yourProperty.originalValue - 所以你可以檢查值是否真的改變。

隨着其他驗證的東西,派上用場!

乾杯