ken
ken

Reputation: 3745

Global Notifications View using Ember

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.

Upvotes: 17

Views: 3214

Answers (2)

Elise Chant
Elise Chant

Reputation: 5196

I don't agree that Notifications should be a View, I think they should be a Component. Then they are also more flexible to be used across your application.

You could a Notification Component instead as answered here: How can I make an Alert Notifications component using Ember.js?

Upvotes: 0

Yehuda Katz
Yehuda Katz

Reputation: 28703

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.

Upvotes: 24

Related Questions