Search code examples
ember.jsember-router

ember.js: can I only render in route?


I need some "conceptual" advice for ember.js.

I think I understand how things work for straight forward cases when the URL changes (manually or with transitionTo). The route is responsible for loading the corresponding model and render a template into the parent's outlet.

What I don't understand is: there are some occasions where you want to change the state of the application but you do not want to (or can't) change the URL.

Let's say I have a template with two outlets:

<div id='dashboard'>
  <div id='top'>{{outlet top}}</div>
  <div id='bottom'>{{outlet bottom}}</div>
</div>

top and bottom part of the dashboard are independent of each other. Initially the application probably transitions to a /dashboard route which renders the initial state of top and bottom into the outlets. But what happens then? If I want to change the content of the top outlet, where do I render and insert that content (since there is no route involved)? Can I render in a controller? Do I have to set up a custom view container and how and where would that be rendered?

Any hint would be appreciated.


Solution

  • Not really sure if this is the best way to go about it, but I was playing around and got it working like this:

    Full Source | Run

    JavaScript:

    App.DashboardView = Em.View.extend({
        starActive: true,
        userActive: false,
        heartActive: false,
        resetDisplay: function() {
            this.set('starActive', false);
            this.set('userActive', false);
            this.set('heartActive', false);
        },
        star: function() { 
            console.log('star'); 
            this.resetDisplay();
            this.set('starActive', true);
        },
        user: function() {
            console.log('user'); 
            this.resetDisplay();
            this.set('userActive', true);
        },
        heart: function() {
            console.log('heart'); 
            this.resetDisplay();
            this.set('heartActive', true);
        }
    });
    

    Handlebars:

    <script type="text/x-handlebars" data-template-name="_navDashboard">
        <ul class="nav-list">
            <li class="nav-header">Actions</li>
            <li>
                <a {{action star target="view"}}><i class="icon-star"></i> One</a>
            </li>
    
            <li>
                <a {{action user target="view"}}><i class="icon-user"></i> Two</a>
            </li>
            <li>
                <a {{action heart target="view"}}><i class="icon-heart"></i> Three</a>
            </li>
        </ul>
    </script>
    
    <script type="text/x-handlebars" data-template-name="dashboard/user">
        <h3>User</h3>
    </script>
    
    <script type="text/x-handlebars" data-template-name="dashboard/star">
        <h3>Star</h3>
    </script>
    
    <script type="text/x-handlebars" data-template-name="dashboard/heart">
        <h3>Heart</h3>
    </script>
    
    <script type="text/x-handlebars" data-template-name="dashboard">
        <div class="row-fluid">
            <h2>Dashboard</h2>
        </div>
        <div class="row-fluid">
            <div class="span3">
                <div class="well sidebar-nav">
                  {{partial navDashboard}}
                </div>
            </div>
            <div class="span7">
                {{#if view.starActive}}
                    {{render "dashboard/star"}}
                {{/if}}
                {{#if view.userActive}}
                    {{render "dashboard/user"}}
                {{/if}}
                {{#if view.heartActive}}
                    {{render "dashboard/heart"}}
                {{/if}}
            </div>
        </div>
    </script>
    

    I'm not sure about this solution because it makes the developer responsible for managing when to render or not a certain template or view; depending on the complexity it would be easier to make a mistake and leave more than one view display at the time, or even display the wrong view, but that's what I got at the moment.