Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context option for child views like in NestedView #2

Open
ghost opened this issue Sep 18, 2013 · 10 comments
Open

Add context option for child views like in NestedView #2

ghost opened this issue Sep 18, 2013 · 10 comments

Comments

@ghost
Copy link

ghost commented Sep 18, 2013

Why you don't added context option binding for child views like in your NestedView plugin for Backbone ?

Example:
{{#each models}}
{{view "myChildView" context=this}}
{{/each}}

@spikebrehm
Copy link
Member

Interesting. I suppose I never encountered that case. It also seems more brittle, and safer to explicitly pass in specific attributes.

What's your use case?

@ghost
Copy link
Author

ghost commented Sep 19, 2013

app/templates/places/list.hbs
{{#each places}}
{{view "places/place" context=this}}
{{/each}}

app/templates/places/place.hbs
{{context.name}}

It's better if we can do that:

app/templates/places/list.hbs
{{#each places}}
{{view "places/place" context=this}}
{{/each}}

app/templates/places/place.hbs
{{name}}

@spikebrehm
Copy link
Member

Hmm. Well, typically you'd be working with models and collections, right? So you could do something like:

{{#each places}}
{{view "places/place" model=this}}
{{/each}}

@ghost
Copy link
Author

ghost commented Sep 20, 2013

app/templates/places/list.hbs
{{#each places}}
{{view "places/place" model=this}}
{{/each}}

app/templates/places/place.hbs
{{name}}

I have this exception:
Express
500 TypeError: Object # has no method 'toJSON'
at module.exports.Backbone.View.extend.getTemplateData (/Users/chris/workspace/croosty/croosty-app/node_modules/rendr/shared/base/view.js:97:25)

@ghost
Copy link
Author

ghost commented Sep 20, 2013

It's working when I do that, tell me if it's a good usage.

app/controllers/places_controller.js

var _ = require('underscore');

module.exports = {
  index: function(params, callback) {
    var spec = { 
      places: { collection: 'Places', params: { location: params['location'] }, expires: 3600 }
    };

    this.app.fetch(spec, function(err, results) {
      if (err) return callback(err);
      callback(err, results);
    });
  },

  show: function(params, callback) {
    var spec = {
      place: { model: 'Place', params: params }
    };

    this.app.fetch(spec, function(err, result) {
      if (err) return callback(err);
      callback(err, result);
    });
  }
};

app/views/places/index.js

View = require('../../base/view');

module.exports = View.extend({
  className: 'places-index',

  getTemplateData: function() {
    var data = View.prototype.getTemplateData.call(this);
    data.location = this.options.places.meta.location;
    data.places_count = this.options.places.meta.places_count;
    return data;
  }
});

module.exports.id = 'places/index';

app/templates/places/index.hbs

<aside id="sidebar">
  <header id="location-infos">
    <h2>{{places_count}} restaurants à {{location.name}}</h2>
  </header>

  {{view "places/list" collection=places}}
</aside>

app/views/places/list.js

View = require('../../base/view');

module.exports = View.extend({
  tagName: 'ul',
  id: 'places-list'
});

module.exports.id = 'places/list';

app/templates/places/list.hbs

{{#each _collection.models}}
  {{view "places/place" model=this}}
{{/each}}

app/views/places/place.js

View = require('../../base/view');

module.exports = View.extend({
  tagName: 'li',
  className: 'place'
});

module.exports.id = 'places/place';

app/template/places/place.hbs

{{name}}

@jeromegn
Copy link

I'm stumbling on the same issue.

I tried your code. For the first instantiation, it seems fine. However, if I reload the same page (in rendr), then all of my models seem to equal the last model in the array. Caching issue?

Also, curiously _models and _collection.models is not the same (first one will give me "toJSON error").

Are we doing something wrong?

@jeromegn
Copy link

Looks like adding a idAttribute to my model (because they don't have an id) makes this go away. Nice.

@spikebrehm
Copy link
Member

Good catch re: idAttribute!

@vincentbello
Copy link

I found myself being able to nest views within loops like this:

{{#each models}}
   {{view="xview" model=this}}
{{/each}}

And then, in xview.js:

var BaseView = require('./base');
module.exports = BaseView.extend({
    getTemplateData: function () {
        return this.model;
    }
});
module.exports.id = 'xview';

Because in xview, this.model is just an array.
But in this case, the "xview" instances lose their model. All the views in App.router.currentView.childViews have model "undefined." Is there any workaround for this? It would be tremendously useful to be able to do this to nest views and still access these views' models.

@StevenLangbroek
Copy link

+1 on this. This allows for a nice and clear encapsulation of model's view logic within a template (click handlers etc), without having to override the getTemplateData, or breaking convention (a view's model property should always be exactly that: its model, not a JSON representation of a model).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants