以前書いた、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


最近のコメント