以前書いた、Backbone.js Model.save()によるPOSTデータをPHPで読み込むに続いて、
Backbone.jsを使ったリソース参照に関する記事です。
Backbone.jsを使った一覧表示サンプル
Backbone.jsのCollectionとModelを使って、Collection.fetchの結果を画面に一覧表示するサンプルを作ってみました。
サンプルの動作
- 「表示」ボタンをクリックすると、ユーザーリソースにGETリクエストを送信
- JSON形式のユーザー一覧データを含むレスポンスが返ってくる
- backbone_fetch_test.jsがレスポンスを解析して画面に表示する
サンプルを構成するファイル
サンプルを動作させているファイルの一覧と、ファイルの内容です。ブログ用にコメント多めに入れてます。
ファイル一覧
- backbone-fetch-test.html
- ユーザー一覧画面
- backbone_fetch_test.js
- ユーザー一覧をfetch(GETリクエスト)して、画面に表示するJavaScript
- backbone_test_user.php
- GETリクエスト先のPHPファイル(ユーザーリソース)
backbone-fetch-test.htmlの一部
ユーザー一覧を表示するテーブルとテンプレート部分です。
tbody内部に、id=”user_row_template”が示すテンプレートにユーザーデータを当てはめたものを表示します。ユーザーデータが取得できなかった場合は、id=”user_norow_template”が示すテンプレートをそのまま表示します。
<table class="table table-bordered table-striped table-condensed rule-list"> <thead> <tr> <th>ID</th> <th>名前</th> <th>郵便番号</th> <th>住所</th> </tr> </thead> <tbody id="user_list_body"> <tr> <td colspan="4">「表示」ボタンを押してください(IDに入力が無い場合は全ユーザーを表示します)</td> </tr> </tbody> </table> <div id="loading" style="padding:10px;"></div> <script type="text/template" id="user_row_template"> <tr> <td><%= user_id %></td> <td><%= name %></td> <td><%= postno %></td> <td><%= address %></td> </tr> </script> <script type="text/template" id="user_norow_template"> <tr> <td colspan="4">データがありません</td> </tr> </script>
backbone_fetch_test.js
入力されたIDをパラメーターにして、fetch(GETリクエスト)します。
$(function() { // ユーザー情報を格納するモデル var User = Backbone.Model.extend({ // 属性指定が無いインスタンス生成の際のデフォルト属性(本サンプルでは無くてもいい) defaults : function() { return { 'data' : { 'user_id' : null, 'name' : null, 'postno' : null, 'address' : null } }; } }); // ユーザー情報モデルを複数格納するためのコレクション var UserList = Backbone.Collection.extend({ // リソースから取得した結果を格納するモデル model : User, // モデルの内容取得先リソース url : './backbone_test_user.php', // リソースから取得した結果をモデルに格納する前に参照できる。 // returnされた値のみがモデルに格納される parse : function(resp) { if (resp.error) { // エラーがあればエラーメッセージ表示 alert(resp.error.message); } // モデルに格納するデータ部分を返す return resp.data; } }); // ユーザー一覧表示領域のビュー var UserView = Backbone.View.extend({ el : '#user_list_body', model : User, collection : UserList, initialize : function(options) { _.bindAll(this, 'render'); this.reset(); }, reset : function() { this.collection = new UserList(); }, render : function() { $(this.el).empty(); // リソースから取得 // (collectionのurlにGETリクエストを送信する) this.collection.fetch({ data : { user_id : $('#user_id').val() }, dataType : 'json', success : $.proxy(this.add, this) }); }, add : function(collection, resp) { var that = this; if (collection.length == 0) { // データが無い →専用のテンプレートを表示 $(that.el).append(_.template($('#user_norow_template').html(), null)); return; } collection.each(function(model) { // コレクションに格納されたモデルの内容を1件ずつテンプレートに当てはめて表示 $(that.el).append(_.template($('#user_row_template').html(), model.attributes)); }); } }); var BtnShowView = Backbone.View.extend({ el : $('#btn_show'), userView : null, initialize : function(data) { this.userView = data.userView; }, events: { // clickイベントの登録 'click' : 'click' }, click : function(e) { // ユーザー一覧を描画する this.userView.render(); } }); var userView = new UserView(); var btnShowView = new BtnShowView({userView: userView}); });
fetchの結果得られるJSONは、このような形式を想定しています。
{ "data": [{ "user_id": [ID], "name": [名前], "postno": [郵便番号], "address": [住所] }, ], "error": { "message": [エラーメッセージ(エラー発生時のみ)] } }
model.attributeを使ってテンプレートに値を当てはめたい場合、data部の属性のみをmodelに設定する必要があります。そこでparseを使ってdata部のみをreturnすることで、data部の属性のみをmodelに設定しています。
parseを使うと、モデルにレスポンスデータが反映される前に、レスポンスデータを参照し、必要な部分だけをモデル属性に設定することができます。
backbone_test_user.php
ユーザーリソースを表します。
Collection.fetch()により送信されたGETパラメータ(ユーザーID)を取得し、値が無ければ全ユーザーを返し、値があればIDに該当するユーザーをJSONで返します。
サンプルのため、getUserListの中で適当にユーザー配列を作っていますが、ユーザー情報をデータベースから取得してユーザー配列を作るというのがよくあるパターンでしょう。
<?php $respBody = array('data' => null, 'error' => null); $userId = $_GET['user_id'] != '' ? $_GET['user_id'] : null; if (empty($userId) || is_numeric($userId)) { $userList = getUserList($userId); foreach ($userList as $user) { $respBody['data'][] = $user; } } else { // エラー $errMsg = 'Detect invalid parameter.'; $respBody['error']['message'] = $errMsg; } echo json_encode($respBody); function getUserList($userId) { $userList = array( 1 => array('user_id'=>1, 'name'=>'東京A子', 'postno'=>'103-0000', 'address'=>'東京都中央区'), 2 => array('user_id'=>2, 'name'=>'東京B子', 'postno'=>'150-0000', 'address'=>'東京都渋谷区'), 3 => array('user_id'=>3, 'name'=>'東京C子', 'postno'=>'105-0000', 'address'=>'東京都港区'), 101 => array('user_id'=>101, 'name'=>'大阪X子', 'postno'=>'530-0000', 'address'=>'大阪府大阪市北区'), 102 => array('user_id'=>102, 'name'=>'大阪Y子', 'postno'=>'539-0000', 'address'=>'大阪府大阪市中央区'), 103 => array('user_id'=>103, 'name'=>'大阪Z子', 'postno'=>'543-0000', 'address'=>'大阪府大阪市天王寺区'), ); if (isset($userId)) { // 該当IDのユーザーだけ抽出 $newUserList = array(); if (isset($userList[$userId])) { $newUserList[$userId] = $userList[$userId]; $userList = $newUserList; } else { $userList = array(); } } return $userList; } // end of file
まとめ
Backbone.jsのCollectionとModelを連携させて、GETリクエストの結果得られたJSON文字列を一覧表示するサンプルでした。
JSONの形式がどのような形であっても、Collectionのparseを使うことで必要な要素のみをModelに反映させられます。
一覧ですから、ページネーションも必要だよねーとかあると思うのですが、そうするともう少し手を加える必要があるので、それはまたの機会にw
最近のコメント