Conditional rendering of header based upon action


#1

Hi,

Every page in my ember app renders a header using this application.hbs:

{{partial "header"}}

{{outlet}}

{{partial "footer"}}

However, for a couple of actions like e.g sign-in and signup I want a different much simpler header than all the other actions. This is similar to what http://angel.co does when you click Log In. What is the recommended practices for implementing this?


Custom computed property for route specific values
#2

Why don’t you use a simple conditional statement?

{{#if isUserLoggedIn}}
    {{partial "header_v1"}}
{{else}}
    {{partial "header_v2"}}
{{/if}} 

I’m not sure that it’s a good solution, but at least…


#3

In this solution, how do I make the partial conditional upon which controller or action is currently rendered? The header is in my case not conditional upon if the user is authenticated or not.


#4

You could try to use the render method available to routes. The render method allows you to control which templates, controller and model is used for specific parts of your application. This combined with named outlets might be what you are after.

Route render api: http://emberjs.com/api/classes/Ember.Route.html#method_render

Named outlets take the form:

{{outlet header}}

So when you enter or exit routes you could render the specific template you need for the header.


#5

currentPath is available on the ApplicationController so you can do something like:

App.ApplicationController = Ember.Controller.extend({
    headerPartial: function(){
        return this.get("currentPath") === '/login' ? 'simpleHeader' : 'fullHeader';
    }.property("currentPath")
})

#6

employing something similar to @opsb’s route lookup, I was able to get it to work with the following stubs to show the login template without the wrapping content (headers, navbars, etc):

app/controllers/application.js

import Ember from 'ember';

export default Ember.Controller.extend({
    isLoginRoute: Ember.computed.equal('currentRouteName', 'login')
});

app/templates/application.hbs

<div {{bind-attr class="isLoginRoute::wrapper"}}>
{{#unless isLoginRoute}}
    {{partial "header"}}
    {{bread-crumbs}}
{{/unless}}
        {{outlet}}
{{#unless isLoginRoute}}
    {{partial "footer"}}
{{/unless}}
</div>

the class binding was used to ensure no wrapper affects the login template but would otherwise be active but probably there’s a better way out there to achieve this.


#7

@asabjorn a thread I made earlier has a solution to this problem.

probably the easiest thing for you is to have a computed property on your application controller:

showReducedHeader: function(){
        //array of all routes without header
        var reducedHeader = [
            'login',
            'logout'
        ]
        //read as reducedHeader.contains('currentPath')
        return ($.inArray(this.get('currentPath'), reducedHeader) != -1);
 }.property('currentPath')

and then your template

{{#if reducedHeader}}
    {{partial 'reducedHeader'}}
{{else}}
    {{partial 'header'}}
{{/if}}

or using my routeVal computed property defined in the link:

routeVals: [
        RouteVal.create({
            route: 'login',
            reducedHeader: true
        }),
        RouteVal.create({
            route: 'logout',
            reducedHeader: true
        })
],
reducedHeader: routeVal('routeVals', 'reducedHeader')

#8

I’m not sure why back then I was using the {{unless}} … {{/unless}} blocks but today this is what I have in my login template instead:

{{#if isLoginRoute}}
  {{outlet}}
{{else}}
  {{partial "header"}}
  {{bread-crumbs}}
	{{#each flashMessages.queue as |flash|}}
	  {{flash-message flash=flash messageStyle="bootstrap"}}
	{{/each}}
  {{outlet}}
  {{partial "footer"}}
{{/if}}