2012-05-04 72 views
2

* UPDATE *(見下文)KnockoutJS - 視圖模型Abstracion

我明白KnockoutJS的基礎知識。當創建表視圖模型時,可以使用<tr data-bind="foreach: rows">

現在我試圖抽象表viewmodel,以便我可以創建具有相同行爲(排序,編輯,分頁等)的多個表。那麼,我的目標是這樣的:

HTML

<div class="table a" data-bind="myTableBinding: aTableViewModel"></div> 
<div class="table b" data-bind="myTableBinding: anotherTableViewmodel"></div> 

主視圖模型

var MainViewModel = function() { 
    this.aTableViewModel = new AbstractTableViewModel({ 
     columns: [...] 
     initialSort: [...] 
    }); 
    this.anotherTableViewModel = new AbstractTableViewModel({ 
     columns: [...] 
     initialSort: [...] 
    }); 
}; 

我第一次嘗試了模仿的例子[simpleGrid]插件(@http://knockoutjs.com/examples/resources/knockout.simpleGrid.1.3.js)KnockoutJS文檔用於[Paged grid]示例。

我不太確定,但我認爲抽象的基本概念在這個插件中沒有很好地表現出來。當我試圖將css類包含到<th>這樣的元素中時:<th class="col col-id"><th class="col col-name">等,我發現使用data-bind屬性並不容易(不可能?)。

data-bind屬性可能不應該用於這個東西,因爲這些類不會改變 - 它們是更高抽象層次的一部分:我們實際上應該使用jQuery.tmpl或Underscore的模板系統插入這些類。但後來我得到一個錯誤,說[這個模板系統不支持使用綁定](或類似的東西)。因此

我的第二次嘗試是實施抽象,因爲它應該實現:與另一個「抽象級別」比表中的數據表屬性(列等):

  1. 創建基本<tr data-bind="foreach: rows"> HTML在實例化一個新的特定表視圖模型時,使用「抽象」模板 - 我只是用Underscore的_.template做的。
  2. 讓這個特定的viewmodel照常使用上面的html。

在CoffeeScript的:

do -> 
    ko.dataTable = 
    ViewModel: (config) -> 
     @id = config.id 
     @columns = config.columns 
     @pageSize = config.pageSize ? 9999 
     @sortColumn = ko.observable (config.sortColumn ? @columns[0].col) 
     @sortOrder = ko.observable (config.sortOrder ? "asc") 
     @data = ko.observableArray (config.data ? []) 
     null 

    ko.bindingHandlers.dataTable = 
    init: (el, acc) -> 
     viewModel = acc() 
     $(el).find("div:first").html dataTableTemplateMaker viewModel 
     # ??? [A] ko.applyBindings viewModel, $(el).find("table")[0] 
     # ??? [B] controlsDescendantBindings: yes 
     null 
    update: (el, acc) -> 
     viewModel = acc() 
     # ??? [C] 
     null 

然後:

<div data-bind="dataTable: groupTable"> 

和:

class ViewModel 
    constructor: -> 
    @groupTable = new ko.dataTable.ViewModel 
     id: "grouptable" 
     columns: [ 
     { col: "num",  title: "Groep", editable: yes } 
     { col: "subject", title: "Vak" } 
     { col: "year", title: "Jaar" } 
     { col: "level", title: "Niveau" } 
     { col: "day",  title: "Dag" } 
     { col: "hour", title: "Uur" } 
     { col: "place", title: "Lokaal", editable: yes } 
     ] 
     pageSize: 10 
     sortColumn: "num" 
     sortOrder: "asc" 
     data: [] # [D] 

...其中???標誌的地方(一個或多個),其中我的困惑所在。

說我不插入行[A][B]。然後當然KnockoutJS告訴我綁定全部在我的特定視圖模型(插入到<div>中,如果我插入行[A][B]的html)中混淆,那麼它對初始數據起作用(在[D]),但之後沒有迴應。

總而言之:對抽象視圖模型簡單的事情我很困惑。 KnockoutJS中沒有標準的解決方案嗎? (我已經Google搜索,但無法找到任何東西...)或者我只是把它搞亂了(很可能)? ;)

* UPDATE *

我解決了這個問題(但也許它不是最好/孔在所有 - 你有什麼意見),對完整性的緣故:(精簡版 - 當然你可能也想單獨等觀察行..)

HTML(沒錯,就是有意傳給結合處理字符串)

<div data-bind="myTableBinding: 'viewModelPropertyHoldingTableViewModel'"></div> 

的CoffeeScript

class MainViewModel 
    constructor: -> 
    @viewModelPropertyHoldingTableViewModel = new TableViewModel <options> 
    null 

class TableViewModel 
    constructor: (options) -> 
    @columns = options.columns 
    @rows = ko.observableArray (options.rows ? []) 
    [...] 
    null 

tableTemplateMaker = _.template ' 
    <table> 
    <thead> 
     <tr> 
     [% _.map(tableViewModel.columns, function (column) { %] 
     <th>[%= column.title %]</th> 
     [% } %] 
     </tr> 
    </thead> 
    <tbody data-bind="foreach: rows"> 
     <tr> 
     [% _.map(tableViewModel.columns, function (column) { %] 
     <td data-bind="text: [%= column.id %]"></td> 
     [% } %] 
     </tr> 
    </tbody> 
    </table> 
' 

ko.bindingHandlers.myTableBinding = 
    init: (element, viewModelPropertyNameAccessor, _, mainViewModel) -> 
    tableViewModelProperty = viewModelPropertyNameAccessor() 
    tableViewModel = mainViewModel[tableViewModelProperty] 
    $(element).html tableTemplateMaker 
     tableViewModelProperty: tableViewModelProperty 
     tableViewModel: tableViewModel 
    null 

m = new MainViewModel 
ko.applyBindings m 

m.viewModelPropertyHoldingTableViewModel.data.push [...] 
+0

你是什麼意思「之後,沒有迴應」?你在做'var vm = new ViewModel()'和'vm.groupTable.data(newData);'? – freakish

+0

實際上(!)我在做'vm.groupTable.data()。push' ...但是現在我明白這是多麼的愚蠢;) –

+0

是的,但你實際上可以做'vm.groupTable.data.push'。沒有'()'應該按預期工作。 :) – freakish

回答

相關問題