KnockOut 的 ObservableArray 的資料同步

  • 232
  • 0
  • 2016-01-27

Knockout 的 Observable 機制真的是很棒很成熟,以前在 VB6 要實作 Observable pattern 要花很多的心力把底層做好,就算是 WPF 的 MVVM + Command 也是不那麼容易上手。感恩 Knockout 這個套件將這件事情做得更簡單更好上手。若您考量用最小的資料量下載到頁面中,而且可以希望很容易地同步到頁面,又希望 UX 可以專心的編輯 頁面又不影響到 Server 端的 Code 的話。

Knockout 這個套件真心的推薦給您

Knockout 官網有很多的範例和觀念很重要可以參考,另外,黑大的網站從 2012 年開始也有一系列的文章可以參考。

這次的架構是 ASP.NET MVC 5 + WebAPI + jQuery + Boostrap 3 + Knockout + SignalR 2 的項目,而搭配開發環境是 Visual Studio 2015 。

下面講的問題都很片斷回應,只是整理一些遇到的情況和解法讓各位參考 :)

巢狀的 obserableArray 的 DataBinding

WebAPI 吐回來的 JSON / XML 是屬於有 子類別的話, Data-bind 的寫法基本上都還是一樣。  可以看到 Table 要動態產生 TR 的 code 請直接放在 Tbody 之後再把 TR 並且用 foreach 「物件名稱」即可,而 VedeoList.Jobs 這個子類別名稱也是在指定的 TD 中將 foreach「Jobs」即可,不需要再另外針對 Jobs 底下寫 Jobs.Jobuuid 的,而是直接給 屬性名稱即可。

沒有意外的話,就可以看到資料綁定在頁面上是長這樣子的情況。

Boostrap 的 ProgressBar Data-Binding

這裡是用 Boostrap 的 Progress 樣式,而這裡面最需要注意的是 藍色進度條的顯示是透過 Width :86% 達成的,字的部分則是下面的 P 。若您的 Progress 的值是 double 的話,請務必不要忘記一定要加上「%」不然這裡會無法正常顯示。

當然 P 的部分我已經將 45.44398  的數值透過 Custom DataBinding 的方式自動改成 45% 

 

指定 ObservableArray 的某一個欄位可以雙向 Binding

一開始我以為 observableArray 裡的所有欄位都可以和 UI 雙向 Binding ,但實際上卻不是這麼一回事。因為 observableArray 就跟 Observable Pattern 裡的 Observable Collcetion 相同的等級,它是負責的 Array 的筆數有異動時的通知機制。但每一筆的「內容」是不管你的,因此某一個欄位想要可以雙向 Binding 的話,就必須要再另外指定 Observable 過去。而且我也不喜歡明明就沒有雙向 Binding 的需求卻通通都加上 observable

因此在 $.Ajax 回傳 Done 的 Method 之中我們要將 WebAPI 吐到 Knockout 的 ViewModel 之前,自行將 OverallProgress 的數字改成 observable 即可。 上面的 ColorStatus 欄位則是保持在原本的數值,比較需要注意的是 Knockout 的 Databind 的同一個欄位時不可以某幾筆是 observable 而其他幾筆是一般數值。

指定找 ViewModel 的某一筆資料

由於UI 的更新已經是用 observable 的方式,因此我們就必須要直接修改 ViewModel 的值。而 KO 為了這個需求已經有整理了一堆的 Utils 可以用,其中 ko.utils.arrayFirst 就可以在這個時候派上用場。由於 ViewModel 是巢狀的當然在資料搜尋上也是要巢狀的處理。

若是屬性是「observable」的話,代表這個是 method 所以在第一個 arrayFirst 要加上 () ,而第二組的 jobs 則是一般的資料因此當「屬性」使用就可以。找到資料後只要寫個 return object 就不會再往下找其他的資料了。  這樣子的寫法可以很省工 :)

 

參考資料

Knockout foreach databinding

Knockout Custom databinding