AngularJS で Web API を呼び出す

AngularJS で Web API を呼び出すのに使う $resource が、ドキュメントを読んだだけじゃイマイチ分からなかったんで、簡単なサンプルを書いてみた。

まず、呼び出す対象の Web APISinatra でさくっと作成。

# coding: utf-8
require "sinatra"
require "json"

# データはメモリ上に保存
# 行儀よくないけど定数に配列を入れてしまう
GUESTS = []

get "/" do
  erb :index
end

# ゲスト一覧を JSON で取得する API
get "/guests" do
  content_type :json, :charset => "utf-8"
  GUESTS.to_json
end

# ゲストを追加する API
post "/guests" do
  # POST したデータを params から取得できなかったので
  # body を JSON にパース
  @guest = JSON.parse(request.body.read.to_s)
  GUESTS << @guest

  content_type :json, :charset => "utf-8"
  @guest.to_json
end

んで、こいつを呼び出す AngularJS を使ったサンプル。

<!DOCTPE html>
<html ng-app="app">
  <head>
    <meta charset="utf-8">
    <title>Angular Sample</title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular-resource.min.js"></script>
    <script type="text/javascript">
    // ngResource を依存モジュールに指定
    angular.module("app", ["ngResource"]);

    // メインコントローラー
    function MainCtrl($scope, $resource) {
      // API の URL を指定してモデルを作成
      var Guest = $resource("/guests");

      // query でコレクションを取得
      $scope.guests = Guest.query();

      $scope.guestName = "";

      $scope.addGuest = function() {
        Guest.save({ name: $scope.guestName }, function(guest) {
          // 作成に成功したら一覧に追加する
          $scope.guests.push(guest);
        });

        $scope.guestName = "";
      };
    }
    </script>
  </head>
  <body ng-controller="MainCtrl">
    <input type="text" ng-model="guestName" placeholder="Input name"/>
    <button ng-click="addGuest()">Add</button>
    <ul>
      <li ng-repeat="guest in guests">{{ guest.name }}</li>
    </ul>
  </body>
</html>

ポイントは、

  1. 依存モジュールに ngResource を指定すると $resource が使えるようになる
  2. $resource を使って Web API を呼び出すためのクラスを生成する
  3. 生成したクラスの query や get や save を使って Web API を呼び出す

ってところかな。ドキュメントだと難しく感じたけど、意外と簡単に使えた。

最後に、今回のサンプルの全体を貼り付けておく。

# coding: utf-8
require "sinatra"
require "json"

# データはメモリ上に保存
# 行儀よくないけど定数に配列を入れてしまう
GUESTS = []

get "/" do
  erb :index
end

# ゲスト一覧を JSON で取得する API
get "/guests" do
  content_type :json, :charset => "utf-8"
  GUESTS.to_json
end

# ゲストを追加する API
post "/guests" do
  # POST したデータを params から取得できなかったので
  # body を JSON にパース
  @guest = JSON.parse(request.body.read.to_s)
  GUESTS << @guest

  content_type :json, :charset => "utf-8"
  @guest.to_json
end

__END__
@@ index
<!DOCTPE html>
<html ng-app="app">
  <head>
    <meta charset="utf-8">
    <title>Angular Sample</title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
     <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular-resource.min.js"></script>
    <script type="text/javascript">
    // ngResource を依存モジュールに指定
    angular.module("app", ["ngResource"]);

    // メインコントローラー
    function MainCtrl($scope, $resource) {
      // API の URL を指定してモデルを作成
      var Guest = $resource("/guests");

      // query でコレクションを取得
      $scope.guests = Guest.query();

      $scope.guestName = "";

      $scope.addGuest = function() {
        Guest.save({ name: $scope.guestName }, function(guest) {
          // 作成に成功したら一覧に追加する
          $scope.guests.push(guest);
        });

        $scope.guestName = "";
      };
    }
    </script>
  </head>
  <body ng-controller="MainCtrl">
    <input type="text" ng-model="guestName" placeholder="Input name"/>
    <button ng-click="addGuest()">Add</button>
    <ul>
      <li ng-repeat="guest in guests">{{ guest.name }}</li>
    </ul>
  </body>
</html>

Sinatra のファイル内テンプレートを使っているので、適当なファイル名で保存して、ruby コマンドで実行すれば、すぐ試せるはず。