Главная

Webmacter V.2 Всё для вебмастера » Уроки по JS » Backbone.js 29 – Менеджер контактов. Редактирование и удаление контактов.

Backbone.js 29 – Менеджер контактов. Редактирование и удаление контактов.

Backbone.js 29 – Менеджер контактов. Редактирование и удаление контактов.


Сегодня мы закончим наш “Менеджер контактов”. Нам нужно написать действия редактирования и удаления контактов.




Всем привет! Начнем с верстки. Добавим соответствующий заголовок:
	<table id="allContactsTable">
		<thead>
			<tr>
				<td><strong>Имя</strong></td>
				<td><strong>Фамилия</strong></td>
				<td><strong>Email</strong></td>
				<td><strong>Описание</strong></td>
				<td><strong>Действия</strong></td>
			</tr>
		</thead>
	</table>

Добавим кнопку удаления контакта в шаблон:
<script id="contactTpl" type="text/template">	
	<td>{{first_name}}</td>
	<td>{{last_name}}</td>
	<td>{{email_address}}</td>
	<td>{{description}}</td>
	<td>
		<a href="#contacts/{{id}}" class="delete">Удалить</a>
	</td>
</script>

Теперь идем в наш вид одного контакта и добавляем событие, которое будет происходить после клика по этой кнопке. При клике мы уничтожаем модель и отправляем данные на сервер, а в инициализации вида вешаем событие “destroy” прослушивающее когда модель удаляется и запускающее метод unrender – удаляющее соответствующий вид и элемент привязанный к нему:
App.Views.Contact = Backbone.View.extend({
	initialize: function() {
		this.model.on('destroy', this.unrender, this);
	},


	tagName: 'tr',

	events: {
		'click a.delete' : 'deleteContact'
	},

	deleteContact: function() {
		this.model.destroy();
	},

	unrender: function() {
		this.remove(); // this.$el.remove()
	},

	template: App.template('contactTpl'),

	render: function() {
		this.$el.html( this.template( this.model.toJSON() ) );
		return this;
	}

});

Пишем серверный роут, обрабатывающий DELETE HTTP запрос автоматически отправляемый на сервер, при использовании метода destroy:
Route::delete('/contacts/(:num)', 'contacts@destroy');

С удалением мы покончили. Все работает. Теперь перейдем к редактированию. Добавим в шаблон соответствующую кнопку:
<script id="contactTpl" type="text/template">	
	<td>{{first_name}}</td>
	<td>{{last_name}}</td>
	<td>{{email_address}}</td>
	<td>{{description}}</td>
	<td>
		<a href="#contacts/{{id}}/edit" class="edit">Редактировать</a>
		<a href="#contacts/{{id}}" class="delete">Удалить</a>
	</td>
</script>

И обрабатываем это событие в виде. Пишем метод editContact:
App.Views.Contact = Backbone.View.extend({
	initialize: function() {
		this.model.on('destroy', this.unrender, this);
	},

	tagName: 'tr',

	events: {
		'click a.delete' : 'deleteContact',
		'click a.edit'   : 'editContact'
	},

	deleteContact: function() {
		this.model.destroy();
	},

	unrender: function() {
		this.remove(); // this.$el.remove()
	},

	editContact: function() {

	},

	template: App.template('contactTpl'),

	render: function() {
		this.$el.html( this.template( this.model.toJSON() ) );
		return this;
	}

});

Но, что нам нужно после того как этот метод срабатывает? Давайте напишем алгоритм:

-создаем новый экземпляр вида new EditContactView
-привязываем модель
-вставляем форму в DOM
Начнем с того, что напишем новый вид Edit Contact View:
/*
|---------------------------------------------------
| Edit Contact View
|---------------------------------------------------
*/
App.Views.EditContact = Backbone.View.extend({


});

Так же нам необходим новый шаблон, карточки редактирования контакта:
<script id="editContactTpl" type="text/template">
<h2>Редактирование контакта: {{last_name}} {{first_name}}</h2>
<form  id="edit-contact-form">
	<div>
		<label for="edit_first_name">Имя:</label>
		<input type="text" id="edit_first_name" name="edit_first_name" value="{{first_name}}">
	</div>
	<div>
		<label for="edit_last_name">Фамилия:</label>
		<input type="text" id="edit_last_name" name="edit_last_name" value="{{last_name}}"> 
	</div>
	<div>
		<label for="edit_email_address">Email:</label>
		<input type="text" id="edit_email_address" name="edit_email_address" value="{{email_address}}">
	</div>
	<div>
		<label for="edit_description">Описание:</label>
		<textarea id="edit_description" name="edit_description">{{description}}</textarea>
	</div>
	<div>
		<input type="submit" value="Сохранить изменения.">
	</div>
</form>

</script>

Вставляем его в вид Laravel:
@include('handlebars-templates/editContactTpl');

Добавляем в вид шаблон , а так же методы render и init:
App.Views.EditContact = Backbone.View.extend({
	template: App.template('editContactTpl'),

	initialize: function() {
		this.render();	
	},

	render: function() {
		var html = this.template( this.model.toJSON() );

		this.$el.html(html);
		return this;
	}

});

Пока что, оставим вид редактирования контакта и вернемся в single contact view. пишем метод editContact:
	editContact: function() {
		var editContactView = new App.Views.EditContact({ model: this.model });
		$(document.body).append(editContactView.el);
	}

Попробуем в браузере. Супер! Вид рендерит форму редактирования и вставляет в DOM.
Но у нас есть некоторые проблемы. Первая, то что при редактировании любого другого контакта,
он тоже генерится и просто вставляется после первого. А нам нужно, чтобы каждая новая карточка, просто переписывала старую.

Чтобы это осуществить, первым делом, при клике на кнопку редактирования я буду вызывать свое событие contact:edit и передавать в него соответствующую модель вида привязанного к элементу
, в котором находится эта кнопка.
Так что я перепишу метод editContact следующим образом:
	editContact: function() {
		vent.trigger('contact:edit', this.model);
	}

Логику создания нового вида редактирования контакта и вставку в DOM-дерево срендеренной карточки, вынесем в главный вид App. Там же и будет висеть прослушка события contact:edit:
App.Views.App = Backbone.View.extend({
	initialize: function() {
		vent.on('contact:edit', this.editContact, this);
		var addContact = new App.Views.AddContact({ collection: App.contacts });

		var allContacts  = new App.Views.Contacts({ collection: App.contacts }).render();
		$('#allContactsTable').append(allContacts.el);
	},

	editContact: function(contact) {
		var editContactView = new App.Views.EditContact({ model: contact });
		$(document.body).append(editContactView.el);
	}
});

Cверстаем див editContact, в который каждый раз будет вставляться наша форма редактирования:
<div class="editContact">
		
	</div>

Теперь меняю метод editContact главного вида и вставляю срендеренную форму в наш див editContact:
	editContact: function(contact) {
		var editContactView = new App.Views.EditContact({ model: contact });
		$('.editContact').html(editContactView.el);
	}

Теперь все работает как надо! Давайте только добавим немного свободного пространства. Допишем всем нашим формам и таблице класс
module и немного перепишем стили:
.module  {margin-bottom: 2em;}		

Переходим к следующей проблеме, если мы изменим какой либо параметр в форме редактирования и нажмем “Сохранить изменения”, то…
ничего не изменится. Требуется написать соответствующий функционал. Перемещаемся в наш вид EditContact и дописываем событие, которое будет происходить после отправки формы редактирования. То есть при нажатии на кнопку “Сохранить изменения”.

Так что же нам нужно? Необходимо осуществить следующие действия:

– взять существующую модель.
– обновить ее атрибуты.
– и синхронизировать с сервером.
Все это нам позволит сделать всего один метод save. Смотрим на код:
App.Views.EditContact = Backbone.View.extend({
	template: App.template('editContactTpl'),

	initialize: function() {
		this.render();

		this.form = this.$('form');
		this.first_name = this.form.find('#edit_first_name');
		this.last_name = this.form.find('#edit_last_name');
		this.email_address = this.form.find('#edit_email_address');
		this.description = this.form.find('#edit_description');
	},

	events: {
		'submit form' : 'submit'
	},

	submit: function(e) {
		e.preventDefault();
		
		this.model.save({
			first_name: this.first_name.val(),
			last_name: this.last_name.val(),
			email_address: this.email_address.val(),
			description: this.description.val()
		});

	},

	render: function() {
		var html = this.template( this.model.toJSON() );

		this.$el.html(html);
		return this;
	}

});

Так же сразу дописываем серверный роут, вызывающий соответствующий экшн в контроллере:
Route::put('/contacts/(:num)', 'contacts@update');

Cмотрим в базу данных, контакт поменялся! Но на странице ничего не изменилось. Все потому,
что нам нужно поставить еще одно событие change в виде единичного контакта.
Событие будет срабатывать при изменении модели и вызывать метод render, то есть перерисовывать соответствующую строку в таблице:
App.Views.Contact = Backbone.View.extend({
	initialize: function() {
		this.model.on('destroy', this.unrender, this);
		this.model.on('change', this.render, this);
	},

        ...
});

Теперь все работает, так как надо! Нам осталось только удалять нашу форму каждый раз, при успешном изменении контакта. Все, что нам для этого нужно, это добавить this.remove(), после того как мы изменяем модель и отправляем на сервер в виде EditContact:
	submit: function(e) {
		e.preventDefault();
		// взять существующую модель
		// обновить ее атрибуты
		// синхронизировать с сервером
		
		this.model.save({
			first_name: this.first_name.val(),
			last_name: this.last_name.val(),
			email_address: this.email_address.val(),
			description: this.description.val()
		});


		this.remove();

	}

Ну и последнее. Что если мы передумаем редактировать контакт? должна быть какая то кнопка отмены.
Давайте ее добавим в шаблон editContactTpl:
	<script id="editContactTpl" type="text/template">
                ...

		<div>
			<input type="submit" value="Сохранить изменения.">
			<button type="button" class="cancel">Отмена</button>
		</div>
	</form>

</script>

Вешаем на нее событие в виде редактирования контакта:
App.Views.EditContact = Backbone.View.extend({
       ...

	events: {
		'submit #edit-contact-form' : 'submit',
		'click button.cancel' : 'cancel'
	},

	cancel: function() {
		this.remove();
	},

        ...

Ну вот и все. Мы написали весь базовый функционал нашего приложения. Оно может добавлять, удалять и редактировать наши контакты. Настоящий менеджер контактов! Всем спасибо, за просмотр!

Источник:loftblog
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо зайти на сайт под своим именем.

Информация

Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.