KnockoutJS - ViewModel Abstracion

* ОБНОВЛЕНИЕ * (см. Ниже)

Я понимаю основы KnockoutJS. При создании таблицы viewmodel можно использовать <tr data-bind="foreach: rows">

Теперь я пытаюсь абстрагировать модель представления таблицы, чтобы можно было создать несколько таблиц с одинаковым поведением (сортировка, редактирование, разбиение на страницы и т. Д.). Так что я стремлюсь к чему-то вроде этого:

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 привязка] (или что-то подобное).

Поэтому моя вторая попытка заключалась в том, чтобы реализовать абстракцию так, как она должна быть реализована: со свойствами таблицы (столбцы и т. Д.) На другом "уровне абстракции", чем данные таблицы:

  1. Создать основной <tr data-bind="foreach: rows"> HTML при создании новой конкретной модели табличного представления с использованием "абстрактного" шаблона - это я просто сделал с _.template Underscore.
  2. Позвольте этой конкретной модели представления использовать вышеупомянутый 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? (Я гуглил, но не смог ничего найти...) Или я сам все испортил (вполне возможно)?;)

*ОБНОВИТЬ*

Я решил проблему (но, может быть, она не самая лучшая / вообще - каково ваше мнение?), Для полноты картины: (сжатая версия - конечно, вы, вероятно, также захотите наблюдать за строками по отдельности и т. Д.).)

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 [...]

1 ответ

Зачем изобретать велосипед?:П

https://github.com/CogShift/Knockout.Extensions

Другие вопросы по тегам