NG-Grid の利用

Angular JSを利用するにあたり、JQuery UIのようなUIライブラリを用いることができます。今回はグリッドが面白かったので、紹介します。

# 導入
bowerで導入するのが手っ取り早いので、bowerで入れます。

``` sh:コマンド
bower install ng-grid
```

いつものようにbower_componentsにインストールされます。

# HTMLへの記述
CSS、Javascript、表示領域に分けて、記述していきます。

## CSSの記述
まず、headにスタイルシートの記述をします。


``` html:grid.htmlの一部（CSS)
<link rel="stylesheet" href="bower_components/ng-grid/ng-grid.css">
```

## Javascriptの記述
次にGridのJSの設定をbodyタグの最後に記述しておきます。

``` html:grid.htmlの一部（JS)
<script type="application/javascript" src="bower_components/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="bower_components/angular/angular.js"></script>
<script type="application/javascript" src="bower_components/ng-grid/ng-grid-2.0.12.debug.js"></script>
<script type="application/javascript" src="js/app.js"></script>
```

## 表示領域の記述

最後に表示領域を記述します。

``` html:grid.htmlの一部（グリッドの表示領域)
<div class="count10" ng-grid="gridOptions" ng-show="myData"></div>
```

これだけですむところがすごいところです。その分、暗黒面が多いので配慮は必要ですが…

表示領域に設定されている　ng-grid="gridOptions"　がポイントで、アプリのJSであるapp.jsにこのgridOptionsを設定することで表示されます。

# アプリ用JSの記述
ng-gridを利用するあたり、重要なのはng-gridに設定する連想配列が重要になります。詳細は以下のURLのAPIセクション参照ください。

http://angular-ui.github.io/ng-grid/


## GridOptionの項目
ここでは重要なものだけを記述してみます。

|キー |説明|
|:---------------|:-----------------------|
|data|表示するオブジェクト（配列）|
|rowHeight|1行の高さ（px）|
|columnDefs|表示するカラムの設定|
|showFooter|フッタの表示フラグ|
|pagingOptions|ページングをおこなう設定のオブジェクト|
|enablePaging|ページングを可能にするフラグ|
|totalServerItems|表示をする件数ではない総件数を設定する|

pagingOptions以降の値はページングする場合に利用します。

## GridOptionの例

後ほど説明する例のpagingOptionsは以下のようにしています。

``` javascript:app.js一部
$scope.gridOptions = {
        data: 'myData',

        enablePaging: true,
        showFooter: true,
        rowHeight:40,
        showFilter:true,
        enableColumnResize:true,

        pagingOptions: $scope.pagingOptions,
        totalServerItems: 'size',

        columnDefs: [
            { displayName: "#",width: 60,cellTemplate: '<div align="right">{{row.rowIndex+startCount}}</div>'},
            { field: 'zipcode', displayName: '郵便番号', width: 90 },
            { field: 'address', displayName: '住所', width: '*', cellTemplate: '<div><a href="{{row.entity[\'link\']}}">{{row.entity[col.field]}}</a></div>' },

        ]
    };
```

### showFilter
showFilterは、グリッドで表示しているデータの一部を検索して絞り込む機能の表示をするかどうかを表しています。

### pagingOptions
pagingを行う場合には、ページング設定オブジェクトを設定します。
詳細は先ほどのURLを参照してください。

ここでは、ページングの画面部品を利用したいので、その内容設定だけをおこないます。以下がその例です。

``` javascript:app.js(一部)
    $scope.pagingOptions = {
        pageSizes: [10, 20, 100],
        pageSize: 10,
        currentPage: 1
    };
```

pageSizesにページングするサイズの選択肢の配列を指定します。
pageSizeが１ページに表示する件数を指定します。
currentPageが現在のページを指定します。

この設定は表示に影響しません。サーバサイドと連携するためにUIに表示する値になります。

### columnDefs
columnDefsが一番重要な設定かもしれません。この設定を省略すると、dataに指定したオブジェクトの属性を列として表示します。属性名がそのまま列名になるので読みにくくなる場合、すべての属性を表示したくない場合などにこの指定をします。

|キー |説明|
|:---------------|:-----------------------|
|field|表示する属性名|
|displayName|表示する列名|
|width|表示の幅|
| cellTemplate |セルで組み立てるHTMLのテンプレート|

ここで設定する配列順に表示されるので、表示する順に配列を設定します。（enableColumnReorderingをgridOptionに設定することで順番をブラウザで変えることもできますが）

上記では、fieldを利用しないことで、dataにないものを表示する工夫をしています。（データの順番番号を表示しています）

cellTemplateは、表示するときのセルのテンプレートなので、ここのHTMLを工夫することで、順序番号を表示しています。　fieldがaddressについては、データの要素の中に住所の詳細リンクが含まれているので、リンクを作成しようと思い、Aタグと詳細のリンクを組み込んだ表示するために作成しています。

表示中のオブジェクトについては、rowという名前のオブジェクトになり、表示しようとしているセルがcolというオブジェクトになりますので、このオブジェクトを利用します。

#サーバとの連携
検索ボタンをクリックしたイベントで、サーバに検索して、その結果を表示するなどがこのng-gridの使い方だと思います。
イベントの処理は、通常のAngularJSとして`$http`などを利用すればよいですが、その場合は`pageOptions`の値と連携することでうまく動作します。

## サーバでの総件数の設定
サーバで検索した結果の総件数を`totalServerItems`に設定することで、ページング部品のページ数などが制御されます。

## pagingOptionの変更監視
ページング部品を操作したら、サーバへ検索する必要があるので、pagingOptionを$watchで検索対象として、値が変更された場合再建策にいくとよいでしょう。

``` javascript:app.jsの一部
$scope.$watch('pagingOptions', function (newVal, oldVal) {
        if(newVal != oldVal){
            $scope.pagingOptions = newVal;
            if(newVal.pageSize != oldVal.pageSize){
                $scope.pagingOptions.currentPage = 1;
            }
            $scope.getData($scope.word,false);
        }

    }, true);
```

getData()がサーバへデータを取得しにいく関数です。

# 実装例
今回の例として、郵便番号を検索できる画面を作ってみました。
郵便番号の値を返してくれるRestのサービスがありましたので、それを利用させていただきました。ありがとうございます。
（リコーのラボさんのサイトです）
http://zip.ricollab.jp/index.html
を参照してください。

実行する場合は、Access-Control-Allow-Origin の問題を解決する必要があります。私はWebStormのJetBrain IDE Supportを利用して、開発テストをしています。

検索キーワードが含まれる住所を取得し、郵便番号と住所をこのng-gridで表示する例です。以下のファイルで構成されています。(GithubのGistにおきました）

最初がgrid.html　表示用のHTMLです。
https://gist.github.com/takayasu/ae76159c4f0cd16ca68e

次は、app.js これがメインのJavascriptファイルです。
https://gist.github.com/takayasu/a008ff5e4da75cf6d796

最後にアプリ用のCSSです。たいした内容ではありませんが、heightを設定しないと表示されないので、貼っておきます。
https://gist.github.com/takayasu/2b39d4b87b77fc95ba00

## 課題
まだ、完全に使いこなせておらず残念なことに課題があります。
ご存知の方は教えてください。

|＃ |課題|
|:---------------|:-----------------------|
|1|検索件数を変えても、高さが変化されない。ng-classをうまく使えてない|
|2|編集設定は可能だが、変更後のイベントをうまく拾えない。$watchだと変更した箇所の特定が大変なので、イベントをどれを使えばいいかがわかっていない|