Benito Serna Tips and tools for Ruby on Rails developers

Less code in your javascript sprinkles with Stimulus.js

February 21, 2019

If you are thinking in trying Stimulus.js in your project, maybe this little “before and after” can help you to decide.

Today I was porting a small functionality to send some data to our analytics service from a “data-behavior” style of javascript sprinkles to Stimulus.js….

And I found very interesting that a lot of the code that we had to implement the feature was just to listen for the events and get the data from the html.

This was the previous code…

namespace = "project-item-track-click"
selectorFor = (name) -> "[data-behavior~='#{namespace}:#{name}']"
itemSelector = selectorFor("item")
containerSelector = selectorFor("container")

$items = ->
   $(item) for item in $(itemSelector)

$linksForItem = ($item) ->
   $(link) for link in $item.find("a")

getUserReferralCode = ->
  $container = $(containerSelector)
  $container.data("user-referral-code")

getRemainingDays = (targetDate) ->
  diff = moment(targetDate).diff(moment(), "days") + 1
  if diff > 0 then diff else 0

buildEventDataForItem = ($item) ->
  data = {}
  rawData = $item.data("for-event-tracking")
  data[key] = value for key, value of rawData when key isnt "target_date"
  data.remaining_days = getRemainingDays(rawData.target_date)
  data.user_referral_code = getUserReferralCode()
  data

initialize = ->
  for $item in $items()
    for $link in $linksForItem($item)
      analytics.trackLink($link[0],
        'Campaign Details Clicked',
         buildEventDataForItem($item))

$(document).on "ready page:load", initialize

You can like the code or not, but look how although “our logic” was almost just on the function buildEventDataForItem and getRemainingDays… It was needed to write some funky and custom code to initialize the behavior and get the needed data from the html.

This is now the code using Stimulus.js

import { Controller } from "stimulus"
import moment from "moment"

export default class extends Controller {
  connect() {
    let data = JSON.parse(this.data.get("eventData"));
    this.setRemainingDaysOn(data);
    this.setUserReferralCodeOn(data);
    analytics.trackLink(this.element, "Campaign Details Clicked", data);
  }

  setUserReferralCodeOn(data) {
    let code = document.body.dataset.userReferralCode;
    data.user_referral_code = code;
  }

  setRemainingDaysOn(data) {
    let targetDate = data.target_date;
    delete data.target_date
    data.remaining_days = this.remainingDays(targetDate)
  }

  remainingDays(targetDate) {
    let diff = moment(targetDate).diff(moment(), "days") + 1

    if (diff > 0) {
      return diff
    } else {
      return 0
    }
  }
}

Again, you can like the code or not, but look how now almost all the code here is related to “our logic”… Now Stimulus.js is giving us an easy and standard way to initialize the behavior and fetch the data from the html.

I think is a nice improvement, don’t you think?

Related articles

Weekly tips and tools for Ruby on Rails developers

I send an email each week, trying to share knowledge and fixes to common problems and struggles for ruby on rails developers, like How to fetch the latest-N-of-each record or How to test that an specific mail was sent or a Capybara cheatsheet. You can see more examples on Most recent posts or All post by topic.