酒と泪とRubyとRailsと

Ruby on Rails と Objective-C は酒の肴です!

Knockout.js X Rails 4.2 入門ガイド

最近仕事の関係で「Knockout.js」 について勉強をしています。knockout.jsを選定した理由はレビューしてくれる経験者がチームに居たからです。 JSは不得手なので、アドバイスをくれる同僚がいるのはほんとうに有難い限りです。

Knockout.jsのメリットは次の2つだと考えています。

- 機能が絞りこまれているので、学習コストが低い
- IE6+などの古いブラウザに対応しているので導入しやすい

今回はRailsに「Knockout.js」を組み込んだサンプルを幾つか紹介していきます。


サンプルソース

今回説明するサンプルのソースコードはGitHubで公開しています。

morizyun/knockout_rails_sample

Rails プロジェクトの作成

1
rails new app_name --skip-turbolinks --skip-bundle

Gemfileへの追加

Gemfileに以下を追加。

1
2
# knockout.js
gem 'knockoutjs-rails'

Gemをインストール

1
bundle install --path=vendor/bundle

Knockout.jsの読み込み設定

app/assets/javascripts/application.jsに以下を追加。

1
//= require knockout

サンプルソースの導入

ここからはKnockout.jsのサンプルソースです。 簡単にこんなことができるんだなぁくらいの紹介です。

Text の監視・出力

Textを監視して、出力するスクリプト。まずはCoffeeScript

1
2
3
4
5
6
textViewModel = ->
  self = this
  self.message = ko.observable("")
  return

ko.applyBindings textViewModel

続いてView側。

1
2
3
4
<input type="value" data-bind="value: message, valueUpdate: 'afterkeydown'"/>
<br/>
<br/>
<span data-bind="text: message"></span>

HTML の監視・出力

HTMLを監視して、出力するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
htmlViewModel = ->
  self = this
  self.message = ko.observable("")
  self.messageHtml = ko.computed((->
    "<em>" + self.message() + "</em>"
  ), self)
  return

ko.applyBindings htmlViewModel

続いてView側。

1
2
3
4
<input type="value" data-bind="value: message, valueUpdate: 'afterkeydown'"/>
<br/>
<br/>
<div data-bind="html: messageHtml"></div>

表示&非表示 の制御

表示&非表示を制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
visibleViewModel = ->
  self = this
  self.isTrue = true
  self.isFalse = false
  return

ko.applyBindings visibleViewModel

続いてView側。

1
2
3
4
5
6
<div data-bind="visible: isTrue">
    Visible Sample Text for isTrue
</div>
<div data-bind="visible: isFalse">
    Visible Sample Text for isFalse
</div>

CSS の制御

CSSを制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
cssViewModel = ->
  self = this
  self.isError = true
  return

ko.applyBindings cssViewModel

続いてView側。

1
2
3
4
5
6
7
8
9
10
11
<style type="text/css">
<!--
.error {
  color: red;
}
-->
</style>

<div data-bind="css: {error: isError}">
    CSS Sample Text
</div>

attr (htmlタグの属性) の制御

htmlタグの属性を制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
attrViewModel = ->
  self = this
  self.hrefAttr = ko.observable(
    href: 'http://www.google.co.jp'
    title: 'Google'
  )
  return

ko.applyBindings attrViewModel

続いてView側。

1
2
3
<a href data-bind="attr: hrefAttr">
    Attr Sample Text
</a>

checkbox (htmlタグ) の制御

checkboxを制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
checkboxViewModel = ->
  self = this
  self.items = ko.observableArray([
    'hoge'
    'piyo'
  ])
  return

ko.applyBindings checkboxViewModel

続いてView側。

1
2
3
4
5
6
7
8
9
<div>
    <input type="checkbox" value="hoge" data-bind="checked: items" /> : hoge
</div>
<div>
    <input type="checkbox" value="fuga" data-bind="checked: items" /> : fuga
</div>
<div>
    <input type="checkbox" value="piyo" data-bind="checked: items" /> : piyo
</div>

foreach (繰り返し) の制御

foreach(繰り返し)を制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
foreachViewModel = ->
  self = this
  self.items = ko.observableArray([
    'hoge'
    'fuga'
    'piyo'
  ])

  self.addItem = ->
    self.items.push('add')
  self.removeItem = ->
    self.items.pop()
  return

ko.applyBindings foreachViewModel

続いてView側。

1
2
3
4
5
6
7
8
9
10
<ul data-bind="foreach: { data: items, as: 'item' }">
    <li><span data-bind="text: $index"></span> : <span data-bind="text: item"></span></li>
</ul>

<div>
    <button data-bind="click: addItem">Add Item</button>
</div>
<div>
    <button data-bind="click: removeItem">Remove Item</button>
</div>

select (htmlタグ) の制御

select (htmlタグ)を制御するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
selectViewModel = ->
  self = this
  self.items = ko.observableArray([{
    id: 11
    name: 'HOGE'
  }, {
    id: 22
    name: 'FUGA'
  }, {
    id: 33
    name: 'PIYO'
  }])

  self.toId = (item) ->
    "id_" + item.id

  self.toLabel =  (item) ->
    "label_" + item.name
  return

ko.applyBindings selectViewModel

続いてView側。

1
2
3
<div>
  <select data-bind="options: items, optionsValue: toId, optionsText: toLabel"></select>
</div>

template の管理

template の管理に関するスクリプト。まずは、CoffeeScript

1
2
3
4
5
6
templateViewModel = ->
  self = this
  self.templateModel = ko.observable({ message: 'Hello Template!!' })
  return

ko.applyBindings templateViewModel

続いてView側。

1
2
3
4
5
<div data-bind="template: {name: 'sampleTemplate', data: templateModel}"></div>

<script type="text/html" id="sampleTemplate">
    <i data-bind="text: message"></i>
</script>

カスタムバインディング(custombinding) の制御

カスタムバインディング(custombinding) の制御に関するスクリプト。まずは、CoffeeScript

1
2
3
ko.bindingHandlers.myBinding = init: (element, valueAccessor, allBindings) ->
  param = valueAccessor()
  element.innerText = 'Custom Binding param = ' + param

続いてView側。

1
<div data-bind="myBinding: 101"></div>

本格的に勉強していくのに役立ちそうな資料

ここから、Knockout.jsを勉強していくのにあたって役に立ちそうな資料のリンクを書いておきます。

あとがき

全体としては、確かに学習コストが少なくて簡単に使い始められそうな印象です。 特定のことをやろうとした時にjQueryよりもわかりやすくコードを書けると思います。


おすすめの書籍