Ember - Handle multiples panes and tabs

Here is a solution to handle an application build around two panes, each one having multiple tabs. The router is able to memorize the current tab selected in each pane: * /designer/leftTab1/rightTab1 * /designer/leftTab1/rightTab2 * /designer/leftTab2/rightTab3 * / ...

by obalais

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0-rc.3/handlebars.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/ember.js/1.0.0-rc.1/ember.js"></script>
<script type="text/x-handlebars" data-template-name="application">
  <h1>This is a sample app</h1>
  {{outlet leftPanel}}
  {{outlet rightPanel}}
</script>

<script type="text/x-handlebars" data-template-name="leftPanel">
    <a href="#lefttab1" {{action selectTab "leftPanelTab1"}}>Left pane tab 1</a>
    <a href="#lefttab2" {{action selectTab "leftPanelTab2"}}>Left pane tab 2</a>
    <div class="tab-container">{{outlet}}</div>
</script>

<script type="text/x-handlebars" data-template-name="leftPanelTab1">
Left Panel Tab1
</script>

<script type="text/x-handlebars" data-template-name="leftPanelTab2">
Left Panel Tab2
</script>

<script type="text/x-handlebars" data-template-name="rightPanel">
    <a href="#righttab1" {{action selectTab "rightPanelTab1"}}>Right pane tab 1</a>
    <a href="#righttab2" {{action selectTab "rightPanelTab2"}}>Right pane tab 2</a>
    <div class="tab-container">{{outlet}}</div>
</script>

<script type="text/x-handlebars" data-template-name="rightPanelTab1">
    Right Panel Tab1
</script>

<script type="text/x-handlebars" data-template-name="rightPanelTab2">
Right Panel Tab2
</script>

CSS

h1 {
    font-size: 20px;
    border-bottom: 1px solid #ccc;
    margin-bottom: 20px;
}
.pane {
    display:inline-block;
    width: 40%;
    height: 250px;
}

.tab-container {
    display: block;
}

JavaScript

App = Ember.Application.create({});

App.Router.map(function() {
    this.resource('panels', { path: '/:leftTab/:rightTab' });
});

App.ApplicationRoute = Ember.Route.extend({
    events: {
        leftTabChanged: function(tab) {
            this.controllerFor('application').set('leftTab', tab);
            this.transitionTo('panels', {
                leftTab: tab,
                rightTab: this.controllerFor('application').get('rightTab')
            });

        },
        rightTabChanged: function(tab) {
            this.controllerFor('application').set('rightTab', tab);
            this.transitionTo('panels', {
                leftTab:this.controllerFor('application').get('leftTab'),
                rightTab:tab
            });
        }
    },

    renderTemplate: function() {
        this.render();
        this.render('leftPanel', {
            outlet: 'leftPanel',
            into: 'application'
        });

        this.render('rightPanel', {
            outlet: 'rightPanel',
            into: 'application'
        });
    }
});

App.IndexRoute = Ember.Route.extend({
    redirect: function() {
        this.transitionTo('panels', {
            leftTab: this.controllerFor('application').get('leftTab'),
            rightTab: this.controllerFor('application').get('rightTab')
        });
    }
});

App.PanelsRoute = Ember.Route.extend({
    serialize: function(params, paramNames) {
        return params;
    },
    renderTemplate: function(controller, params) {

        this.render(params.leftTab, {
            into: 'leftPanel'
        });


        this.render(params.rightTab, {
            into: 'rightPanel'
        });
    }
});

App.ApplicationController = Ember.Controller.extend({
    leftTab: 'leftPanelTab1',
    rightTab: 'rightPanelTab1'
});

App.LeftPanelController = Ember.Controller.extend({
    selectTab: function(tab) {
        this.send('leftTabChanged', tab);
    }
});

App.LeftPanelView = Ember.View.extend({
    classNames:...