Ember.js Flash Messages

This is a simple way to create flash messages that are similar to the Ruby on Rails flash messages. I took from Yehuda Katz’s answer on this Stack Overflow post, and extended it to work with the updated controllerFor/needs changes and closing on transitions.


<div class="container">
  {{#if notification}}
  <div {{bindAttr class=":alert notification.type"}} id="notification">
    <button type="button" class="btn-close" {{action "closeNotification"}}></button>
    {{#if notification.title}}


App.ApplicationController = Ember.Controller.extend

  # close notification alert
  # bind to action in template, example: {{action "closeNotification"}}
  # detects if persists and closes on next transition
  closeNotification: ->
    notification = @get('notification')
    if notification
      if notification.persists
        console.log "Notification detected, clearing alert notification after next transition"
        notification.persists = null
        console.log "Notification detected, clearing alert notification now"
        this.set('notification', null)

  # notification alert
  # type can be: error, info, success
  # example: @get('controllers.application').notify({title: "Error!", message: "An error occurred in foobar.", type: "alert-error"})
  notify: (options) ->
    this.set('notification', options)


App.PostsNewController = Ember.ObjectController.extend
  needs: ["application"] # allows access to application controller functions

  # post save
  save: ->
    @set('model.title', @get('title'))
    @set('model.description', @get('description'))

    post = @get('model')

    # if post is not valid, show flash message
    post.on 'becameInvalid', this, (obj) ->
        title: "Error!",
        message: "There was an error creating this post.",
        type: "alert-error"})

    # if post was created transition to posts index, show flash message and persist it to next transition
    post.on 'didCreate', this, () ->
        title: "A new post!",
        message: "#{@get('model.title')} was created.",
        type: "alert-success",
        persists: true})

    # commit post to server


App.BeforeRoute = Ember.Route.extend
  # close any open notifcations before a route loads
  activate: ->

App.PostsIndexRoute = App.BeforeRoute.extend()

In the application.handlebars template I create a condition that checks if the notification variable is set, and if it is, display it with it’s message and alert-type class(error, success, info, etc).

In the application controller, there’s a function that creates the notification and passes options to it, and there’s also a function that closes the notification. The closeNotification first checks for a ‘persists’ flag and if it doesn’t exist it sets the notification variable to null, which closes it. If a ‘persists’ flag does exist, it sets it the flag to null and skips closing the notification. On the next transition, the ‘persists’ flag wont exist and the notification will be closed.

In the posts new controller, at the top I have a needs array, which let’s the controller know that we need access to the application controller. The notifications are hooked into the ‘on’ callbacks for the post model, and called by using @get(‘controllers.application’).notify(). In earlier versions of Ember.js you would directly use the controllerFor() function, but that was deprecated for ‘needs’.

Lastly in the router, I created an App.BeforeRoute extension of Ember.Route which all of my routes extend from. This way every route will execute the activate function, which executes the closeNotification function, before every route loads.