今回は、簡単な編集と削除機能を作ります。
こんな感じ
前回からの追加内容をざっくりと書くとー
レイアウトに編集画面用のレイアウト追加
モデルに保存、削除時の送信先となるurlを設定
あとは、保存、削除ボタン押下時の処理を記述といった感じです。
では、さっそく
layout.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>backbone.jsの超簡単サンプル 2回目</title>
</head>
<body>
<!-- view表示用タグを埋め込む -->
<div id="about"></div>
<br>
<div id="memberDetail"></div>
<!-- ここは外部ライブラリの読み込み -->
<script src="js/lib/jquery-2.1.4.min.js"></script>
<script src="js/lib/underscore-min.js"></script>
<script src="js/lib/backbone-min.js"></script>
<!-- template読み込み -->
<!-- チーム紹介 template -->
<script type="text/template" id="about-template">
<div>
<div>名前: <span><%= name %></span></div>
<div>生年月日: <span><%= birthday %></span></div>
<div>ポジション: <span><%= position %></span></div>
<div><input type="button" class="detail" value="詳細" id="<%= index %>"></div>
<div><input type="button" class="edit" value="編集" id="<%= index %>"></div>
</div>
</script>
<!-- メンバー詳細 template -->
<script type="text/template" id="member-detail-template">
<div>
<div>名前: <span><%= name %></span></div>
<div>生年月日: <span><%= birthday %></span></div>
<div>ポジション: <span><%= position %></span></div>
<div>背番号: <span><%= number %></span></div>
<div>趣味: <span><%= hobby %></span></div>
<div>今季の意気込み: <span><%= zeal %></span></div>
</div>
</script>
<!-- メンバー詳細(編集用) template -->
<script type="text/template" id="edit-member-detail-template">
<div>
<div>名前: <input type="name" value="<%= name %>" id="name" ></div>
<div>生年月日: <input type="birthday" value="<%= birthday %>" id="birthday" ></div>
<div>ポジション: <input type="position" value="<%= position %>" id="position" ></div>
<div>背番号: <input type="number" value="<%= number %>" id="number" ></div>
<div>趣味: <input type="hobby" value="<%= hobby %>" id="hobby" ></div>
<div>今季の意気込み: <input type="zeal" value="<%= zeal %>" id="zeal" ></div>
</div>
<input type="button" value="保存" id="editBtn">
<input type="button" value="削除" id="deleteBtn">
</script>
<!-- モデル -->
<script src="js/MemberModel.js"></script>
<!-- コレクション -->
<script src="js/TeamCollection.js"></script>
<!-- チーム紹介ビュー -->
<script src="js/TeamAboutView.js"></script>
<!-- メンバー詳細ビュー -->
<script src="js/MemberDetailView.js"></script>
<!-- メンバー詳細 編集ビュー -->
<script src="js/MemberDetailEditView.js"></script>
<script>
<!-- DOM読み込み完了後に実行 -->
$(function() {
// ビューを生成し、処理を開始する。
new app.TeamAboutView();
});
</script>
</body>
</html>
メンバー詳細(編集用)のテンプレートとそのjavascriptファイルの読み込み追加。
ここは特に問題ないですね。
MemberModel.js
モデル。保存や削除時のリクエストの送信先のURLプロパティを追加。
データ取得時はコレクションのfetchメソッドを使ったけど(複数レコードの取得)、保存や削除はまとめてできない(コレクションにメソッドがない)のでモデルのメソッドを使います。
var app = app || {};
app.MemberModel = Backbone.Model.extend ({
url : '/xxxxx/xxxx',
defaults : {
position : '', // ポジション
name : '', // 名前
birthday : '', // 誕生日
},
});
続いて、チーム紹介用のjavascript。
TeamAboutView.js
var app = app || {};
app.TeamAboutView = Backbone.View.extend ({
el : '#about',
aboutTemplate : _.template($('#about-template').html()),
collection : '',
events : {
'click .detail' : 'dispDetail',
'click .edit' : 'editDetail',
},
initialize : function() {
this.collection = new app.TeamCollection();
// データを取得する。
this.collection.fetch({reset: true});
// データ取得後に、画面を描画する。
this.listenTo(this.collection, 'reset' , this.render);
},
render : function() {
var that = this;
var i = 0;
// コレクションに入っているデータ件数分、メンバーを表示する。
this.collection.each(function(model){
model.set('index', i);
that.$el.append(that.aboutTemplate(model.toJSON()));
i++;
});
},
dispDetail : function (event) {
// indexを取得する。
var index = $(event.target).attr('id');
// modelを取得する。
var memberModel = this.collection.models[index];
// メンバー詳細を表示する。
var options = {
model : memberModel
};
new app.MemberDetailView(options);
},
editDetail : function (event) {
// indexを取得する。
var index = $(event.target).attr('id');
// modelを取得する。
var memberModel = this.collection.models[index];
// メンバー詳細(編集)を表示する。
var options = {
model : memberModel
};
new app.MemberDetailEditView(options);
},
});
編集ボタン押下した際のイベントをeventsプロパティに設定し、
'click .edit' : 'editDetail',
編集レイアウトを描画するメソッドeditDetailを追加。
これも前回と同じなので、問題ないですね。
次が新しい要素たくさんの編集レイアウトのjavascript。
MemberDetailEditView.js
var app = app || {};
app.MemberDetailEditView = Backbone.View.extend ({
el : '#memberDetail',
memberTemplate : _.template($('#edit-member-detail-template').html()),
events : {
'click #editBtn' : 'edit',
'click #deleteBtn' : 'delete',
},
model : '',
initialize : function() {
// 前に描画したメンバー詳細を削除する。
this.$el.empty();
// 画面を描画する。
this.render();
},
render : function() {
// パラメータで渡されたmodelで画面を描画する。
this.$el.append(this.memberTemplate(this.model.toJSON()));
},
edit : function() {
var name = this.$el.find('#name').val();
var birthday = this.$el.find('#birthday').val();
var position = this.$el.find('#position').val();
var number = this.$el.find('#number').val();
var hobby = this.$el.find('#hobby').val();
var zeal = this.$el.find('#zeal').val();
// 入力内容でモデルを変更する。
this.model.set('name', name);
this.model.set('birthday', birthday);
this.model.set('position', position);
this.model.set('number', number);
this.model.set('hobby', hobby);
this.model.set('zeal', zeal);
this.model.save(null, {
success : function(){console.log("success!!")},
});
},
delete : function() {
this.model.destroy();
},
});
前回の復習もかねて、
編集用のレイアウトの表示位置となる
el : '#memberDetail',
描画の際に使用するテンプレート
memberTemplate : _.template($('#edit-member-detail-template').html()),
保存、削除ボタン押下時のイベント
events : { 'click #editBtn' : 'edit', 'click #deleteBtn' : 'delete', },
初期化のinitializeメソッドと描画のrenderメソッド。
ここからがいよいよ新しいものです!
まずeditメソッド。
保存ボタン押下時の処理をします。
やってることは簡単で、入力テキストボックスの値を取得して、それをモデルに詰めなおして、サーバにリクエストを送信してます。
this.$el.findでこのレイアウト内の要素を探します。
var name = this.$el.find('#name').val();
だと
id属性が「name」の要素を探します。
モデルのsetメソッドで値をモデルに設定。
this.model.set('name', name);
そして最後に詰めなおしたモデルのデータでリクエストをサーバに送ってます。
this.model.save(null, {
success : function(){console.log("success!!")},
});
第一引数が送信する値。nullだとモデルのプロパティがリクエストデータとして送られます。
ここに値があれば、モデルのプロパティと第一引数の値をマージしたものが送られます。
例えば、下記のようにするとnameはマージ太朗(第一引数が優先)、そしてnick_nameも追加されたデータが送られる。
var data = {
name : 'マージ 太朗',
nick_name : 'まーじん',
};
this.model.save(data, {
success : function(){console.log("success!!")},
});
リクエストがちゃんと送られてるかをクロームのF12押して確認すると、
ちゃんと送れとります!
今回は更新データなので、リクエストのメソッドは「PUT」になりやす。
新規の場合は、「post」です。
新規かどうかの判断はidプロパティがあるかどーかです。
モデルの全データを送ってますが、変更があったものだけとかサーバに送るデータを選択したい事もありますよねー
その場合はこう。
this.model.save(data, {
success : function(){console.log("success!!")},
patch : true
});
プロパティpatch:trueと書きます。
この通りです。
第一引数の値のみが送信されて、リクエストのメソッドは「patch」となります。
最後に削除。
モデルのdestroyメソッドを使います。
delete : function() {
this.model.destroy();
},
これでdeleteメソッドのリクエストを発生させます!
サーバサイドは書かないけど、それぞれのリクエストに応じてputだと更新、deleteだと削除するようなロジックを書けばOK!
少し長くなったけど、第4回終了。
あっ、忘れてたけど「TeamAboutView.js」でfetchのところと、監視するイベント変えとります。
前は
// データを取得する。
this.collection.fetch();
// データ取得後に、画面を描画する。
this.listenTo(this.collection, 'sync' , this.render);
だったけど、
// データを取得する。
this.collection.fetch({reset: true});
// データ取得後に、画面を描画する。
this.listenTo(this.collection, 'reset' , this.render);
前までのだと、syncイベントを監視してるので、modelのsaveやdestroyでもthis.renderメソッドが動いてしまう。
syncなので、サーバと正常に処理ができると動く。
今回は特にそのタイミングで描画する必要ないので、fetchの場合のみ動くように変更しました。
fetchのパラメータに{reset:true}を渡すと、fetchが完了するとresetイベントを発動してくれる。
ではでは。
プログラムはこちら