profanis
profanis

Reputation: 2751

RequireJs - Backbone.Views depends one to each other

I have an issue with requirejs and backbone. Well, I have two views (View1 and View2). I want to call View2.render() from View1 and View1.render() from View2. In general I want each view to depends to another.

My problem is that I cannot call View2.render(). I am getting the error message "cannot call method render of undefined"

If I remove the View1 dependency from View2 then it will work.

Does anyone know how can I amend the code so it could work without issues?

EDIT

View Name-->View2

define([
'Underscore',
'Backbone',
'Handlebar',
'views/view1'
], function (_, Backbone, Handlebars, View1) {
var View2 = Backbone.View.extend({
    initialize: function () {
        _.bindAll(this, "render");
    },
    tagName: 'div',
    el: '#rightPanel',
    events: {
        'change input#createNewCategory': 'createNewItem',
        'click #saveEdits': 'saveData',
        'click #clearEdits': 'render'
    },
    render: function () {
        //do something here
    },
    clear: function () {
        this.$el.empty();
    },
    createNewItem: function (e) {
      //so something here
    },
    saveData: function () {
        //This works Fine
        View1.render();
    }
});

return new View2;
});

View Name --> View1

define([
'Underscore',
'Backbone',
'Handlebar',
'views/view2'
], function (_, Backbone, Handlebars, View2) {
var View1 = Backbone.View.extend({
    tagName: 'li',
    el: '#categoriesList',
    events: {
        'click .categoryItem': 'edit'
    },
    initialize: function () {
        _.bindAll(this, "render");
    },
    edit: function (e) {
        View2.render();
        //**ERROR (cannot call method render of undefined)**
    },
    render: function () {
        //do something here
    }
});

return new View1;
}); 

Thanks

Upvotes: 2

Views: 1024

Answers (2)

opengrid
opengrid

Reputation: 1944

First add EventBus module. This is basically Event Aggregator Pattern:

define([
    'Underscore',
    'Backbone'
], function(_, Backbone){
    var EventBus = {
    };
    _.extend(EventBus, Backbone.Events);
    return EventBus;
});

Next, use EventBus module for sending messages between modules. This also lets you subscribe for these events in multiple modules and helps to keep Single responsibility principle.:

define([
'Underscore',
'Backbone',
'Handlebar',
'EventBus',
], function (_, Backbone, Handlebars, Vent) {
var View2 = Backbone.View.extend({
    initialize: function () {
        _.bindAll(this, "render");
        Vent.on("View1:edit", this.render, this);
    },
    tagName: 'div',
    el: '#rightPanel',
    events: {
        'change input#createNewCategory': 'createNewItem',
        'click #saveEdits': 'saveData',
        'click #clearEdits': 'render'
    },
    render: function () {
        //do something here
    },
    clear: function () {
        this.$el.empty();
    },
    createNewItem: function (e) {
      //so something here
    },
    saveData: function () {
        Vent.trigger("View2:save");
    }
});

return new View2;
});


define([
'Underscore',
'Backbone',
'Handlebar',
'EventBus'
], function (_, Backbone, Handlebars, Vent) {
var View1 = Backbone.View.extend({
    tagName: 'li',
    el: '#categoriesList',
    events: {
        'click .categoryItem': 'edit'
    },
    initialize: function () {
        _.bindAll(this, "render");
        Vent.on("View2:save", this.render, this);
    },
    edit: function (e) {
        Vent.trigger("View1:edit");
    },
    render: function () {
        //do something here
    }
});

return new View1;
}); 

Upvotes: 4

Matti John
Matti John

Reputation: 20477

Circular dependencies is covered in the require.js documentation here: http://requirejs.org/docs/api.html#circular

You need to include require in your dependency list (as a param to Define function), and then use require() to call the other view, e.g.:

define([
'require'
'Underscore',
'Backbone',
'Handlebar',
'views/view1'
], function (require, _, Backbone, Handlebars, View1) {
var View2 = Backbone.View.extend({
    initialize: function () {
        _.bindAll(this, "render");
    },
    tagName: 'div',
    el: '#rightPanel',
    events: {
        'change input#createNewCategory': 'createNewItem',
        'click #saveEdits': 'saveData',
        'click #clearEdits': 'render'
    },
    render: function () {
        //do something here
    },
    clear: function () {
        this.$el.empty();
    },
    createNewItem: function (e) {
      //so something here
    },
    saveData: function () {
        //This works Fine
        require("View1").render();
    }
});

return new View2;
});

Upvotes: 0

Related Questions