There are lots of ways to do this and some plugins out there (eg aexmachina’s ember-notify and poteto’s ember-cli-flash) but here is my take
Use a simple array controller to keep track of the current messages, a model to hold the message and what type of alert it is, a view with an action to remove the alert and a template to show it on the page.
The page needs a template containing the flash messages.
<script type="text/x-handlebars"> {{#each flashMessage in controllers.flash.content}} {{view "flash" contentBinding="flashMessage"}} {{/each}} </script>
It also needs a template for the flash message.
<script type='text/x-handlebars' id='flash'> {{#if flashMessage.isNotice}} <div class="alert notice"> {{flashMessage.message}} <button type="button" class="right" {{action "click" flashMessage target=view}}><span>×</span></button> </div> {{/if}} {{#if flashMessage.isSuccess}} <div class="alert success"> <button type="button" class="right" {{action "click" flashMessage target=view}}><span>×</span></button> {{flashMessage.message}} </div> {{/if}} {{#if flashMessage.isError}} <div class="alert error"> <button type="button" class="right" {{action "click" flashMessage target=view}}><span>×</span></button> {{flashMessage.message}} </div> {{/if}} </script>
We need a controller to keep track of all the flash messages
App.FlashController = Ember.ArrayController.extend({ createFlash: function(options) { if (options.type !== null && options.message !== null) { this.pushObject(this.get('store').createRecord( "flashMessage", { type: options.type, message: options.message } )); } } });
We also need model for a flash message.
App.FlashMessage = DS.Model.extend({ type: DS.attr('string'), message: DS.attr('string'), isNotice: function() { return this.get("type") === "notice"; }.property("type"), isSuccess: function() { return this.get("type") === "success"; }.property("type"), isError: function() { return this.get("type") === "error"; }.property("type") });
If a controller wants to create a flash message then it ‘needs’ the Flash controller. Here the Application controller creates a flash message in response to an action.
App.ApplicationController = Ember.Controller.extend({ needs: ['flash'], actions: { createFlashNotice: function() { this.get('controllers.flash').createFlash({ type: "notice", message: "I'm a flash notice." }); }, createFlashError: function() { this.get('controllers.flash').createFlash({ type: "error", message: "I'm a flash error." }); }, createFlashSuccess: function() { this.get('controllers.flash').createFlash({ type: "success", message: "I'm a flash success." }); } } });
We need a view for a flash messages which can remove it in response to a user action.
App.FlashView = Ember.View.extend({ templateName: 'flash', classNames: ['hide'], didInsertElement: function() { this.$().fadeIn(1000); }, actions: { click: function(alert) { this.get('controller').get( 'controllers.flash').removeObject( this.get('content')); this.destroy(); } } });
JS Bin example. Click on one of the buttons to create a flash message and remove it by clicking on the ‘x’.
Thanks to Eric Berry for the ‘flash’ of inspiration.