Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global Notifications View using Ember

Tags:

ember.js

I have a notification view responsible for displaying global messages at the top of the page (info, warning, confirmation messages ...)

I created a NotificationView for the purpose, defined its content property and provided two handlers to show and hide the view.

APP.NotificationView = Ember.View.extend({
    templateName: 'notification',
    classNames:['nNote'],
    content:null,

    didInsertElement : function(){                
    },

    click: function() {
        var _self = this;
        _self.$().fadeTo(200, 0.00, function(){ //fade
            _self.$().slideUp(200, function() { //slide up                    
                _self.$().remove(); //then remove from the DOM
            });
        });
       _self.destroy();
    },

    show: function() {
        var _self = this;
        _self.$().css('display','block').css('opacity', 0).slideDown('slow').animate(
            { opacity: 1 },
            { queue: false, duration: 'slow' }
        );          
    }
});

Ideally, i should be able to send an event from any controller or route to show the view with the proper content and styling. What would be the best way to architect this

I thought of using a named outlet in my application's template, however outlets are not quite suited for dynamic views.

<div id="content">
    {{outlet notification}}
    {{outlet}}
</div>

I was also thinking of architecting the notification view to be a response to "The application" or "A Module" state.

like image 766
ken Avatar asked Jan 12 '13 00:01

ken


1 Answers

Because you have animations you want to run when the notifications change, you will want to create a subclass of Ember.View (a "widget"):

App.NotificationView = Ember.View.extend({
  notificationDidChange: function() {
    if (this.get('notification') !== null) {
      this.$().slideDown();
    }
  }.observes('notification'),

  close: function() {
    this.$().slideUp().then(function() {
      self.set('notification', null);
    });
  },

  template: Ember.Handlebars.compile(
    "<button {{action 'close' target='view'}}>Close</button>" +
    "{{view.notification}}"
  )
});

This widget will expect to have a notification property. You can set it from your application template:

{{view App.NotificationView id="notifications" notificationBinding="notification"}}

This will gets its notification property from the ApplicationController, so we will create a couple of methods on the controller that other controllers can use to send notifications:

App.ApplicationController = Ember.Controller.extend({
  closeNotification: function() {
    this.set('notification', null);
  },

  notify: function(notification) {
    this.set('notification', notification);
  }
});

Now, let's say we want to create a notification every time we enter the dashboard route:

App.DashboardRoute = Ember.Route.extend({
  setupController: function() {
    var notification = "You have entered the dashboard";
    this.controllerFor('application').notify(notification);
  }
});

The view itself manages the DOM, while the application controller manages the notification property. You can see it all working at this JSBin.

Note that if all you wanted to do was display a notification, and didn't care about animations, you could just have done:

{{#if notification}}
  <div id="notification">
    <button {{action "closeNotification"}}>Close</button>
    <p id="notification">{{notification}}</p>
  </div>
{{/if}}

in your application template, with the same ApplicationController, and everything would just work.

like image 108
Yehuda Katz Avatar answered Nov 07 '22 05:11

Yehuda Katz