Elte Hupkes
Elte Hupkes

Reputation: 2978

Ember.js: Dynamically switching layouts with outlets

I'm trying to dynamically switch between layouts in Ember.js by having one outlet named layout in ApplicationView, and several layout classes with an unnamed outlet inside of it. See this JSfiddle: http://jsfiddle.net/ElteHupkes/SFC7R/2/.

This works fine the first time, however upon toggling the layout the content disappears. This seems to be the same problem that occurs when you simply re-render the application view (router.get('applicationView').rerender()), making this question somewhat related to my other one earlier: Re-rendering ApplicationView with outlet.

I would say that as the controller bindings stay the same, the unnamed outlet should still be connected and the inner view contents should thus be rendered. I'm hoping someone can enlighten me as to why they aren't :).

HTML:

<script type="text/x-handlebars" data-template-name="application">
  {{outlet layout}}
  <a href="#" {{action doToggleLayout}}>Toggle layout</a>
</script>

<script type="text/x-handlebars" data-template-name="layout1">
  <h1>Layout 1</h1>
  {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="layout2">
  <h1>Layout 2</h1>
  {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="index">
  Page contents.
</script>

JS:

App = Ember.Application.create({
    autoinit: false,
    Router: Ember.Router.extend({
        root: Em.Route.extend({
            index: Em.Route.extend({
                route: '/',
                connectOutlets: function(router) {
                    // Fire toggle once as an initializer
                    router.send('doToggleLayout');

                    router.get('applicationController').connectOutlet('index');
                }
            }),

            doToggleLayout: function(router) {
                this.set('layoutClass', this.get('layoutClass') == App.Layout2View ? App.Layout1View : App.Layout2View);

                router.get('applicationController').connectOutlet({
                    viewClass: this.get('layoutClass'),
                    outletName: 'layout'
                });
            }
        })
    }),

    ApplicationView: Em.View.extend({
        templateName: 'application'
    }),

    ApplicationController: Em.Controller.extend({})
});

App.IndexView = Em.View.extend({
    templateName: 'index'
});
App.Layout1View = Em.View.extend({
    templateName: 'layout1'
});
App.Layout2View = Em.View.extend({
    templateName: 'layout2'
});
App.set('layoutClass', App.Layout2View);
App.initialize();

Upvotes: 1

Views: 851

Answers (1)

sly7_7
sly7_7

Reputation: 12011

I think for potential leaks reason, when you switch the outlet, the previous view (and all of its subviews are destroyed. So you have to reconnect the anonymous outlet in order to fill it.

Upvotes: 2

Related Questions