2014-07-22 84 views
2

我遇到了與訂閱的更新沒有約束的淘汰賽模型的問題。我有一個C#MVC頁面,它將模型傳遞給模板,並將模板解析爲Json並作爲ViewModel作業的一部分傳遞給ko.applyBindings。我訂閱了一個observable,它調用一個方法來執行viewModel數據的更新。不相干的東西掏出,並更名爲實例:淘汰賽映射不更新我的模型

var myViewModel = function (data) { 
    var self = this; 

    self.CurrentPage = ko.observable(); 
    self.SomeComplexArray= ko.observableArray([]); 

    self.Pager().CurrentPage.subscribe(function (newPage) { 
     self.UpdateMyViewModel(newPage); 
    }); 

    self.UpdateMyViewModel= function (newPage) { 
     var postData = { PageNumber: newPage }; 
     $.post('/Article/GetMyModelSearchByPage', postData, function (data) { 
      ko.mapping.fromJS(data, {}, self);; 
     }); 
}; 

當我執行日誌記錄,我可以看到所有的數據,而這一切看起來是正確的。使用相同的方法來生成初始模型和更新後的模型。我在其他頁面上使用了這種技術,並且每次都完美無瑕。然而,在這種情況下,我正在尋找它來綁定/更新SomeComplexArray,這只是沒有發生。如果我嘗試手動執行此操作,則無法在數組上得到空白的正確綁定。我想知道是否有什麼明顯的表現,我做錯了,我只是失去了理智。

編輯:我不知道ko.mapping可以指出爲罪魁禍首。標準模型更改也不會影響界面。這是一些不具有約束力的工作。我有一個可見綁定到數組長度的p元素和一個綁定到一個函數的div元素,該函數從SomeComplexArray中彈出項目。我可以在控制檯日誌中看到它正在執行其功能(並且隨後的點擊導致'undefined'沒有該功能)。但是,p元素從不顯示。最初的陣列只有2個項目,使一個單一的點擊清空它:

<p data-bind="visible: SomeComplexArray().length === 0">nothing found</p> 


<div data-bind="click: function() { UpdateArray(); }">try it manually</div> 


-- in js model 
self.UpdateArray = function() { 
     console.log(self.SomeComplexArray()); 
     console.log(self.SomeComplexArray().pop()); 
     console.log(self.SomeComplexArray()); 
     console.log(self.SomeComplexArray().pop()); 
     console.log(self.SomeComplexArray()); 
}); 

編輯2:從評論@馬特Burland,我已經修改了的流行是如何調用和手動的方法現在的作品進行修改動態的元素。然而,ko.mapping仍然沒有像我期望的那樣運行。在測試中,我在調用ko.mapping和之後做了特定行的console.log。對可觀察陣列沒有改變。

+1

數據是什麼樣的?它是一個JavaScript對象嗎? –

+0

@ m.casey:這是一個JSON格式的POCO。在其上使用'JSON.parse()'提供了格式正確且可訪問的對象。 –

+1

我之所以會問這個問題,ko.mapping.fromJS()期望'data'應該是一個JavaScript對象,所以如果我們傳遞'data'而'data'當時仍然是一個JSON對象,它不會工作,對吧?此外,不確定這是否僅僅是複製/粘貼問題,但映射語句末尾存在語法錯誤,$ .post函數後面缺少'}'。 –

回答

0

我不太確定爲什麼,但似乎ko.mapping根本無法重新映射viewmodel。由於沒有任何字段被映射到self我的假設是,有一個異常發生在ko.mapping僅僅是吞嚥的地方,或者由於其他原因沒有被報告。考慮到我可以使用@MattBurland的有用提示手動操作數組,我決定稍微回溯一下,只更新需要在數據加載時直接更改的元素。我結束了創建我的ViewModel的Init功能和使用ko.mapping填充的項目,直接出現:

self.Init = function (jsonData) { 
    self.CurrentPage(0); 
    self.Items(ko.mapping.fromJS(jsonData.Items)()); 
    self.TotalItems(jsonData.TotalItems); 
    // More stuff below here not relevant to question 
} 

這裏的主要區別是,結果所需的ko.mapping.fromJS被稱爲前的功能可觀察陣列將會如此識別它。考慮到這工作,我的控制器將成爲AJAX請求期間提供相同的對象回來,它幾乎複製/過去:

self.UpdateMyViewModel= function (newPage) { 
    var postData = { PageNumber: newPage }; 
    $.post('/Article/GetMyModelSearchByPage', postData, function (data) { 
     self.Items(ko.mapping.fromJS(JSON.parse(data).Items)()); 
    }); 
}; 

這可能是不理想的大多數情況,但因爲沒有大在更新過程中對viewModel的操作提供了一個工作解決方案。我仍然想知道爲什麼ko.mapping不會重新映射頂層的viewModel,但回想起來,它可能會是一場災難,因爲viewModel中有「修改」的數據,服務器將不得不取代它。這個解決方案足夠快速和簡單。

0

我在JSFiddle中創建了一個你的挖空情況的測試。

你必須調用你的數組函數沒有pamentalhesis。我測試了這部分:

self.UpdateArray = function() { 

     self.SomeComplexArray.pop(); 

}; 

它似乎在JSFiddle方面工作。

+0

經過@MattBurland的一些評論,這個手動測試確實有效。但是,原始的ko.mapping仍然無法正常工作。 –

+0

@JoelEtherton,我發現你的問題。你可以檢查我的更新答案。 –

+0

這不是問題所在。那只是我用來測試界面更新的東西,就像我說的,MattBurland的評論幫我糾正了這個問題。問題在於ko.mapping不像最初代碼示例中定義的那樣運行。 –