Skip to main content

Subscribe to GoRails to get access to this episode and all other pro episodes, and new awesome content every month.

Subscribe Now
Only $19/month

Unlimited access. Cancel anytime.

28 Common Features:

Improving In-App Notifications

Episode 124 · June 20, 2016

Learn how to refactor in-app notifications to render server side to simplify your code and templates

Notifications Javascript


Transcripts

Subscribe or login to view the transcript for this episode.

Discussion


Fallback

Fallback

Hey Chris great stuff. Can you please add the length of an episode somewhere.


Fallback

def like to see the action cable ep


Fallback

Fallback

I'd like to see the additional episode.

Also I'd love to be able to see how you have formatted the notification box. I'm struggling to increase the size of my notification box so it doesn't look anywhere near as presentable as yours do in the preview video.

Fallback

So those are just the normal dropdowns for Bootstrap, but I've added in some divs inside the elements instead of it just being one-liners and the following CSS:

.dropdown-menu .notification {
&.unread {
a {
border-left: 4px solid $red;
}
}

a {
padding: 10px 20px;
}

.avatar {
height: 24px;
margin-right: 10px;
width: 24px;
}
}

Fallback

Also, the ActionCable episode! Just posted it! https://gorails.com/episode...


Fallback

Great episode! I ran into a self-imposed quirk with this and I"m passing along the solution just in case anyone else runs into this. I was using a bootstrap badge to indicate the number of unread notifications. I had wanted it to behave similar to Facebook, where if there aren't any unread notifications then there won't be a badge (e.g., a badge with "0"). Here's how to make it work:

1. Change $("[data-behavior='unread-count']").text(0) to $("[data-behavior='unread-count']").text("")

2. Change $("[data-behavior='unread-count']").text(unread_count) to: $("[data-behavior='unread-count']").text(parseInt(unread_count) || "")

The change above slightly tweaks the functionality so that 'unread-count' isn't equal to "0", but is instead an empty string.

Hope this helps someone and saves them a couple of hours!

Source: most of the credit for this goes to http://stackoverflow.com/qu...


Fallback

nice Chris! Thank you!


Fallback

Chris thank you for the video - I'm a new developer so I just wanted to test the waters by cloning your source code and seeing if it will run in heroku. While the styling runs and I'm able able to post new threads > the notification system is not appearing. If you can help me out would be amazing

https://fathomless-bastion-...


Fallback

Great video Chris!


Fallback

Thank you Chris for a very interesting video. This Notification model works great for scenarios where notifications are created one at a time (actor to recipient action), or the way you use it with gorails.com to notify users a couple times per week. I would like to use this Notification model to notify users whenever (using this example) a new forum thread is created, or other actions are made among a group of users, thus being notified individually. Meaning every time a new forum thread is created, hundreds of users could potentially be notified, and this could grow very quickly if I want to add other actions to notify users. There is another approach making this kind of frequent multi-users notifications a public activity model https://github.com/chaps-io... but then you loose the individual read indicator or any individual metadata. Can you think of a way to keep the episode database structure for notifications, to scale it for a scenario of large notification creations?

Fallback

Really good question. The main tradeoff going that route is that while you might reduce the number of records at the beginning, you won't in the long run because you'll need to save the read timestamps for each of those users. You'll also complicate the initial query for notifications because you now have to search multiple tables (forum threads, episodes, etc) to figure out which ones you should notify the user about.

So if you're going to be creating those records anyways, why not just save them as a Notification record at the beginning? You can create them in a background job that will speed up creation of them at the beginning without overcomplicating your app just yet. Once you hit massive performance problems, you can optimize it then because you'll know exactly where the bottlenecks are. Trying to optimize before you know where the bottlenecks are is always where engineering problems tend to make things really tough.

Fallback

Thanks for your answer Chris. I agree with you, I will try to solve this issue once and if I face it!


Fallback

I've followed your video and able to now create notifications on all my controllers but the conversation and messages controllers not able to. cant really find the recipient in the case of mailboxer messages and conversations? also do i create both notifications for a new conversation and new message? can you help with creating notification for messages and conversations? thanks


Fallback

Great episode Chris, newbie question here.

I adapted it to the app I'm currently working on, and works like a charm in localhost but in production (Heroku) the mark_as_read method gets only triggered after I do a hard refresh of the browser, otherwise the notifications remain as read: false even if I hit the link a hundred times. Might be an issue with turbolinks?

I read something in the slack channel about how the javascript should be running on turbolinks:load event instead of the dom content ready, but I'm not sure about how to do this. I could try just to remove turbolinks from the app but I would be losing a lot of speed. Any thoughts?

Fallback

Hey Ernesto, yeah it sounds like the JS is running on document ready, but not turbolinks load (which is run every single time you visit another page since turbolinks fakes those second page requests).

This is the case from the example because of this code:

jQuery ->
new Notifications

The jQuery -> is a function for saying when the document is ready, then run this code.

If you change it to this it will work on every turbolinks page:

$(document).on 'turbolinks:load', ->
new Notifications

Fallback
Hello Chris 

Great episode, everything works fine thank you. Except I want to call: 
 getNewNotification()
once upon page refresh and then only have the time interval implemented: 

if @notifications.length > 0
   @handleSuccess @notifications.data("notifications")
   $("[data-behavior='notifications-link']").on "click", @handleClick
  
    # Call the function once here 

    setInterval (=>
      @getNewNotifications()
     ), 15000
this is so that the user wouldn't have to wait 15 seconds for their notification/s to appear. I know the alternative would be to decrease the time interval but I think that it would be computationally costly in the long run. 

There is a helper function written by David Walsh I found to be interesting: 

function once(fn, context) { 
  var result;

  return function() { 
    if(fn) {
      result = fn.apply(context || this, arguments); 
      fn = null;
     }

     return result;
  };
}
I don't know if I should use it with a self invoking function or how to really implement it efficiently.
Thank you for your help.
Fallback

Hey Thato,

You can simply just call that function on the turbolinks:load event (or DOMContentLoaded if you aren't using Turbolinks).

It's as simple as doing something like this:

document.addEventListener("turbolinks:load", function() {
getNewNotification()

})
Fallback
It never crossed my mind, thank you very much Chris.

Fallback
I've just implemented this on my app and it's seems to work okay, I have a question around the interaction part. 

Currently when I click on the notification bell icon it marks all the new notifications as read. I have changed the UI to display the dropdown on hover, I can't quite work out how to mark only the notification you have clicked on as marked as read. 

ie. If you have 3 new notifications, I hover over the bell icon and I click on the 2nd notification in the dropdown, does anyone know how to make just the 2nd notifications show as read and notifications 1 and 3 remain unread the next time I hover over the bell icon?

Fallback
 Hello! Thanks for this tutorial... However, I've implemented the old in-app navbar notification system on my rails 5.1.3 app with no problem but when I tried improving it according to your tutorial, everything works well except that the /notifications.json keeps loading in my CMD without loading another page and it won't stop. 

Login or create an account to join the conversation.