この記事は、knockout.js Advent Calendar 2015の6日目の記事です。 先に5日目に目を通すことを推奨しています。
knockout , knockout-es5 , knockout.punches環境を想定しています。
実はknockoutは、jQueryのプラグイン等の既存のUIライブラリとの相性も良いです。
たとえば、TwitterのBootstrapのjavascript部分関連との連携があげられます。
ほぼほぼ静的なサイトであれば、BootstrapのVia data attributes
だけでも十分な場合も多々ありますが、
knockstrap等の連携ライブラリもあるのでこれらを利用するのも1つの手です。
ただし、knockout-es5での利用を想定していないライブラリが大半なので、knockout-es5環境で2way-bindingにする際には、ko.getObservable(mode,'property-name')でobservableを渡すか、ライブラリ側の拡張が必要になる場合があります。(参考: Knockout ES5 に対応したカスタムバインディングを書く作法 )
個人的には、UIライブラリのモデル操作部分についてはjavascript部分は無理に使う必要はないとも考えています。
この手のUIライブラリは、単純にHTML要素のclassに"active"などのクラスを付替えたりしているだけで、見た目等についてはCSSで制御されていることが大半なので、それら(classの付替え)の処理はknockoutに任せてしまうのも手です。
具体的に、同じく UIライブラリの一種である、semantic uiを例として挙げてみます。
今回はこのチェックボックスを使ってみます。
見た目の切替等制御をknockoutに任せる方法
まず、semantic uiが提供しているscriptを使わずに、knockout側でclassを付替えるサンプルをやってみます。
semantic ui のラジオボタンは、checked classの有無で見た目を切り替えているようなので、
function VM(){
this.often='2';
this.wishNewsletter = false;
ko.track(this);
}
ko.punches.enableAll();
ko.applyBindings(new VM());
<div class="ui form">
<div class="grouped fields">
<label>How often do you use checkboxes?</label>
<div class="field">
<div class="ui radio checkbox {{often=='1'?'checked':''}}">
<input type="radio" id="often-1" class="hidden" name="often" value="1" data-bind="checked:often">
<label for="often-1">Once a week</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox {{often=='2'?'checked':''}}">
<input type="radio" id="often-2" class="hidden" name="often" value="2" data-bind="checked:often">
<label for="often-2">2-3 times a week</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox {{often=='3'?'checked':''}}">
<input type="radio" id="often-3" class="hidden" name="often" value="3" data-bind="checked:often">
<label for="often-3">Once a day</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox {{often=='4'?'checked':''}}">
<input type="radio" id="often-4" class="hidden" name="often" value="4" data-bind="checked:often">
<label for="often-4">Twice a day</label>
</div>
</div>
</div>
</div>
このようにして、oftenの現在値によってchecked classの有無を切り替えることで期待通りの動きをしています。
ニュースレター通知
のトグル部分はより単純で、
<div class="ui toggle checkbox">
<input type="checkbox" data-bind="checked:wishNewsletter">
<label>Subscribe to weekly newsletter</label>
</div>
だけでも動いているみたいです。
CustomBindingを用いて連携する方法
もう1つの方法として、semantic uiが用意しているscriptを忠実に利用する方法で連携してみたいと思います。(サンプル)
function VM(){
this.often='2';
this.wishNewsletter = false;
ko.track(this);
}
ko.punches.enableAll();
ko.bindingHandlers['checkbox'] ={
init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var options = ko.unwrap(valueAccessor())||{};
if(!options.onChange){
options.onChange = function(){
$(this).triggerHandler('click');
};
}
$(element)['checkbox'](options);
}
};
ko.applyBindings(new VM());
<div class="ui form">
<div class="grouped fields">
<label>How often do you use checkboxes?</label>
<div class="field">
<div class="ui radio checkbox" data-bind="checkbox:{}">
<input type="radio" name="often" value="1" data-bind="checked:often">
<label>Once a week</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox" data-bind="checkbox:{}">
<input type="radio" name="often" value="2" data-bind="checked:often">
<label>2-3 times a week</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox" data-bind="checkbox:{}">
<input type="radio" name="often" value="3" data-bind="checked:often">
<label>Once a day</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox" data-bind="checkbox:{}">
<input type="radio" name="often" value="4" data-bind="checked:often">
<label>Twice a day</label>
</div>
</div>
</div>
</div>
<div class="ui toggle checkbox" data-bind="checkbox:{}">
<input type="checkbox" data-bind="checked:wishNewsletter">
<label>Subscribe to weekly newsletter</label>
</div>
この方法は、checkbox
というcustom bindingを定義して、semantic ui のscriptと連携するというアプローチです。
checkbox:{}
には、これらの設定(オプション)のイベントハンドラを設定できます。