Search code examples
jqueryruby-on-railsajaxturbolinks

Prevent Turbolinks from running after jQuery .load() Ajax event


I have a controller update action that essentially works in two parts. There's an initial create/update, then an after_action callback that goes back in and adds additional data to the record. This additional data is what needs to be readily available to Javascript.

For this reason, I'm not able to simply .append() the initially created object into the div since, at that initial "first pass" stage, it does not yet have the after_action data.

To get around this, I'm using a jQuery .load() action. This refreshes the div in question with the new content and the full object (with the additional data-attributes) is ready to go.

HOWEVER! What I'm noticing is that after the Ajax submission goes through, in the background the server is essentially processing a full page reload, re-rendering the full enchilada rather than stopping at just the div I pass into the .load() function.


How can I disable Turbolinks during/immediately after this process so it doesn't reload the entire page?


From the Turbolinks documentation, it seems data-turblinks="false" should do the trick, but I haven't had any luck so far.

Any idea where I'm going wrong? Anything else I should try?

Thank you in advance, let me know if there's any other code snippets you'd like to see!

.html.erb

<%= button_tag "", type: 'submit', class: "btn btn-lg btn-default glyphicon glyphicon-ok above-interaction-barrier",
id: "crop-submit-button-#{image.id}", data: { turbolinks: false, no_turbolink: true } do %>
  # Nesting a link_to just in case turbolinks requires it to be an actual link element (??)
  <%= link_to "", data: { turbolinks: false, no_turbolink: true} %>
<% end %>

controller

after_action :set_crop_attributes_for_crop_image, only: [:update, :create]

def set_crop_attributes_for_crop_image
  if image_params[:crop_x].present? && @crop_image.parent_image_id.present?
    @crop_image.crop_x = image_params[:crop_x]
    @crop_image.crop_y = image_params[:crop_y]
    @crop_image.crop_w = image_params[:crop_w]
    @crop_image.crop_h = image_params[:crop_h]
    @crop_image.save!
  end
end

.js

$('form').submit(function(event) {
  $(this)
    .off('ajax:beforeSend')
    .on('ajax:beforeSend', function() {
      $body.addClass('loading');
    });
  $(this)
    .off('ajax:success')
    .on('ajax:success', function() {
      cropperInstance.clear();
      // Show/Hide div under the radar so lazyloading plugin kicks in
      $('#selection-confirmation-highlights')
        .removeClass('above-interaction-barrier')
        .attr('z-index', '-500');
      $('#selection-confirmation-highlights').show();
      $('#selection-confirmation-highlights').hide();
      $('#selection-confirmation-highlights')
        .addClass('above-interaction-barrier')
        .removeAttr('z-index');
      $body.removeClass('loading');
    });
});

.js.erb

$('#selection-confirmation-highlights').load(location.href+" #selection-confirmation-highlights>*");

Solution

  • Okay, so it turns out my question was slightly misplaced. After a lot of reading/searching I learned that params are avaible in the .js.erb file. This is excellent!

    This let me bypass my initial Turbolinks/Ajax concerns altogether and go a much simpler route by using the .append() method. I basically ended up recreating the _image.html.erb output

    $('#selection-confirmation-highlights')
      .append("<div class= 'highlight'> <%= j image_tag @image.crops.last.file_url(:small_thumb),
              data: { imageid: @image.crops.last.id,
                      imagepath: image_path(@image.crops.last),
                      parentimageid: @image.crops.last.parent_image.id,
                      cropx: params[:image][:crop_x],
                      cropy: params[:image][:crop_y],
                      cropw: params[:image][:crop_w],
                      croph: params[:image][:crop_h] } %> " +
              // ...
       );
    

    This way, the Javascript/Ajax added images have the same data structure as those already loaded in with the page.

    In the controller, due to the way Carrierwave generates the resulting crop images, I still had to add the crop dimensions through the after_action callback I noted in my original post.