amber Smalltalk で knockout.js を使ってみた

先日の[第78回Smalltalk勉強会] (http://www.smalltalk-users.jp/Home/gao-zhi/dai78kaismalltalkbenkyoukai)の[デモプログラム] (https://github.com/tty-hayashi/LindaClientDemo) でMVVMフレームワーク knockout.js を amber Smalltalk から利用したときの手順覚書です。
自分用忘備録と本編資料のフォローもかねて走り書き。

*  knockout.js ロード設定手順の概略

* knockout.js を使った例


# knockout.js ロード設定手順の概略
1. knockout.js を stプロジェクトに bower で追加
2. {ライブラリ名}.amd.json ファイルの作成
3. grunt devel で config.js と the.js の更新
4. Packege の impoorts 指定

## 1. knockout.js を stプロジェクトに bower で追加
amber Smalltalk のプロジェクトディレクトリでターミナルを使った作業。
knockout.js を bower で追加指定。

``` bash:
$ bower knockout —save
```

## 2. {ライブラリ名}.amd.json ファイルの作成
jsライブラリの場所を指定するファイルを作成する。

ファイル名: knockout.amd.json

``` json: 
{
    "paths": {
          "knockout" : "dist/knockout"
    }
}
```

## 3. grunt devel で config.js と the.js の更新
grunt を実行して config.js と the.js を更新する。

``` bash:
$ grunt devel
```

ここまではターミナルでの作業。

## 4. Packege の impoorts 指定
ここからは amber Smalltalk での作業。
Helios を使ってるならばパッケージの定義で、以下の ‘ko’ -> ‘knockout’ のように knockout.js の参照を定義する。これで ko という名前で参照が可能になる。

``` smalltalk:
Package
    named: 'LindaClientDemo'
    imports: {'ko' -> 'knockout'. 'amber/jquery/Wrappers-JQuery'. 'amber/web/Web'. 'silk/Silk'}
    transport: (AmdPackageTransport namespace: 'amber-lindaclient')
```

***

# knockout.js を使った例
knockout.jsの使い方について、体系的に説明すべきなんですが、とりあえず先日の [第78回Smalltalk勉強会でのデモプログラム](https://github.com/tty-hayashi/LindaClientDemo) のコードの解説でカンベンしてください。
（knockout.js の全機能のトライはまた改めて）

* SELECT タグでのリストと選択肢について

* オブジェクトのリストとTABLEタグ表示

## SELECT タグでのリストと選択肢について
HTML 側にdata-bind:アトリビュートでバインドする対象の指定を行い
その対象名をキーとしてobservale な値を持つオブジェクトもしくはJSONを applyBindings する。

``` smalltalk: 
"LindaClientApp >> setupViewModel"
"模式的なViewModelの例"
"インスタンス変数 viewModel は #{} で初期化されてることとする"

self viewModel addAll: #{
        #availableServers -> (ko observableArray: LindaClient serverUrls) .
        #serverUrl -> (ko observable: LindaClient defaultServerUrl) 
    }.
```

このViewModelをknockoutに登録する。

``` smalltalk: 
"LindaClientApp >> augmentPage"
ko applyBindings: viewModel.
```

データバインディングには、リストのoptions: と選択値は value: で指定する。

``` html:
<div>
    <p>lindaサーバーURL: 
    <select data-bind="options: availableServers,
                       value: serverUrl,
                       optionsCaption: '-選択してください-'"></select></p>
</div>
```

## オブジェクトのリストとテーブル表示
LindaThermoController デモで温度とコマンド結果一覧をテーブルで表示している箇所。

![thermo.PNG](https://qiita-image-store.s3.amazonaws.com/0/13174/7a7d2b73-a9a2-ad49-73aa-800d68702e4c.png)

テーブルはThermoTupleのリストで各ThermoTupleのセンサ名と温度と時刻を表示する。

``` smalltalk: 
"LindaThermoController >> setupViewModel"
     viewModel addAll: #{
        #workers -> (ko observableArray: #())
    }.
```

データバインディング

``` html:
  <table>
    <thead>
      <tr>
        <th>sensor</th><th>celsius</th><th>time</th>
      </tr>
    </thead>
    <tbody data-bind="foreach: workers">
      <tr>
    <td data-bind="text: sensor"></td>
    <td data-bind="text: celsius"></td>
    <td data-bind="text: time"></td>
      </tr>
    </tbody>
  </table>
```
ただし、テーブル表示の要素はstオブジェクトではなくJSONもしくはHashedCollection である必要がある。

``` smalltalk: 
dataOfWorkerList
    "LindaThermoController >> dataOfWorkerList"
    "TupleオブジェクトからJSONのdataのリストを作る"
    ^self workerList collect: [:e | e data]
```

``` smalltalk:
(self viewModel at: #workers) value: self dataOfWorkerList. 
```


## 参考URL
* [第78回Smalltalk勉強会でのデモプログラム](https://github.com/tty-hayashi/LindaClientDemo)
* [Knockout 日本語ドキュメント](http://kojs.sukobuto.com)