7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

backboneの基礎の基礎 第4回[データの保存・削除]

Last updated at Posted at 2015-05-28

今回は、簡単な編集と削除機能を作ります。
こんな感じ

4_screen.png

編集ボタンを押すと下に編集する画面が表示されます。
4_screen2.png

前回からの追加内容をざっくりと書くとー
レイアウトに編集画面用のレイアウト追加
モデルに保存、削除時の送信先となる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押して確認すると、
4_request.png
ちゃんと送れとります!

今回は更新データなので、リクエストのメソッドは「PUT」になりやす。
新規の場合は、「post」です。
新規かどうかの判断はidプロパティがあるかどーかです。

モデルの全データを送ってますが、変更があったものだけとかサーバに送るデータを選択したい事もありますよねー
その場合はこう。

this.model.save(data, {
	success : function(){console.log("success!!")},
	patch : true
});

プロパティpatch:trueと書きます。
この通りです。
4_patch.png
第一引数の値のみが送信されて、リクエストのメソッドは「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イベントを発動してくれる。

ではでは。
プログラムはこちら

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?