Backbone.js Collection.fetch() による一覧画面の描画

Pocket

以前書いた、Backbone.js Model.save()によるPOSTデータをPHPで読み込むに続いて、
Backbone.jsを使ったリソース参照に関する記事です。

Backbone.jsを使った一覧表示サンプル

Backbone.jsのCollectionとModelを使って、Collection.fetchの結果を画面に一覧表示するサンプルを作ってみました。

一覧表示サンプル

サンプルの動作

  1. 「表示」ボタンをクリックすると、ユーザーリソースにGETリクエストを送信
  2. JSON形式のユーザー一覧データを含むレスポンスが返ってくる
  3. 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

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Post Navigation