IronRouter extending data option on route controller
Asked Answered
H

4

10

Is there a way to extend the data option when using IronRouter and the RouteController, It seems like it gets overridden when I inherit from a super controller, the child controller doesn't extend the defined data properties. I have had similiar issues with the yieldTemplates option on a route and used a workaround (underscore _extends) but it didn't work in this case:

ApplicationController = RouteController.extend({
     data: function(){
          return {
                 user: Meteor.user()   
         }     
   }
});

ChildController = ApplicationController.extend({
  data: function(){
        return {
               // I expect to inherit Meteor.User ?????
               someData: {}
        }
   }
});

EDIT:

After using underscore and the extend function to inherit the prototype function, I am still unable to inherit in route definition's that use the ChildController

this.route('someRoute', {
   template: 'task_template',
   //tasks is not available on the template
   data: function () {
            var base = ChildController.data.call(this);
            console.log(base);
            return _.extend(base, {
                tasks: Tasks.find({state: 'Open'})
            });
});
Hoodoo answered 14/6, 2014 at 19:3 Comment(2)
Can you explain why do you want to do this and what you are trying to achievie? Maybe there's another way?Karate
You need to also invoke the parent (super) controller from child's data().Hexagram
M
8

I use something similar to this in a production app:

Router.route('/test/:testparam', {
    name: 'test',
    controller: 'ChildController'
});

ParentController = RouteController.extend({
    data: function() {
        console.log('child params: ', this.params);
        return {
            foo: 'bar'
        };
    }
});

ChildController = ParentController.extend({
    data: function() {
        var data = ChildController.__super__.data.call(this);
        console.log(data);
        return data;
    }
});

Using __super__ seems to do the trick!
You can than use _.extend to extend the data (http://underscorejs.org/#extend)

Macario answered 29/12, 2014 at 1:17 Comment(1)
Can this be done without extending controller? by using directly on this.route definition?Jocko
V
3

To add to the selected answer, note that if you're using Coffeescript the following will yield the same result:

class @ChildController extends ParentController
  data: -> super()
  # or if you want to add to it:
  data: ->
    _.extend super(), { extraThing: 'some value' }
Vexation answered 24/4, 2015 at 9:56 Comment(1)
Really don't know why people didn't vote 4 u. Just an awesome solution. Thanks a lot!Callant
G
1

I think _.extends should work in this case as well:

ChildController = ApplicationController.extend({
  data: function() {
    var base = ApplicationController.data.call(this);
    return _.extends(base, {
      someData: {},
    });
  }
});
Grati answered 14/6, 2014 at 22:4 Comment(1)
Is it extends or extend, I tried both but still unable to use data from the ChildController. If i remove the data definition from the ApplicationController it worksHoodoo
S
0

Another option that may achieve the same result is to define a method on your parent controller, then call it using super without extending anything. It's slightly more work for each controller but is easier to apply retroactively. Also it makes the method optional for your child controller rather than by default.

ApplicationController = RouteController.extend({
        waitOn: function() {
           return [Meteor.subscribe('customUserPublish')];
        },
        GetProfileWithEmail: function(){
           var user = Meteor.user();
           var profile = user.profile;
           profile.email = user.emails[0].address;
           return profile;
        }
    });

ProfileController = ApplicationController.extend({
        waitOn: function() {
          return [Meteor.subscribe('anotherCollectionPublish')];
        },
        data: function(){
          return {
            profile:  function(){
              var profile = ApplicationController.__super__.GetProfileWithEmail.call(this);
              console.log('profile from super', profile);
              return profile;
            }
          }
        }
});

Remember that you have to subscribe to the published collection as well and I believe that you need to use the waitOn array option so that it will merge the subs properly (admittedly I always use an array format so YMMV). You can access the data in your template using {{#with profile}}...{{/with}} or if you were getting back an array of objects use {{#each profile}}...{{/each}}.

Superabundant answered 31/5, 2015 at 16:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.