0
votes

In my Ember template, I render an arbitrarily-sized array of displayItems like so:

<script type="text/x-handlebars" id="display">
    <h1>{{name}}</h1>
    <hr>
    <div id="display-items">
        {{#each displayItem in displayItems itemController="chart"}}
            {{render "chart" displayItem}}
        {{/each}}
    </div>
</script>

However, I need to initialize some properties on the chart controller before the chart view renders. I know that for predefined view and controller structures, you can use the setupController hook on a route, but since these controllers are created dynamically, I thought I could use the chart controller's init property like so:

...other controller code
init: function() {
    var self = this;

    self._super();

    self.get("views")
    .then(function(views) {
        self.set("currentView", views.objectAt(0));
    });
}
...

But although the init hook is called, it is called too late--the view has already rendered with undefined values. Is there a way to setup dynamically-created controllers before their views render?

1
first off, I think you don't need to specify itemController="chart" in your loop, because render 'chart' displayItem will create a new chart controller for each element. And for your question, isn't render creating a new controller ?, In the docs have this: When no model is provided it gets the singleton instance of the corresponding controller. And When a model is provided it gets a unique instance of the corresponding controller. I guess it is creating a new controller, I haven't look at the source, but if it is creating a new controller, then, the init should be fired. - fanta
thanks for the reply! Init is firing, it's just firing after I want it to--it doesn't fire before the views are rendered, which means that properties required for the view to render start off as undefined... - Brad Ross
I see, then, why don't you use and 'if' in your view ? an in your 'chart' controller create a property that will be 'true' only when all the properties you need are complete.. that way in the view, the code will be fired after the property is 'true'. - fanta
this is an example jsfiddle.net/NQKvy/1186 - fanta
great idea! I implemented it, and it works. If you want the bounty, go ahead and submit an answer explaining what you mean in a bit more detail. - Brad Ross

1 Answers

1
votes

What you need to do is to create a property in your 'chart' controller, that will be observing all properties you need to be filled int before displaying the view. First off, I would recommend you to change this:

{{#each displayItem in displayItems itemController="chart"}}
  {{render "chart" displayItem}}
{{/each}}

to this:

{{#each displayItem in displayItems}}
  {{render "chart" displayItem}}
{{/each}}

'render' will instantiate a new charController for you, and its corresponding view. Then, in your 'chartController', add a property listening to all properties you need before rendering the view:

App.ChartController = Ember.ObjectController.extend({
  isAllInformationComplete: function() {
    return !Ember.isEmpty('property1') && !Ember.isEmpty('property2');
  }.property('property1', 'property2')
});

and in your view, wrap your code in an if statement:

<script type="text/x-handlebars" data-template-name="chart">
  {{#if isAllInformationComplete}}
    All your view html, handlebars, etc...
  {{/if}}
</script>

here is a Fiddle for more details.