Best practices of emitting events bound for a view


#1

We’ve been adding user notifications for asynchronous operation completes into our app lately. Mainly when the user clicks save/send/commit/etc, once we hear back from the server we pop up a little message informing the user it was successful. Here is an example, apparently “new users” can’t post images (seems useful?): http://i.imgur.com/lsY1ksu.png

Thus far, we’ve been using a few different “widgets” that will do the following:

App.ParticipantAddedNotification = Ember.View.extend({
  didInsertElement: function() {
    this.get('controller').on('participantAdded', this.show);
  },
  willDestroyElement: function() {
    this.get('controller').off('participantAdded', this.show);
  },
  show: function() {
    this.set('visible', true);
    Ember.run.later(this, function() {
      this.set('visible', false);
    }, 5000); 
  }
});

And of course our controllers then do the follow:

App.ManageParticipantsController = Ember.Controller.extend(Ember.Evented, {
  addParticipant: function() {
    var self = this;
    doAjax().then(function() {
      self.trigger('participantAdded');
  }
});

My question is, is this the right way to go about it? Any other alternatives?


Controller.get('view')? managing dom focus from controller events
#2

A slightly different approach could be using a combination of a controller, template and the render helper:

App.NotificationController = Ember.Controller.extend({
  message: "",

  hasMessage: function() {
    return !!this.get('message')     
  }.property('message'),

  messageDidChange: function() {
    var self = this; 
    if(this.get('message')) {
      Ember.run.later(function(){self.set('message', null);}, 5000);   
    }
  }.observes('message')   
   
});


App.ManageParticipantsController = Ember.Controller.extend(

  needs: ['notifications'],   
     
  addParticipant: function() { 
    var self = this; 
    doAjax().then(function() { 
      self.get('controllers.notifications').set('message', 'Participant added');
    });
  }
});

Then in your notification.handlebars

<div {{bindAttr class="hasMessage">
  {{message}}     
</div>

and include all this using the render helper in your main application template or wherever makes sense:

{{render 'notification'}}

Hopefully that’s all syntactically correct. You could extend this so that messages is an array and could respond appropriately based on the array changing.


#3

Hey – How about that. I didn’t even think of that. Thanks for the suggestion @robmonie!

I’d love to hear what others think about these two (or if they have a third option)


#4

Hey @workmanw

I’ve done something very similar to @robmonie, but as he indicated as a possibility, I wanted to be able to queue up my notifications (that may not necessarily all be the same). In my case, I included CSS animation on a notification element that lasted for 5 seconds so it would appear and disappear (and if another exists, immediately reappear). The template was bound to {{firstObject}}.

App.NotificationsController = Ember.ArrayController.extend({
  currentMessageDidChange : function() {
    if( this.get("firstObject") ) {

      Ember.run.later( this, function() {
        this.removeAt(0);
      }, 5000);

    }
  }.observes("firstObject")
});

App.ManageParticipantsController = Ember.Controller.extend({
  needs : ["notifications"],

  addParticipant : function() {
    var self = this;
    doAjax().then(function( message ) {
      self.get("controllers.notifications").pushObject( message );
    });
  }
});

#5

@Spencer_Price Thanks for sharing!

I slept on it last night and I was able to convince myself that your (and @robmonie’s) approach was more MVC proper than my initial approach. I think I’ll pursue this route.