Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

knockoutと既存UIライブラリの連携

More than 5 years have passed since last update.
この記事は、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の有無で見た目を切り替えているようなので、

javascript
function VM(){
    this.often='2';
    this.wishNewsletter = false;
    ko.track(this);
}

ko.punches.enableAll();
ko.applyBindings(new VM());
html
<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の有無を切り替えることで期待通りの動きをしています。

ニュースレター通知のトグル部分はより単純で、

html
<div class="ui toggle checkbox">
  <input type="checkbox" data-bind="checked:wishNewsletter">
  <label>Subscribe to weekly newsletter</label>
</div>

だけでも動いているみたいです。


CustomBindingを用いて連携する方法

もう1つの方法として、semantic uiが用意しているscriptを忠実に利用する方法で連携してみたいと思います。(サンプル)

javascript
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());

html
<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:{}には、これらの設定(オプション)のイベントハンドラを設定できます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away