Backbone.js инициализирует представления для сбора данных, где элементы dom уже отображаются на сервере
Я работаю над SPA backbone.js для отображения контактов пользователей для пользователей нашего сайта.
Приложение My Backbone состоит из трех представлений: AppView - просмотр коллекции элементов списка контактов createContactView - просмотр формы для добавления новых контактов ContactView - просмотр каждого элемента контакта
Коллекция: ContactList И модель: Контакт
Разметка состоит из упорядоченного списка с id="address-list", содержащего элементы списка
Я предоставил загруженный массив Javascript объектов JSON, которые представляют каждый контакт, представленный в элементе списка.
В своей первой работе над этим проектом я соответствовал примеру списка задач в книге "Разработка приложений Backbone.js", написанной Адди Османи. В примере использовались загруженные данные для создания TodoViews при создании экземпляра приложения, а затем визуализация представления и добавление его в представление TodoList примера. Затем основное приложение прослушивает коллекцию Todos, а когда срабатывает событие add, создаст другое представление Todo и добавит его в список Todo.
Поэтому я изначально следовал этому примеру для своей адресной книги SPA, и все работало отлично, каждый ContactView отображался в dom и добавлялся в список адресов, а все события были прикреплены к соответствующим кнопкам для обновления и удаления контакта.
Backbone рекомендует для эффективности создать разметку для начального просмотра списка контактов на стороне сервера.
Поэтому я реорганизовал свой код на стороне сервера, чтобы отобразить начальные элементы списка контактов в упорядоченном списке списка адресов.
Поэтому на стороне клиента я все еще создаю коллекцию из загруженной контактной информации, создаю представление, но не вызываю метод render, поскольку он уже существует в dom. Я предоставил el в загрузочных данных, думая, что представление будет прикрепляться к правильному элементу dom, чтобы все мои события соединялись с соответствующими элементами для обновления и удаления контакта, но этого никогда не происходит.
Поэтому мой вопрос заключается в том, как мне создать представление из существующих элементов dom с загруженными данными, когда мне не нужно отображать его, потому что оно уже существует в Dom?
Ниже приведен код, который я использую, а затем пример загруженных данных. Спасибо за любую помощь, которую вы можете предоставить.
Javascript:
// The main application view controller.
var AppView = Backbone.View.extend({
// el binds the AppView to the existing ordered
// list of contacts presented on the client.
el: $("#address-list"),
addressbookRouter: '',
createContactView: '',
contacts: '',
contactViews: [],
sort: 'lastName',
// Initialize the AppView application.
initialize: function(contactsData) {
console.debug('AppView.initialize');
// initialize the ContactsCollection
// - contactsData is a bootstrapped json object
// of contacts created on the server side.
this.contacts = new ContactsCollection(contactsData);
this.listenTo(this.contacts, 'add', this.render, this);
// initialize a ContactView for each contact in the collection.
this.createContactViewsForCollection(this.contacts);
// initialize the AppRouter for
// sorting of contacts on the client.
this.addressbookRouter = new AppRouter();
this.listenTo(this.addressbookRouter, 'route', this.render, this);
// initialize the CreateContactView
// - used for adding new contacts to the
// contacts collection and updating wombat.
this.createContactView = new CreateContactView(this.contacts);
},
// Add a ContactView and render.
// - contact is a JSON object
addContactView: function(contact) {
console.debug('AppView.addContactView');
// - create contact view
// - render the view
var view = new ContactView(
{model: contact
});
this.$el.append( view.render().el );
},
// Instantiate a view for each contact in the collection.
createContactViewsForCollection: function(contacts) {
console.debug('AppView.createViewsForCollection');
this.contacts.each(
function( contact ) {
this.contactViews.push(
new ContactView({
model: contact
})
);
}, this
);
},
// Render contact views for the ContactsCollection
// - render will be called in the following cases
// 1. A column header has been clicked, and a
// sort order based on that header is passed in
// and set to this.sort.
// 2. A new contact has been added to the collection
// resulting in a Backbone Model being passed to the
// function, with this.sort as the sort order.
render: function(sort) {
console.debug('AppView.render');
// determine the sort order
// for the collection.
// - when render is called after adding a new
// contact to the collection, a Backbone Model
// is passed to render. In that case use the default sort.
console.debug('sort:', sort);
if (sort instanceof Backbone.Model) {
sort = this.sort;
} else {
this.sort = sort;
}
// sort the collection
this.contacts.sortByField(sort);
// reset the view
this.$el.empty();
// render the sorted contacts
this.contacts.each(
function( item ) {
this.addContactView( item );
}, this
);
}
});
// Contacts View item
var ContactView = Backbone.View.extend({
tagName: 'li',
className: 'hideContact',
template: _.template($('#contact_view').html() ),
events: {
'click #editContact' : 'toggleVisible',
'click #delete' : 'deleteContact'
},
initialize: function() {
console.debug('ContactView.initialize');
},
render: function() {
console.debug('ContactView.render');
// this.el is what we defined in tagName.
// use $el to get access to jQuery html() function
this.$el.html( this.template( this.model.toJSON() ));
return this;
},
deleteContact: function() {
console.debug('ContactView.deleteContact');
// Delete model
this.model.destroy();
// Delete view
this.remove();
},
toggleVisible: function( e ) {
console.debug('ContactView.toggleVisible');
e.preventDefault();
this.$el.toggleClass( 'hideContact' );
}
});
// CreateContacts View
var CreateContactView = Backbone.View.extend({
el: $("#addContact"),
contacts: '',
events: {
'click #add' : 'addContact'
},
initialize: function(contactsCollection) {
console.debug('CreateContactView.initialize');
// set contacts collection
this.contacts = contactsCollection;
},
// Add a new contact to the contacts collection from form data.
addContact: function( e ) {
console.debug('CreateContactView.addContact');
e.preventDefault();
var formData = _.object(_.map($('#addContact').serializeArray(), _.values));
// Collection will call the REST endpoint to store a new contact.
this.contacts.create(formData);
this.resetView();
},
resetView: function() {
console.debug('CreateContactView.resetView');
// reset the addContact form
hideaddcontact('add-contact-list');
showaddcontact('add-contact-mobile-container');
document.getElementById("addContact").reset();
}
});
// Contact Collection
var ContactList = Backbone.Collection.extend({
// reference to this collections model.
model: Contact,
url: '/addressbook',
sort_key: 'lastName',
comparator: function (contact) {
return contact.get(this.sort_key);
},
sortByField: function(fieldName) {
this.sort_key = fieldName;
this.sort();
},
initialize: function() {
console.log('ContactList.initialize');
}
});
// Contact Model
var Contact = Backbone.Model.extend({
// default contact information
// - el : id of the contact list item
// - email : email
// - firstName : first Name
// - lastName : last Name
// - cid : contact id
// - eid : event id
// - emailid : email id
// - month : birthday month
// - day : birthday day
defaults: {
el: '',
email: '',
firstName: '',
lastName: '',
cid: '',
eid: '',
emailid: '',
month: '',
day: ''
},
initialize: function( data ) {
console.log('Contact.initialize');
this.set('id', data.cid);
}
});
Example of bootstrapped data:
var contacts = [
{
email : "jbanks@volcano.com",
firstName : "Joseph",
lastName : "Banks",
cid : "408416",
el : "#408416",
eid : "318665",
emailid : "380177",
month : "3",
day : "17"
}
,
{
email : "jbean@whisky.com",
firstName : "Jim",
lastName : "Bean",
cid : "408435",
el : "#408435",
eid : "318696",
emailid : "380196",
month : "5",
day : "7"
}
,
{
email : "ben@skywalkerranch.com",
firstName : "Uncle",
lastName : "Ben",
cid : "406536",
el : "#406536",
eid : "317817",
emailid : "378239",
month : "1",
day : "14"
}
,
{
email : "beru@skywalkerranch.com",
firstName : "Aunt",
lastName : "Beru",
cid : "406537",
el : "#406537",
eid : "",
emailid : "378240",
month : "None",
day : "None"
}];
HTML:
<div class="container">
<form id="addContact" action="#" name="addContact" class="frmaddrbook">
<input type="hidden" value="" name="numrecs">
<input type="hidden" name="mode" value="">
<fieldset id="fs-addab">
<ol class="sort-list">
<li class="fname">First name</li>
<li class="lname">Last name</li>
<li class="email">E-mail address</li>
<li class="bday">Birthday</li>
</ol>
<ol id="add-contact-list">
<li>
<span>
<label for="fldFname">First name:</label>
<input id="fldFname" name="firstName" class="text fname" type="text" maxlength="200" value="">
</span>
<span>
<label for="fldLname">Last name:</label>
<input id="fldLname" name="lastName" class="text lname" type="text" maxlength="200" value="">
</span>
<span>
<label for="fldEmail">E-mail address:</label>
<input id="fldEmail" name="email" class="text email" type="text" maxlength="256" value="">
</span>
<span>
<label for="month">Month:</label>
<select class="selMonth" name="month" id="month">
<option value="" selected="selected"></option>
<option value="01">January</option>
<option value="02">February</option>
<option value="03">March</option>
<option value="04">April</option>
<option value="05">May</option>
<option value="06">June</option>
<option value="07">July</option>
<option value="08">August</option>
<option value="09">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
</span>
<span>
<label for="day">Day:</label>
<select class="selDay" name="day" id="day">
<option value="" selected="selected"></option>
<option value="01"> 1</option>
<option value="02"> 2</option>
<option value="03"> 3</option>
<option value="04"> 4</option>
<option value="05"> 5</option>
<option value="06"> 6</option>
<option value="07"> 7</option>
<option value="08"> 8</option>
<option value="09"> 9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</span>
<span>
<input id="add" name="btnAddressBook" type="button" value="Add" class="mbutton">
</span>
</li>
</ol>
</fieldset>
</form>
<p class="intro"><strong class="title">Update an Entry</strong> Please click any of the column headings to sort the list in order of that column.</p>
<ol class="sort-list">
<li class="fname"><a href="#firstName">First name</a></li>
<li class="lname"><a href="#lastName">Last name</a></li>
<li class="email"><a href="#email">E-mail address</a></li>
<li class="bday">Birthday</li>
</ol>
<form action="#" class="frmaddrbook" name="frmAddressbook0" id="frmABupdate0">
<fieldset class="fs-editab">
<ol id="address-list">
<li class="hideContact" id="408416">
<input type="hidden" value="380177" name="emailid">
<input type="hidden" value="408416" name="cid">
<input type="hidden" value="318665" name="eid">
<span>
<label for="fldFname0">First name</label>
<input type="text" value="Joseph" maxlength="200" class="text fname" name="firstName" id="fldFname0">
</span>
<span>
<label for="fldLname0">Last name</label>
<input type="text" value="Banks" maxlength="200" class="text lname" name="lastName" id="fldLname0">
</span>
<span>
<label for="fldEmail0">E-mail address</label>
<input type="text" value="jbanks@volcano.com" maxlength="256" class="text email" name="email" id="fldEmail0">
<button id="editContact"></button>
</span>
<span>
<label for="month">Month:</label>
<select name="month" class="selMonth">
<option value=""></option>
<option value="1">January</option>
<option value="2">February</option>
<option value="3" selected="">March</option>
<option value="4">April</option>
<option value="5">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
</span>
<span>
<label for="day">Day:</label>
<select name="day" class="selDay">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17" selected="">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</span>
<span>
<input type="button" value="Update" name="update" id="update" class="mbutton">
<input type="button" value="Delete" name="delete" id="delete" class="mbutton button-alt">
</span>
</li>
<li class="hideContact" id="408435">
<input type="hidden" value="380196" name="emailid">
<input type="hidden" value="408435" name="cid">
<input type="hidden" value="318696" name="eid">
<span>
<label for="fldFname0">First name</label>
<input type="text" value="Jim" maxlength="200" class="text fname" name="firstName" id="fldFname0">
</span>
<span>
<label for="fldLname0">Last name</label>
<input type="text" value="Bean" maxlength="200" class="text lname" name="lastName" id="fldLname0">
</span>
<span>
<label for="fldEmail0">E-mail address</label>
<input type="text" value="jbean@whisky.com" maxlength="256" class="text email" name="email" id="fldEmail0">
<button id="editContact"></button>
</span>
<span>
<label for="month">Month:</label>
<select name="month" class="selMonth">
<option value=""></option>
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
<option value="5" selected="">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
</span>
<span>
<label for="day">Day:</label>
<select name="day" class="selDay">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7" selected="">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</span>
<span>
<input type="button" value="Update" name="update" id="update" class="mbutton">
<input type="button" value="Delete" name="delete" id="delete" class="mbutton button-alt">
</span>
</li>
</ol>
</fieldset>
</form>
</div>
1 ответ
Я смог решить эту проблему, передавая el и id из модели при создании экземпляра моего ContactView.
// Instantiate a view for each contact in the collection.
createContactViewsForCollection: function(contacts) {
console.debug('AppView.createViewsForCollection');
this.contacts.each(
function(contact) {
var view = new ContactView({
model: contact,
el: contact.attributes.el,
id: contact.attributes.cid
});
this.contactViews.push(view);
}, this
);
},