angular-resourceでローカルjsonファイルを読み込み、ngStorageでWebStorageにデータを保存して扱う方法

## 概要
タイトルのとおりです。そんな需要があるのかないのかわかりませんが、勉強になったのでメモ代わりに。

## 前提、動機
以下のようなデータを初期値としてファイルから読み込みたかったのですが、データの保存も考慮するとファイル書き込みよりもWebStorage(僕の場合はLocalStorage)に保存して扱いたいと思ったのがきっかけです。
HTML5アプリ(Android/iOS)だったので、ファイル保存手段としてngResourceのPOSTメソッドを使えなかったという事もあります。

```JSON:data.json
[
  {
    "author": "Archer",
    "title": "Aces: nothing else comes close."
  },{
    "author": "Chopper",
    "title": "Rock'n Roll is my life."
  },{
    "author": "Edge",
    "title": "let me fly as your wingman just a little while longer..."
  },{
    "author": "Swordsman",
    "title": "Faces of Aces"
  }
]
```

## 用語
- angular-resource = ngResource = $resource: 同じことです。最初は区別しようと思っていたのですが断念。。
- ngStorage = $storage: 同じです。

## 解決策の概要
- 初期値ファイルの読み込みにはngResource(angular-resource)を使います。
  ただし、書き込み(POST)はサーバ側の実装が必要になるので読み込み(GET)のみ使います。
- WebStorageはngStorageを用いました。$watchを使った双方向バインディングが強力です。

## 手段の詳細
#### 1. angular-resourceとngStorageをインストールする。

`bower install ngstorage angular-resource`

- ng'**S**'torageではなく、sを小文字で入力してください。
- `--save`オプションをつけた方がbower.jsonに依存性を保存できるので便利ですね。

#### 2. index.htmlでライブラリのjsファイルと自分のjsファイルをincludeします。

```HTML:index.html
<!doctype html>
<html>
  <head><meta charset="utf-8">
    <!-- angular, angular-resource, ngStorageを読み込み -->
    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/angular-resource/angular-resource.js"></script>
    <script src="bower_components/ngstorage/ngStorage.js"></script>
    <!-- メインロジックを読み込み -->
    <script src="app.js"></script>
  </head>

  <body ng-app="StrageTestApp">
    <div ng-controller="MainCtrl as mc"> <!-- 以降mcでアクセス可能 -->
      <ul>
        <li ng-repeat="i in mc.items">
          author: <input ng-model="i.author">
          title: <input ng-model="i.title">
        </li>
      </ul>
    </div>

  </body>
</html>
```

#### 3. Javascriptでangularのコードを記載します。以下、ポイントです。
  - angular.moduleでngResourceとngStorageをinjectします。
  - Local Storageを使う場合はconfigで$localStorageProviderに
    prefixをつけた方がbetterです。
    同サイトの他のwebアプリとデータが混在してしまうためです。
    Session Storageの場合はあまり気にならないと思います。
  - factoryでデータの読み込みとLocal Storageへのバインドを行います。
    - ngResourceは遅延実行される点がポイントです。$promiseを使いましょう。

```Javascript:app.js
'use strict';

/**
 * app definition
 * ここでngResourceとngStorageをinjectionする
 */
angular.module('StrageTestApp', [
  'ngResource',
  'ngStorage'
])
.config(['$localStorageProvider',
    function ($localStorageProvider) {
        // prefixをつけないと他のwebアプリと混在してしまいます。
        $localStorageProvider.setKeyPrefix('StrageTest');
    }]);

/**
 * controller
 * サービスとindex.htmlとの橋渡しをする。
 */
angular.module('StrageTestApp')
  .controller('MainCtrl', ['MainService', function(MainService){
    // $scopeでもOKです。
    this.items = MainService.all(); // $localStorageをitemsへ
  }]);

/**
 * service(factoryサービス)
 * 1. ngResourceでdata.jsonから読み込む
 * 2. 1.をlocalStorageに保存する
 *    - session storageを使いたい場合は$sessionStorageを。
 * all: localStorageオブジェクトを返却するメソッド
 */
angular.module('StrageTestApp')
  .factory('MainService', ['$resource', '$localStorage',
    function($resource, $localStorage){

      // $resource(ngResource)を使って読み込む
      var res = $resource('data.json');

      // $resourceは遅延実行なので$promiseを使ってデータを取得できるまで
      // 待ってから$localStorageへ保存
      var data = res.query();
      data.$promise.then(function(){
        $localStorage.$default(data); // localStorageの$defaultへ
      });

      // factoryサービスのreturn部
      return{
        all: function(){
          return $localStorage; // $localStorageを返す
        }
      };
    }]);

```

## 動作結果
- 一度バインドしてしまえば、angularの双方向バインドが効き、一文字単位で入力内容が
  Web Storageに反映されます。非常に便利だと思います。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/53948/4cc79b8f-e71c-0376-5032-6407575c16d9.png)

![2.png](https://qiita-image-store.s3.amazonaws.com/0/53948/8aeb3453-bae7-1cff-b417-87290b7d44bf.png)

## 議論、future work
- 全てをローカルで実施したい場合は使いやすいのではないかと思います。
- ngStorageのprefixはまだ課題があるようでしたが [(参考1)](http://qiita.com/amoO_O/items/d55a367dd29bb38eab6c)、今は特に問題なさそうに見えます
。どなたか情報あれば。

## 参考リンク
[AngularJSでの非同期処理](http://www.slideshare.net/likr/angularjs-35612212)
[本家：$resourceのドキュメント](https://docs.angularjs.org/api/ngResource/service/$resource)
[GitHub:ngStorage](https://github.com/gsklee/ngStorage)
[参考1: webStorage を便利に使う angularJS用モジュールを作った by amoO_O氏](http://qiita.com/amoO_O/items/d55a367dd29bb38eab6c)