Użycie agregatora zdarzeń do załadowania widoku z innym modelem w js sieci szkieletowej
Jestem nowym użytkownikiem backbone.js, który rozpoczął się od kręgosłupa tydzień temu. Musiałem zrobić demo. Główną ideą jest to, kiedy strona jest ładowana, muszę pokazać kursy, a domyślnie lista studentów dla pierwszego kursu na liście. Oto kod, który wyświetla listę kursów, która się znajdujecourse.js plik
//Model
var Course = Backbone.Model.extend({
urlRoot: '/api/courses/',
idAttribute: 'Id',
defaults:{
Id: null,
Name: ""
},
validate: function (attr) {
if (!attr.Name)
return "Name is required";
}
});
var Courses = Backbone.Collection.extend({
model: Course,
url: '/api/courses'
});
// Widoki
var CourseList = Backbone.View.extend({
tagName: 'ul',
initialize: function () {
this.collection.on('reset', this.renderAll, this);
this.collection.on('add', this.render, this);
this.collection.fetch();
_.bindAll(this, 'renderAll', 'render');
return this;
},
renderAll: function () {
this.collection.each(this.render);
$('#spnStdntCourseName').text('Students Enrolled in ' + this.collection.at(0).get("Name"));
},
render: function (model) {
var item = new CourseItem({ model: model });
this.$el.append(item.el);
},
events: {
"click #btnAddCourse": "createNewCourse",
"keypress #txtNewCourse": "createOnEnter"
},
createOnEnter: function (e) {
if (e.keyCode == 13) {
this.createNewCourse();
}
},
createNewCourse: function () {
this.collection.create({ Name: this.$el.find('#txtNewCourse').val() });
this.$el.find('#txtNewCourse').val('');
}
});
var CourseItem = Backbone.View.extend({
tagName: 'li',
className: 'courseli',
events: {
'click .remove': 'deleteItem',
'click .edit': 'showEdit',
'click': 'courseClicked'
},
initialize: function () {
this.template = _.template($('#course').html()),
this.model.on('change', this.render, this);
this.render();
},
render: function () {
var html = this.template(this.model.toJSON());
this.$el.html('').html(html);
},
courseClicked: function () {
$('#spnStdntCourseName').text('Students Enrolled in ' + this.model.get("Name"));
Vent.trigger('studentDetails',"how to load student list from here based on courseID...?");
},
showEdit: function (event) {
event.preventDefault();
Vent.trigger('edit', this.model);
},
deleteItem: function () {
this.model.destroy();
this.remove();
}
});
var CourseEdit = Backbone.View.extend({
el: '#courseEdit',
events: {
'click #save': 'save',
'click #cancel': 'cancel'
},
initialize: function () {
_.bindAll(this, 'render', 'save');
Vent.on('edit', this.render);
this.template = _.template($('#courseEditTemplate').html())
},
render: function (model) {
var data, html;
this.model = model;
data = this.model.toJSON();
html = this.template(data);
this.$el.html(html)
.show()
.find('#name')
.focus();
this.model.on('error', this.showErrors, this);
},
save: function (event) {
var self = this;
this.model.save({
'Name': this.$el.find('#name').val()
}, {
success: function () {
alert('Saved!');
if (!window.courses.any(function (course) {
return course.get('Id') === self.model.get('Id');
})) {
window.courses.add(self.model);
}
self.$el.hide();
}
});
},
cancel: function () {
this.$el.hide();
},
showErrors: function (model, error) {
var errors = '';
if (typeof error === 'object') {
errors = JSON.parse(error.responseText).join('<br/>');
alert(errors);
}
else {
alert(error);
}
}
});
var Vent = _.extend({ }, Backbone.Events);
window.courses = new Courses();
$(function () {
var edit = new CourseEdit(),
list = new CourseList({
collection: window.courses,
el: '#coursesList'
});
});
Proszę spojrzeć na„courseClicked” funkcjonować wewnątrzPrzedmiot Zobacz, to ma załadować listę uczniów, gdy element kursu zostanie kliknięty.
Teraz mam mojeStudent model i widoki w students.js jak poniżej
var Student = Backbone.Model.extend({
urlRoot: '/api/students/',
idAttribute: 'Id',
defaults: {
Id: null
},
validate: function (attr) {
if (!attr.Name)
return "Name is required";
}
});
var Students = Backbone.Collection.extend({
model: Student,
url: '/api/students'
});
// Widoki
var StudentList = Backbone.View.extend({
tagName: 'ul',
initialize: function () {
this.collection.on('reset', this.renderAll, this);
this.collection.on('add', this.render, this);
this.collection.fetch({ data: $.param({ courseId: 11 }) });
_.bindAll(this, 'renderAll', 'render');
return this;
Vent.on('studentDetails', this.render);
},
renderAll: function () {
this.collection.each(this.render);
},
render: function (model) {
var item = new StudentItem({ model: model });
this.$el.append(item.el);
},
events: {
"click #btnAddStudent": "createNewStudent",
"keypress #txtNewStudent": "createOnEnter"
},
createOnEnter: function (e) {
if (e.keyCode == 13) {
this.createNewStudent();
}
},
createNewStudent: function () {
this.collection.create({ Name: this.$el.find('#txtNewStudent').val() });
this.$el.find('#txtNewStudent').val('');
}
});
var StudentItem = Backbone.View.extend({
tagName: 'li',
className: 'studentli',
events: {
'click .remove': 'deleteItem',
'click': 'studentClicked'
},
initialize: function () {
this.template = _.template($('#student').html()),
this.model.on('change', this.render, this);
this.render();
},
render: function () {
var html = this.template(this.model.toJSON());
this.$el.html('').html(html);
},
studentClicked: function () {
var Id = this.model.get("Id");
},
deleteItem: function () {
this.model.destroy();
this.remove();
}
});
window.students = new Students();
$(function () {
var studentDetails = new StudentList({
collection: window.students,
el: '#studentsList'
});
});
więc wewnątrz dokumentu. Już mamstudentDetails zmienna, która ładuje listę studentów.Tutaj jest mój problem, ponieważ teraz załadowałem listę studentów na stronie ładowania, przekazując jakiś twardy kod parametru wewnątrz fetch, jak poniżej
this.collection.fetch({ data: $.param({ courseId: 11 }) });
ale muszę pokazać, że lista studentów na pierwszym kursie w widoku courselist, gdy strona jest załadowana, a na późniejszych etapach, lista studentów dla każdego elementu kursu została kliknięta. W tym celu, jeśli pamiętasz w „courseClicked” działa w widoku „CourseItem” w course.js, użyłem
Vent.trigger('studentDetails',"how to load student list from here based on courseID...?");
studentDetails to var, który zainicjowałem w students.js (w powyższym kodzie) w ten sposób
window.students = new Students();
$(function () {
var studentDetails = new StudentList({
collection: window.students,
el: '#studentsList'
});
});
Więc kiedy wyzwalam szczegóły ucznia, zdecydowanie potrzebuję modelu ucznia wewnątrz mojej funkcji courseClicked, która nie jest dostępna w tym kontekście. Wierzę, że zrozumieliście mój problem z powyższego wyjaśnienia. Jak więc to naprawić ...? Czy podejście, które podążyłem, jest błędne ..? Każda dobra alternatywa, potrzebujesz sugestii. Mam nadzieję, że nie ma zbyt dużego hałasu w pytaniu.
EDYTOWAĆ
var CourseList = Backbone.View.extend({
tagName: 'ul',
initialize: function () {
this.students = new Students();
var studentList = new StudentList({
collection: this.students,
el: '#studentsList'
});
this.collection.on('reset', this.renderAll, this);
this.collection.on('add', this.render, this);
this.collection.fetch();
_.bindAll(this, 'renderAll', 'render');
return this;
},
renderAll: function () {
this.collection.each(this.render);
$('#spnStdntCourseName').text('Students Enrolled in ' + this.collection.at(0).get("Name"));
this.students.fetch({ data: $.param({ courseId: this.collection.at(0).get("Id") }) });
},
render: function (model) {
this.$el.html("");
var item = new CourseItem({ model: model, students: this.students});
this.$el.append(item.el);
}
})
Wprowadziłem następujące zmiany
1. uczniowie w kolekcji do this.students (wewnątrz inicjalizacji widoku „CourseList”) w poniższym kodzie
initialize: function () {
this.students = new Students();
var studentList = new StudentList({
collection: this.students,
el: '#studentsList'
});
2. Pobrałem uczniów wewnątrz funkcji renderAll zamiast funkcji renderowania, ponieważ dla każdego pobranego przedmiotu uczeń jest również pobierany. Mam na myśli, że jeśli jest 6 kursów, widzę uczniów na kurs 0 w kolekcji 6 razy
renderAll: function () {
this.collection.each(this.render);
$('#spnStdntCourseName').text('Students Enrolled in ' + this.collection.at(0).get("Name"));
this.students.fetch({ data: $.param({ courseId: this.collection.at(0).get("Id") }) });
SubQuestion
W „CourseList” inicjalizujemy funkcję jak poniżej
initialize: function () {
this.students = new Students();
var studentList = new StudentList({
collection: this.students,
el: '#studentsList'
});
Lista uczniów jest jak poniżej
<div id="studentsList" class="box">
<div class="box-head">
<h2 class="left">
<span id="spnStdntCourseName"></span>
</h2>
</div>
<div>
<input type="text" id="txtNewStudent" placeholder="Add New Student" />
<button id = "btnAddStudent">+ Add</button>
</div>
</div>
ilekroć to robię. $ el.html ("") wewnątrz funkcji renderowaniaStudentList zobacz jak poniżej
var StudentList = Backbone.View.extend({
tagName: 'ul',
render: function (model) {
this.$el.html("");
var item = new StudentItem({ model: model });
this.$el.append(item.el);
},
......
Zgubiłem elementy przycisków i pola tekstowego w elemencie studentList el, a ul nie jest wyświetlana, gdy przeglądam kod źródłowy w mojej przeglądarce, o którym wspomniałem jako tagName, ale widzę li, który jest tagName dla widoku studentItem. robić źle
Dziękujemy za cierpliwość