* 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的模板系统插入这些类。但后来我得到一个错误,说[这个模板系统不支持使用绑定](或类似的东西)。因此
我的第二次尝试是实施抽象,因为它应该实现:与另一个“抽象级别”比表中的数据表属性(列等):
- 创建基本
<tr data-bind="foreach: rows">
HTML在实例化一个新的特定表视图模型时,使用“抽象”模板 - 我只是用Underscore的_.template做的。 - 让这个特定的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 [...]
你是什么意思“之后,没有回应”?你在做'var vm = new ViewModel()'和'vm.groupTable.data(newData);'? – freakish
实际上(!)我在做'vm.groupTable.data()。push' ...但是现在我明白这是多么的愚蠢;) –
是的,但你实际上可以做'vm.groupTable.data.push'。没有'()'应该按预期工作。 :) – freakish