KnockoutJS で WPF の Converter 的なこと (※参考) をやろうとした時、View のコンテキストに一時変数を定義できればいいな、と思いカスタムバインディングを作ってみました。
View 側で変換した値を使いまわしたい、というときに便利です。
できること
基本
※doSomething という関数がグローバルに定義されているとします
View
<div data-bind="variable: { foo: doSomething(someProperty) }">
<!--ko if: foo() == 'hoge'-->
<span data-bind="text: foo"></span>
<!--/ko-->
</div>
このように一時変数が使えます。
ただし someProperty が observable の場合、変更が自動的に反映されません。
反映されるようにするには次のように書きます。
変更を自動反映する書き方
※ someProperty が observable になったとします
View
<div data-bind="variable: { foo: function(){ return doSomething(someProperty()) } }">
<!--ko if: foo() == 'hoge'-->
<span data-bind="text: foo"></span>
<!--/ko-->
</div>
このように無名関数でラップし、getter 関数にすることによって
定義される一時変数を computed にすることができます。
結果、someProperty が書き換わると自動的に反映されるようになります。
Virtual Element
View
<!--ko variable: { foo: function(){ return doSomething(someProperty()) } }-->
<!--ko if: foo() == 'hoge'-->
<span data-bind="text: foo"></span>
<!--/ko-->
<!--/ko-->
仮想エレメント(コメント記法)でも使えます。
Knockout-ES5 に対応してます
Knockout-ES5 はプロパティを ()
なしで参照できるようにしてくれるシンタックスプラグインです。
Knockout-ES5 が読み込まれている場合は以下のように書くことができます。
View
<div data-bind="variable: { foo: function(){ return doSomething(someProperty) } }">
<!--ko if: foo == 'hoge'-->
<span data-bind="text: foo"></span>
<!--/ko-->
</div>
DEMO
http://jsfiddle.net/sukobuto/wpD2u/
コンバータパターンで一時変数を有効活用する例です。
variable-binding
これを ko.applyBindings 呼び出し前のどこかに貼り付ければ使えます。
variable-binding
ko.bindingHandlers['variable'] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var variables = valueAccessor();
for ( var v in variables ) {
if (variables.hasOwnProperty(v)) {
if (ko.isObservable(variables[v])) {
bindingContext[v] = variables[v];
} else if (typeof variables[v] === 'function') {
if (ko.hasOwnProperty('defineProperty'))
ko.defineProperty(bindingContext, v, variables[v]);
else bindingContext[v] = ko.computed(variables[v]);
} else {
bindingContext[v] = variables[v];
}
}
}
}
};
ko.virtualElements.allowedBindings['variable'] = true;