Search code examples
javascriptjqueryruby-on-railsturbolinks

Turbolinks - Showing datetimepicker only on Scheduled posts - hidden by default


I'm having a _form partial in oorder to create/edit posts. This form has a dropdown for setting the post status, so if the user sets the status as Scheduled then the datetimepicker shows up in order to select a date, otherwise this is should be hidden by default (ie when status is "Draft" or "Published").

# app/views/posts/_form.html.haml
= simple_form_for ["admin", @post] do |f|

  = f.input :title

  = f.input :status, collection: ["Draft", "Published", "Scheduled"], selected: status_for(@post)

  .published-field
    = f.input :published_at, as: :date_time_picker

...

# app/helpers/posts_helper.rb
module PostsHelper
  def status_for(post)
    if post.published_at?
      if post.published_at > Time.zone.now
        "Scheduled"
      else
        "Published"
      end
    else
      "Draft"
    end
  end
end

# app/assets/javascripts/posts.coffee
changeVisibility = (status) ->
  if status == "Scheduled"
    $(".published-field").show()
  else
    $(".published-field").hide()

jQuery ->
  changeVisibility $("#post_status :selected").text()
  $("#post_status").on "change", (e) ->
changeVisibility $(this).find(":selected").text()

The problem comes when user access the page for the first time, so the status is set to Draft by default (as expected), however the datetimepicker is visible which isn't supposed to (remeber? this should be visible only if user selects to schedule the post). If you refresh the page at this point when vieweing the fomr, then the datepicker disapears.

The original issue can also be found here https://gorails.com/episodes/scheduling-posts

This issue is probably caused because of turbolinks. I have also tried to use the jquery-turbolinks gem, but didn't manage to solve the problem. Any ideas how to fix this issue?


Solution

  • If you want to use Turbolinks, its important to remember that it works by not having real page loads at all, it just does an XHR request then replaces the HTML within <body>, while saving the old <body> to implement the back button.

    This means no scripts will get executed, you wont get any document load/ready events, etc. $(handler) is the same as $.ready(handler) and is only run on page load once "page's Document Object Model (DOM) becomes safe to manipulate.".

    Turbolinks fires turbolinks:load on document, so use $(document).on('turbolinks:load', handler) for all such things.

    You also need to be aware of the fact it kept a copy of your old <body> DOM and anything scripts did, so any memory used by that, and any other JavaScript from the last "page" such as timeouts and animation frames, etc. keeps running. And you used it to implement the show/hide based on the CSS selector at load time.

    This Rails guide has more information, as well as the Turbolinks library itself.