93

I have a series of buttons which when clicked display a popup menu positioned just below the button. I want to pass the position of button to the view. How can I do that?

ItemView = Backbone.View.extend({
    tagName: 'li',
    events: {
        'click': 'showMenu'
    },
    initialize: function() {
        _.bindAll(this, 'render');
    },
    render: function() {
    return $(this.el).html(this.model.get('name'));
    },
    showMenu: function() {
        var itemColl = new ItemColl();
        new MenuView({collection: itemColl}); // how to pass the position of menu here?
    }
});
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
vikmalhotra
  • 9,981
  • 20
  • 97
  • 137

5 Answers5

169

You just need to pass the extra parameter when you construct the MenuView. No need to add the initialize function.

new MenuView({
  collection: itemColl,
  position: this.getPosition()
})

And then, in MenuView, you can use this.options.position.

UPDATE: As @mu is too short states, since 1.1.0, Backbone Views no longer automatically attach options passed to the constructor as this.options, but you can do it yourself if you prefer.

So in your initialize method, you can save the options passed as this.options:

initialize: function(options) {
    this.options = options;
    _.bindAll(this, 'render');
},

or use some finer ways as described by @Brave Dave.

Community
  • 1
  • 1
dira
  • 4,671
  • 2
  • 22
  • 17
  • 53
    This no longer works as of 1.1.0: ["Backbone Views no longer automatically attach options passed to the constructor as `this.options`, but you can do it yourself if you prefer."](http://backbonejs.org/#changelog). – mu is too short Oct 15 '13 at 00:15
  • 1
    This works perfectly, just add the parameter in your view initialize method: initialize: function (options) { alert(options.position); } – Cabuxa.Mapache Feb 17 '14 at 10:53
  • @Cabuxa.Mapache No, it doesn't work. This answer uses `this.options.position`, not `options.position`. Views used to attach the `initialize` arguments to `this.options` but that stopped happening in 1.1.0. – mu is too short May 30 '14 at 00:16
46

Add an options argument to initialize:

initialize: function(options) {
    // Deal with default options and then look at options.pos
    // ...
},

And then pass in some options when you create your view:

var v = new ItemView({ pos: whatever_it_is});

For more information: http://backbonejs.org/#View-constructor

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • this is more elegant/simple for most of the situations. – Cullen SUN May 20 '13 at 04:46
  • @CullenSUN: Thanks. I prefer the explicitness of this approach, the magical "action at a distance" of using `this.options` gives me maintenance and debugging nightmares. – mu is too short May 20 '13 at 04:55
  • I saw the Backbone link first but your example clarified it for me. Thanks – Manuel Hernandez Aug 06 '13 at 15:01
  • This has been deprecated, and you can no longer use `this.options` – Trip Dec 06 '13 at 14:26
  • 4
    @Trip: Huh? `initialize: function(options) { ... }` is just fine, the change is that Backbone no longer automatically sets `this.options` for you: ["Backbone Views no longer automatically attach options passed to the constructor as `this.options`, but you can do it yourself if you prefer."](http://backbonejs.org/#changelog). – mu is too short Dec 06 '13 at 15:58
  • @muistooshort so `initialize: function(options) { this.options = options }` would be fine? – alapeno Dec 07 '13 at 18:57
  • @alapeno: You could do that but I think unpacking `options` into properties is still a better idea. If you use `this.options` all over the place then it is very difficult to know what your view's interface really is and that just leads to maintenance problems. – mu is too short Dec 07 '13 at 19:44
  • You can use the [backbone.viewOptions plugin](https://github.com/rotundasoftware/backbone.viewOptions) to white-list initialization options and automatically attach them directly to your view. – Brave Dave Jan 05 '14 at 04:03
12

As of backbone 1.1.0, the options argument is no longer attached automatically to the view (see issue 2458 for discussion). You now need to attach the options of each view manually:

MenuView = Backbone.View.extend({
    initialize: function(options) {
        _.extend(this, _.pick(options, "position", ...));
    }
});

new MenuView({
    collection: itemColl,
    position: this.getPosition(),
    ...
});

Alternatively you can use this mini plugin to auto-attach white-listed options, like so:

MenuView = Backbone.View.extend({
    options : ["position", ...] // options.position will be copied to this.position
});
Brave Dave
  • 1,300
  • 14
  • 9
-1

pass from other location

 new MenuView({
   collection: itemColl,
   position: this.getPosition()
})

Add an options argument to initialize in view you are getting that passed variable,

initialize: function(options) {
   // Deal with default options and then look at options.pos
   // ...
},

to get the value use -

   var v = new ItemView({ pos: this.options.positions});
Imtiaz Mirza
  • 591
  • 1
  • 7
  • 26
-2

Use this.options to retrieve argumentr in view

 // Place holder
 <div class="contentName"></div>

 var showNameView = Backbone.View.extend({
        el:'.contentName',
        initialize: function(){
            // Get name value by this.options.name
            this.render(this.options.name);
        },
        render: function(name){
            $('.contentName').html(name);
        }
    });

    $(document).ready(function(){
        // Passing name as argument to view
        var myName1 = new showNameView({name: 'Nishant'});
    });

Working Example: http://jsfiddle.net/Cpn3g/1771/

Nishant Kumar
  • 5,995
  • 19
  • 69
  • 95