Вопрос по backbone.js, asp.net-mvc-4 – Использование Event Aggregator для загрузки представления с другой моделью в магистрали js

1

Я новичок в backbone.js начал с позвоночника неделю назад. Я должен был сделать демо. Основная идея заключается в том, что когда страница загружена, мне нужно показать курсы, и по умолчанию список студентов для первого курса в списке. Вот код для отображения списка курсов, который находится вcourse.js файл

//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'
});   

//Views

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'
    });
});

Пожалуйста, посмотрите на'courseClicked' функция внутриCourseItem Представление: предполагается, что список студентов загружается при нажатии на элемент курса.

Теперь у меня есть мойStudent модель и представления в Students.js, как показано ниже

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'
});

//Views

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'
    });      
});

так внутри документа. уже у меня естьstudentDetails переменная, которая загружает список студентов. Вот моя проблема, поскольку на данный момент я загрузил список студентов при загрузке страницы, передав некоторый параметр жесткого кода в fetch, как показано ниже

 this.collection.fetch({ data: $.param({ courseId: 11 }) });

но что мне нужно показать, так это список студентов для первого курса в представлении курсоров при загрузке страницы, а на более поздних этапах - список студентов для каждого элемента курса. Для этой цели, если вы можете вспомнить в & Quot; courseClicked & Quot; функция внутри & quot; CourseItem & quot; посмотреть в course.js, я использовал

 Vent.trigger('studentDetails',"how to load student list from here based on courseID...?");

studentDetails - это переменная, которую я инициализировал в student.js (в приведенном выше коде) следующим образом

window.students = new Students();
$(function () {
var studentDetails = new StudentList({
    collection: window.students,
    el: '#studentsList'
});      
}); 

Поэтому, когда я запускаю studentDetails, мне определенно нужна модель студента внутри моей функции courseClicked, которая недоступна в этом контексте. Я полагаю, вы, ребята, поняли мою проблему из приведенного выше объяснения. Так как мне это исправить ...? Это неправильный подход? ..? Любая хорошая альтернатива, нужны предложения. Надеюсь, что в этом вопросе не слишком много шума.

EDIT

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);   
}
})

Я сделал следующие изменения

1.students в коллекции this.students (внутри инициализации представления «CourseList») в приведенном ниже коде

initialize: function () {
    this.students = new Students();
    var studentList = new StudentList({
        collection: this.students,
        el: '#studentsList'
    });

2. Я выбрал студентов из функции renderAll вместо функции render, потому что для каждого элемента курса, который был выбран, студент также выбирается. Я имею в виду, что если есть 6 курсов, я получаю возможность увидеть студентов в курсе 0 в коллекции 6 раз.

 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

В & quot; CourseList & quot; у нас есть функция инициализации, как показано ниже

 initialize: function () {
    this.students = new Students();
    var studentList = new StudentList({
        collection: this.students,
        el: '#studentsList'
    });

Список студентов приведен ниже

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

всякий раз, когда я делаю это. $ el.html (& quot; & quot;) внутри функции рендерингаStudentList смотреть как ниже

var StudentList = Backbone.View.extend({
tagName: 'ul',

render: function (model) {
this.$el.html("");
    var item = new StudentItem({ model: model });
    this.$el.append(item.el);
},
......

Я теряю элементы button и textbox внутри элемента StudentsList, и ul не отображается при просмотре исходного кода в моем браузере, который я назвал tagName, но я вижу li, которое является tagName для представления studentItem. Можете ли вы сказать, что я делать неправильно

Спасибо за наше терпение

Я бы предположил, что я могGET /api/students/:courseId получить всех студентов в этом курсе? sntran
Вы можете быть более ясным ...? bhargav
Извините, не берите в голову, вы использовали$.param вместо этого взять студентов. sntran
Что касается очистки вещи. Лучше использовать шаблон для рендеринга только учащихся, а не добавлять его в DIV с существующими элементами. Таким образом, вы можете просто заменить содержимое этого шаблона. sntran

Ваш Ответ

1   ответ
5

CourseList вид, чтобы отслеживатьStudents коллекция, а такжеStudentList,Students коллекция будет передана в каждыйCourseItem посмотреть, чтобы получить. После того, как это делает всеCourseItem, это скажетStudents коллекция для извлечения студентов первого курса.

var CourseList = Backbone.View.extend({
  tagName: 'ul',
  initialize: function () {
    this.students = new Students();
    var studentList = new StudentList({
      collection: 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;
  },

  render: function (model) {
    this.$el.html("");
    var item = new CourseItem({ model: model, students: this.students});
    this.$el.append(item.el);
    this.students.fetch({ data: $.param({ courseId: 0 }) }); // fetch the first
  },
  ...
})

CourseItem будет хранитьStudents коллекции, и при щелчке выберите нужных учеников, используя идентификатор модели.

var CourseItem = Backbone.View.extend({
  ...
  initialize: function() {
    this.students = this.options.students;
  },
  ...
  courseClicked: function () {  
    $('#spnStdntCourseName').text('Students Enrolled in ' + this.model.get("Name"));

    var courseId = this.model.id;
    this.students.fetch({ data: $.param({ courseId: courseId }) });
  },
  ...
})

ВStudentList вид, вы не можете получить его самостоятельно.

var StudentList = Backbone.View.extend({
  tagName: 'ul',
  initialize: function () {
      this.collection.on('reset', this.renderAll, this);
      this.collection.on('add', this.render, this);
      _.bindAll(this, 'renderAll', 'render');
      return this;
  },
  ...

  render: function() {
    this.$el.html(""); // Reset the view for new students
    var item = new StudentItem({ model: model });
    this.$el.append(item.el);
  }
})

Тогда в вашем основном скрипте:

window.courses = new Courses();

$(function () {
   var courseList = new CourseList({
        collection: window.course,
        el: '#courseList'
    });
});

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: непроверенные коды.

Должен ли я написать courseList.fetch (), потому что я уже упоминал об этом в своей функции инициализации & quot; CourseList & quot; просмотр и удаление показывает мне курсы bhargav
Еще один вопрос :) Скажите, пожалуйста, как я смогу показать студентам первый предмет курса, как только страница загрузится? bhargav
Theres дублирование кода здесь правильно ..? В файле student.js, как я уже упоминал выше, там, в документе. Я уже написал тот же код, который написан сейчас внутри «CourseClicked». : |. bhargav
конечно, я попробую это сейчас. bhargav
это работает как очарование, но одна проблема, когда я нажимаю на элемент курса, я вижу студентов курса, на который нажали, а также предыдущего курса ... это связано с призрачным представлением ...? bhargav

Похожие вопросы