*更新* (下記参照)
KnockoutJS の基本を理解しています。テーブルビューモデルを作成するときは、次を使用します<tr data-bind="foreach: rows">
現在、同じ動作 (並べ替え、編集、ページネーションなど) で複数のテーブルを作成できるように、テーブル ビューモデルを抽象化しようとしています。だから私が目指しているのは次のようなものです:
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] の例に使用しています。
よくわかりませんが、このプラグインでは抽象化の基本概念がうまく表現されていないと思います。、などの<th>
要素に css クラスを含めようとしたとき、属性を使用するのは簡単ではない (不可能?) ことがわかりました。<th class="col col-id">
<th class="col col-name">
data-bind
これらのdata-bind
クラスは変更されないため、属性はおそらくこのようなものには使用しないでください。これらのクラスは、より高い抽象化レベルの一部です。これらのクラスは、jQuery.tmpl または Underscore のテンプレート システムで実際に挿入する必要があります。しかし、[このテンプレート システムはバインディングの使用をサポートしていませんforeach
] (またはそのようなもの) というエラーが表示されました。
したがって、私の2番目の試みは、実装されるべき抽象化を実装することでした.テーブルプロパティ(列など)をテーブルデータとは別の「抽象化レベル」で使用します。
- 「抽象」テンプレートを使用して、新しい特定のテーブル ビュー モデルのインスタンス化で基本的な html を作成します
<tr data-bind="foreach: rows">
。これは、Underscore の _.template を使用して単純に行いました。 - この特定のビューモデルが通常どおり上記の 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>
コーヒースクリプト
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 [...]