AngularJSの $resource でサーバからデータを読み込む

JavaScript

AngularJSには標準の HTTP通信クライアントとして $httpが用意されているが、RESTfulなサーバ側データにアクセスすることを想定した高レベルAPIである $resourceもあるので使ってみる。

$resourceを利用するには、angular-resource(.min).js をロードし、アプリケーションの依存モジュールとして "ngResource" を指定する必要がある。

$resourceを使ったサーバへのアクセスは次のように行われる

  1. サーバ側のURIを指定し、リソースオブジェクトを作成する。URIの構成要素は :で始まる名称を付けることでパラメータ化できる。
  2. 作成したリソースオブジェクトに対し、get/save/query/remove/delete といった関数の呼び出しを行うことでサーバとの通信を開始する。この時、パラメータを与えることが出来る。先に指定したURIに含まれているパラメータを与えればその部分に適用されるし、そうでないものはクエリパラメータなどとして付加される。
  3. サーバから返ってきた結果をもとにバインドされたオブジェクトが更新され、画面表示に反映されるなどする。この処理は普通、AngularJSによって自動的に行われる。

非同期通信を行うプラットフォームではいつものことだが、「2が行われてから3に至るまでの間」という状態が存在することに注意すること。非同期通信に慣れていない人は 2の処理を行った直後にサーバからの応答が既に得られているものと思い込んで応答結果に対する処理を記述してしまうというプログラミングミスをよくする。

サーバから返ってくるのが JSONオブジェクトである場合(つまり一番外側の括弧が {} の場合)は get 関数を使い、JSONアレイ(一番外側の括弧が[])の場合は query関数を使う必要があることにも注意すること。

サンプルでは、東京都千代田区神田の郵便番号一覧を JSONファイルにしたものをサーバから読み込んで表示している。

絞り込みを行う機能も付けてみた。絞り込み処理はサーバ側でなくクライアント側で AngularJSのfilter機能を使って行っている。

サーバ側で絞り込みをするように改良するには(サーバ側で絞り込みのロジックを実装するのはもとより)、

  • query()を呼び出す際の引数として絞り込みのキーワード(=postalNumber)を渡す
  • テキストボックスにバインドされたスコープ変数 postalNumber を $watch し、何らかの入力が行われる度に改めて query()を呼び出す

のようにする必要があるだろう。

resource.html

<html lang="ja" ng-app="MyApp">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular-resource.min.js"></script>
    <script language="javascript">
      angular.module("MyApp", ["ngResource"])
        .controller("MyController", ["$scope","$resource",function($scope,$resource) {
          var contents = $resource("./contents.json");
          $scope.postalNumber = "101";
          $scope.contents = contents.query(); // getはobject、queryはarray
        }]);
    </script>
    <title>$resourceを使ってサーバからデータを読み込む</title>
  </head>
  <body>
    <div class="container" ng-controller="MyController">
      <p class="lead">$resourceを使ってサーバからデータを読み込む</p>
      <p>郵便番号又は住所の一部: <input type="text" ng-model="postalNumber"></p>
      <dl class="dl-horizontal">
	<dt ng-repeat-start="entry in contents | filter:postalNumber">{{entry[0]}}</dt>
	<dd ng-repeat-end>{{entry[1]}}</dd>
      </dl>
    </div>
  </body>
</html>

contents.json

[
    ["1010029","東京都千代田区神田相生町"],
    ["1010063","東京都千代田区神田淡路町"],
    ["1010024","東京都千代田区神田和泉町"],
    ["1010033","東京都千代田区神田岩本町"],
    ["1010052","東京都千代田区神田小川町"],
    ["1010045","東京都千代田区神田鍛冶町"],
    ["1010036","東京都千代田区神田北乗物町"],
    ["1010035","東京都千代田区神田紺屋町"],
    ["1010026","東京都千代田区神田佐久間河岸"],
    ["1010025","東京都千代田区神田佐久間町"],
    ["1010051","東京都千代田区神田神保町"],
    ["1010041","東京都千代田区神田須田町"],
    ["1010062","東京都千代田区神田駿河台"],
    ["1010046","東京都千代田区神田多町"],
    ["1010048","東京都千代田区神田司町"],
    ["1010043","東京都千代田区神田富山町"],
    ["1010054","東京都千代田区神田錦町"],
    ["1010037","東京都千代田区神田西福田町"],
    ["1010022","東京都千代田区神田練塀町"],
    ["1010028","東京都千代田区神田花岡町"],
    ["1010034","東京都千代田区神田東紺屋町"],
    ["1010042","東京都千代田区神田東松下町"],
    ["1010027","東京都千代田区神田平河町"],
    ["1010023","東京都千代田区神田松永町"],
    ["1010038","東京都千代田区神田美倉町"],
    ["1010053","東京都千代田区神田美土代町"]
]

なお、Safariと Firefoxでは resource.html と contents.jsonを Webサーバにアップロードせずにローカルファイル(file://...)のまま開いても動作を確認出来る。ChromeではローカルファイルだとJSONをロードできず。IEは未検証。Operaは(自分の環境では)クラッシュした。

同じカテゴリの記事

Angular.JSでselect要素にoptionをぶら下げる色々な方法 2014年3月29日
AngularJSで、時間のかかる通信の間にモーダルを使ってプログレスバーを表示する 2014年3月18日
HTML5アプリケーションでの、サーバとクライアントの時差について 2014年3月17日
AngularJSの $resourceを使って application/x-www-form-urlencoded 形式のリクエストを POSTする 2014年3月15日
AngularJSと UI Bootstrapで日付と時刻の入力をする 2014年3月14日

お勧めカテゴリ

英語でアニメ観ようず
なじみ深い日本製アニメの英語版DVDで、字幕と音声から英語を学びましょうという趣旨のシリーズ記事です。
ScalaのようでJavaだけど少しScalaなJSON API
Scalaと Spring Frameworkを使って REST的なJSON APIを実装してみましょう。
ドクジリアン柔術少女 すから☆ぱいそん
代表 嶋田大貴のブログです。写真は神仏に見せ金をはたらく罰当たりの図