8

I am familiar with building backbone apps but am trying to convert it to use requirejs, the issue i am facing is when i am trying to extend the parent view, it is undefined

when trying to extend base-view.js to properties-view.js

 define(['backbone','underscore','jquery','views/node/base-view'],                  
   function(Backbone, _, $, NodeBaseView){
     PropertiesView = NodeBaseView.extend({

        });
     }
});

Instantiating a child view inside the parent base view

    define(['backbone','underscore','jquery','views/node/properites-view'], function(Backbone, _, $, PropertiesView){
    NodeBaseView = Backbone.View.extend({
    ..
        new PropertiesView({});
    ..
    });

});

Here NodeBaseView is undefined when trying to extend it for PropertiesView. Any Help?

Note: I am using AMD versions of backbone and underscore from here https://github.com/amdjs

Gokul Kav
  • 839
  • 1
  • 8
  • 14

3 Answers3

3

The problem here appears to be a circular dependency. Base view requires properties view, and vice versa. This results in one of them being undefined.

greim
  • 9,149
  • 6
  • 34
  • 35
  • I understand that. However the regular version of backbone does not have this issue and extending views is one of the features. Any idea how I can fix this here – Gokul Kav Mar 18 '13 at 17:06
  • 2
    Well, to be clear, unless I've totally misunderstood the question, the issue you're experiencing has nothing to do with Backbone. It's rather with how you're using require. Circular dependencies aren't allowed in AMD. (Someone correct me if I'm wrong.) Even if you weren't using require, it seems strange to me that a parent view would depend on a child view. Not trying to tell you what's best for your code, just saying I think there's valid reasons a dependency lib would disallow it. If it were me I'd work around the issue by simply using three views. – greim Mar 19 '13 at 04:11
  • its the child view that wants to extend the parent view (not parent view extending the child view). Was wondering if anyone had experience using AMD with backbone and extended parent views to child views for using parent methods and event handling. – Gokul Kav Mar 19 '13 at 19:35
  • @GokulKav I've got the very same situation here. Have you managed to solve it? So I'm unable to instantiate a child view from the parent? If not, how can I get the same behavior doing it in a different way? – darksoulsong Dec 12 '13 at 12:31
  • It's generally a limitation with the AMD format as per James Burke's comment here: http://stackoverflow.com/questions/4881059/how-to-handle-circular-dependencies-with-requirejs-amd – backdesk Dec 12 '13 at 15:38
  • But generally you're always doing something similar when you work with Backbone.View ... you'll have views which instantiate other views and both views will have a Backbone dependency. – backdesk Dec 12 '13 at 15:40
  • I think backbone from v1.0 offers native support for AMD and now I am able to extend child views without any problem. Please comment if you have the problem even if using > v1.0 or else I will close the question. – Gokul Kav Dec 13 '13 at 19:02
  • Backbone 1.0 does not have any kind of native AMD support. http://stackoverflow.com/questions/9009510/why-did-underscore-js-remove-support-for-amd - you would have to go with an AMD flavor instead or load it using the 'shim' configuration. – backdesk Dec 16 '13 at 11:08
3

Let's pretend this definition sits in 'views/main'

define(['backbone', 'views/node/base'],                          
    function(Backbone, BaseView){
        var MainView = BaseView.extend({

        });

        return MainView;
    }
);

Then as your child view:

define(['backbone', 'views/node/base'],                          
    function(Backbone, BaseView) {
        var PropertiesView = BaseView.extend({

        });

        return PropertiesView;
    }
);

Then somewhere else in a universe far far away:

myView = new MainView();

Using the example from the manual:

define(['backbone', 'views/node/base'],                          
    function(Backbone, BaseView){
        var MainView = BaseView.extend({

        });

        return MainView;
    }
);

Then

define(['backbone'], function (Backbone) {                  
  var BaseView;

  require(['views/node/base'], function(b){
      BaseView = b;
  });

  var PropertiesView = BaseView.extend({

  });

  return PropertiesView;
});
backdesk
  • 1,781
  • 3
  • 22
  • 42
  • In my case, yes, I am returning the "PropertiesView". It seems I'm not supposed to instantiate a child from the parent but I really can't think of another way to make the parent becomes aware of its child. – darksoulsong Dec 12 '13 at 14:01
  • There's nothing wrong with instantiating a child view from the parent in principle. You could alternatively use the CommonJS format or just require one of your views in. See redolent's example at: http://stackoverflow.com/questions/4881059/how-to-handle-circular-dependencies-with-requirejs-amd – backdesk Dec 12 '13 at 15:03
1

You could require PropertiesView dynamically so BaseView does not have to depend on it.

define(['backbone','underscore','jquery','views/node/base-view'],
   function(Backbone, _, $, NodeBaseView){
     PropertiesView = NodeBaseView.extend({

        });
     }
     return PropertiesView;
});

Here you require PropertiesView

define(['backbone','underscore','jquery'],
    function(Backbone, _, $, PropertiesView){
        NodeBaseView = Backbone.View.extend({
        ..
            var PropertiesView = require('views/node/properites-view');
        ..
            new PropertiesView({});
        ..
        });

});

Example:

define(['views/node/base-view', 'views/node/properites-view'],
    function(NodeBaseView, PropertiesView){
        return {
            base: new NodeBaseView()
        }
});
joseljmz
  • 11
  • 2