* UPDATE * (смотри ниже)KnockoutJS - ViewModel Abstracion
Я понимаю основы KnockoutJS. При создании таблицы viewmodel, можно было бы использовать <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>
Главная ViewModel
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 , Но потом я получил сообщение об ошибке [Эта система шаблонов не поддерживает использование привязки foreach
] (или что-то в этом роде). Поэтому
Моя вторая попытка была реализовать абстракцию, как это должно быть реализовано: со свойствами таблицы (колонны и т.д.) на другой «уровень абстракции», чем данные таблицы:
- Создание основной
<tr data-bind="foreach: rows">
HTML при создании новой конкретной модели табличного представления с использованием «абстрактного» шаблона - это я просто сделал с помощью _.template Underscore. - Пусть эта конкретная модель просмотра использует вышеуказанный 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 сообщает мне, что привязки перепутаны в html для моей конкретной модели (которая вставлена в <div>
.Если я вставляю строки [A]
и [B]
, то она работает для начальных данных ([D]
), но после этого не отвечает.
Все в порядке: я довольно смущен про что-то простое, как абстрагирование вида. Разве нет стандартного решения для этого в KnockoutJS? (Я искал googled, но не мог найти ничего ...) Или я просто испортил это сам (вполне возможно)? ;)
* 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