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ść

questionAnswers(1)

yourAnswerToTheQuestion