backboneの基礎の基礎 第5回[イベント通知]

今回はイベントの通知を。
backboneは1画面を1レイアウト(1ファイルのjs)で作成する事はほぼなく、複数レイアウトで作成すると思います。
そーすると、別のレイアウト(例えば子レイアウトから親レイアウト)へ処理の完了を教えたりとか、パラメータを渡したりとか、そういう場面がいろいろとあります。
その時に使うのがイベント通知です。

簡単に言うと、自作イベントを任意のタイミングで発生させます！！

今回は編集ボタン押下時に表示される名前を変更すると、親レイアウトにイベント通知し、親レイアウトでアラートを表示するサンプルを作ります。編集ボタン押下時に表示されるレイアウトが子レイアウトとなりますね。
この仕様に別に意味はないので。。。あくまでも実装の理解をする為に、こんなサンプルを実装してみますー。

![backbone_5.png](https://qiita-image-store.s3.amazonaws.com/0/79214/f3707299-afe9-48b7-c984-7ac682a95619.png)

前回から変更があるファイルは**MemberDetailEditView.js**と**TeamAboutView.js**です。
メンバー詳細編集View(MemberDetailEditView.js、子レイアウト)は名称が変更されたら、イベントを発生するよう修正。
チーム紹介View(TeamAboutView.js、親レイアウト)は子レイアウトのイベントを監視して、イベントが発生するとアラートを表示するよう修正。

では、まずメンバー詳細編集Viewから。
## MemberDetailEditView.js ##
```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',
		'change #name' : 'changeName',
	},
	
	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();
	},
	
	changeName : function(event) {
		// 入力されている名称をパラメータに、イベントを発生させる。
		this.trigger('changeNameDa', $(event.target).val());
	},
	
	empty : function () {
		this.$el.empty();
	}
});

```

eventsプロパティに名称変更イベントを追加。
`　'change #name' : 'changeName',　`

今回の注目①！！

```js	
changeName : function(event) {
	// 入力されている名称をパラメータに、イベントを発生させる。
	this.trigger('changeNameDa', $(event.target).val());
},
```

triggerでイベントを発生させます！
第二引数は変更された名称を渡しています。

## TeamAboutView.js ##

続いて、親レイアウト側。

```js

var app = app || {};

app.TeamAboutView = Backbone.View.extend ({
	el : '#about',
	
	aboutTemplate : _.template($('#about-template').html()),
	
	collection : '',
	
	editView : null,
	
	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) {
		// 既に編集ビューが表示されている場合は、空にして(名称変更監視イベントも解除)から再作成する。
		if (this.editView != null) {
			this.stopListening(this.editView);
			this.editView.empty();
		}
	
		// indexを取得する。
		var index = $(event.target).attr('id');
	
		// modelを取得する。
		var memberModel = this.collection.models[index];
		
		// メンバー詳細(編集)を表示する。
		var options = {
			model : memberModel
		};
		this.editView = new app.MemberDetailEditView(options);

		// 子ビュー(編集ビュー)からの名称変更のイベントを監視する。
		this.listenTo(this.editView, 'changeNameDa', this.dispName);
	},
	
	dispName : function (name) {
		// アラートをあげる。
		alert("子ビューから渡された：" + name);
	},
});

```

今回の注目②！！
ここが子レイアウトからのイベントを受け取っているところ。
イベントを監視する**listenTo**を使います。この関数はやりましたね。
editViewのchangeNameDaイベントが発生したらdispName関数を実行しろ！という事ですね。

```js
// 子ビュー(編集ビュー)からの名称変更のイベントを監視する。
this.listenTo(this.editView, 'changeNameDa', this.dispName);
```

やりたい事はこれで実現できるのですが、前回よりeditDetail関数がややこしくなってますね。
これは編集viewが削除された場合に、イベントの監視をストップしています。
stopListeningで停止できます。引数を指定するとそのイベント、指定しないと全イベントが停止されやす。
これをしないと、どんどん監視してしまい、一回のtriggerイベントで複数回dispName関数が実行されてしまいます。

ボタンを押すたびにどんどん実行される回数が増える！！！！なんて時は、イベント監視を停止し忘れているかもです。

今回のサンプルだと、編集viewを表示しているときに再度編集ボタンが押下されたら、一度ビューを削除し、イベントの監視も停止させて、新たにviewを作成してます。

ではっ。
[ソースはこちら](https://github.com/naka4A6/backbone_5)