Skip to content

Instantly share code, notes, and snippets.

@joshnesbitt
Created October 30, 2013 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshnesbitt/7230503 to your computer and use it in GitHub Desktop.
Save joshnesbitt/7230503 to your computer and use it in GitHub Desktop.

If you've used Rails for a while you'll be well familiar with flash messages. Flash objects provide a way to temporarily store information to recall later (usually on the next page render). This can be really useful for performing an action in a controller and then setting a feedback message to show the user during the next action.

We've done a lot of work with EmberJS lately, and we needed this functionality to feedback model saves to the user. There are already a wide variety of solutions out there, including the awesome Growl-esque notifications by Aaron Haurwitz, but for one of our smaller projects we wanted something simpler.

We're already using Foundation for it's excellent grid system, so we wanted to re-purpose the alert component into Ember JS flash object.

You can view the complete demo here, what follows is a break down of each area. Please note that this demo assumes you have the Foundation CSS and EmberJS loaded on the page.

Model

Firstly, we'll create the flash model, responsible for storing information such as the type of message (alert and success) and the message content itself.

App.FlashModel = Ember.Object.extend({

  type : null,

  message : null,

  isAlert : Ember.computed.equal('type', 'alert'),

  isSuccess : Ember.computed.equal('type', 'success'),

  clear : function(){
    this.update(null, null);
  },

  update : function(type, message){
    this.set('type', type);
    this.set('message', message);
  },

  success : function(message){
    this.update('success', message);
  },

  alert : function(message){
    this.update('alert', message);
  }

});

View

Then we need to create a view, which is backed by the flash model. This is responsible for binding to model properties and ensuring the view reflects the current model state. It also handles hiding the modal by clearing the flash data from the model on a click event.

App.FlashView = Ember.View.extend({

  templateName : 'flash',

  classNames : [ 'alert-box' ],

  classNameBindings : [ 'success', 'alert' ],

  messageBinding : 'model.message',

  alertBinding : 'model.isAlert',

  successBinding : 'model.isSuccess',

  isEmpty : Ember.computed.empty('message'),

  didInsertElement : function(){
    if(this.get('isEmpty'))
      this.hide();
  },

  onMessageChange : function(){
    this.get('isEmpty') ? this.hide() : this.show();
  }.observes('message'),

  hide : function(){
    this.$().hide();
  },

  show : function(){
    this.$().show();
  },

  click : function(e){
    e.preventDefault();
    this.get('model').clear();
  }

});

Template

As well as the view object itself, we'll create the template, which simply renders the flash message. All foundation classes are taken care of by the view object.

<script type="text/x-handlebars" data-template-name="flash">
  {{view.message}}
</script>

Application

Now we'll write the glue code which uses the flash object (for the purposes of this demo only). We'll create an Ember application object, which acts as the namespace for everything app related. All views and models will be stored on this object.

App = Ember.Application.create();

Alongside the application object, we'll want to add a template, which renders the current route via the outlet and the flash view as part of the main app layout. The flash view binds the model to the global App.flash object (which we'll set later on).

<script type="text/x-handlebars">
  <h1>Flash Demo</h1>

  {{outlet}}

  {{view App.FlashView modelBinding=App.flash}}
</script>

Then we'll define an index view and route. The view defines action triggers which call actions within the route that change the state of the flash object.

<script type="text/x-handlebars" data-template-name="index">
  <button {{action setSuccess}} class='success'>Flash Success</button>
  <button {{action setAlert}} class='alert'>Flash Alert</button>
  <button {{action setCleared}} class=''>Clear Flash</button>
</script>
App.IndexRoute = Ember.Route.extend({

  actions : {

    setSuccess : function(){
      App.get('flash').success('This is a success message.');
    },

    setAlert : function(){
      App.get('flash').alert('This is an alert message!');
    },

    setCleared : function(){
      App.get('flash').clear();
    }

  }

});

Finally, we'll create an instance of the flash on the application (which is used in the application layout).

App.set('flash', App.FlashModel.create());

Summary

This demo reveals some of the power behind Ember. Computed properties and bound objects are concepts that really help keep your code concise and tidy. After using Ember for only 6 months, we can't imagine how we made large JavaScript apps without it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment