使用事件聚合器加载骨干JS用不同的模型的视图 [英] Using Event Aggregator to load a view with different model in backbone js

查看:90
本文介绍了使用事件聚合器加载骨干JS用不同的模型的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来Backbone.js的开始与骨干一个星期前。我不得不做出一个演示。其背后的主要思想是在加载页面的时候,我需要显示的课程,并默认了学生名单在列表中的第一场。这里是code,以显示该课程列表这是在 course.js 文件

I am new to backbone.js started with backbone a week ago. I had to make a demo. The main idea behind it is when the page is loaded, I need to show the courses,and by default the students list for the first course in the list. Here is the code to display the course list which is in course.js file

//型号

//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 查看,它应该加载过程项被点击时的学生名单。

Please take a look at the 'courseClicked' function inside CourseItem View, it is supposed to load the students list when a course item is clicked.

现在,我有我的学生在students.js模型和视图如下

Now I have my Student model and views in students.js as below

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

//浏览

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

所以里面的document.ready我已 studentDetails 它加载了学生list.Here是我的问题,因为现在的变量我已经通过传递一些硬code参数加载在页面加载学生列表内取像下面

so inside document.ready I have studentDetails variable which loads the students list.Here is my problem as of now I have loaded the students list on page load by passing some hard code parameter inside fetch like below

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

但我要表明的是,当页面加载在courselist鉴于第一期培训班的学生名单,并在以后的阶段,学生名单为每clicked.For为此每门课程的项目,如果你能记得里面course.jsCourseItem视图中的courseClicked功能,我用

but what I need to show is, the student list for the first course in the courselist view when the page is loaded, and in later stages, the student list for each and every course item clicked.For that purpose if you can remember in the "courseClicked" function inside "CourseItem" view in course.js, I have used

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

studentDetails是我在students.js已经初始化的VAR(在code以上)这样的

studentDetails is the var that I have initialised in students.js(in the code above) like this

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

所以,当我触发studentDetails我defnitely是需要我courseClicked功能,这是不是在这方面可里面的学生模型。我beleive你们从上述解释明白我的问题。那么,如何解决这个问题......?是我跟着错了方法..?任何一个优秀的选择,需要的建议。希望没有在问题太多噪声

So when I trigger the studentDetails I defnitely be needing the student model inside my courseClicked function,which is not available in that context. I beleive you guys understood my problem from the above explanation. So how do I fix this...? Is the approach I followed wrong..? Any good alternative,need suggestions. Hope there is not too much noise in the question.

修改

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

我已经作出如下更改

I have made following changes

在收集到1.students this.students(里面的CourseList视图初始化)在下面的code

1.students in collection to this.students(inside initialize of "CourseList" view) in the below code

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

2.我已经赚得renderAll函数,而不是渲染函数内的学生,因为这是拿来学生每门课程的项目也fetched.I意味着,如果有6门课程我能看到学生课程0集合中6次

2.I have fetched the students inside renderAll function instead of render function because for every course item that is fetched the student is also fetched.I mean if there are 6 courses i get to see the students for course 0 in the collection 6 times

 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

在CourseList我们必须初始化函数如下

In the "CourseList" we have initialize function as below

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

该studentsList EL是如下

The studentsList el is as below

<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()内呈现如下图所示。

whenever I do this.$el.html("") inside render function of StudentList view like below

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

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

我松散的studentsList埃尔内的按钮和文本框的元素,当我在我的浏览器,我作为标签名提到的查看源代码code未显示的UL,但我确实看到李是标记名studentItem视图。你能说什么,我做错了。

I loose the button and textbox elements inside the studentsList el, and the ul is not shown when I view source code in my browser which I mentioned as tagName, but I do see li which is tagName for studentItem view.Can you say what I am doing wrong

感谢我们的耐心

推荐答案

首先,你要让 CourseList 查看跟踪的学生集合以及一个 StudentList 。在学生集合将被传递到每个 CourseItem 视图来获取。它呈现毕竟 CourseItem ,它会告诉学生收集来获取第一期培训班的学员。

First, you want to let the CourseList view to keep track of a Students collection as well as a StudentList. The Students collection will be passed into each CourseItem view to fetch. After it renders all CourseItem, it will tell the Students collection to fetch the first course's 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 学生收集储存,并在被点击,获取利用其模型的id正确的学生

The CourseItem will store the Students collection, and on being clicked, fetch the correct students using its model's id.

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 视图,你不让它自行提取。

In StudentList view, you don't let it fetch by itself.

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

然后在你的主脚本:

Then in your main script:

window.courses = new Courses();

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

免责声明:未经测试codeS

DISCLAIMER: Untested codes.

这篇关于使用事件聚合器加载骨干JS用不同的模型的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆