0

Using Rails 5.2.4, coffee-rails 4.2, jquery-rails 4.4.0, jquery-ui-rails 6.0.1

I have some divs that users can drag around and resize, this functions beautifully. The catch is after they are done moving the object, I want to save the new value of where it is on the page based on percentages. I've got the math and everything worked out. The problem is submitting the data via a Rails.ajax call from my coffee script. Everything seems to send fine except the data that I define. Here's what I have in place:

<div class="selector ui-draggable ui-draggable-handle ui-resizable" style="position: absolute; width: 200px; height: 25px; top: 0; left: 0;" id="67745394-df31-4231-85b6-db0cff13c4ea" data-url="/documents/0a910275-5432-4c4e-a22d-dc1b4f70b958/versions/11095c90-087d-4723-ad9d-602f97b9954f/pages/82c4602b-0b7a-4238-a59f-f96bd5acb5df/form_fields/67745394-df31-4231-85b6-db0cff13c4ea">
   <div class="ui-resizable-handle ui-resizable-n" style="z-index: 90;"></div>
   <div class="ui-resizable-handle ui-resizable-e" style="z-index: 90;"></div>
   <div class="ui-resizable-handle ui-resizable-s" style="z-index: 90;"></div>
   <div class="ui-resizable-handle ui-resizable-w" style="z-index: 90;"></div>
   <div class="ui-resizable-handle ui-resizable-ne" style="z-index: 90;"></div>
   <div class="ui-resizable-handle ui-resizable-nw" style="z-index: 90;"></div>
   <div class="ui-resizable-handle ui-resizable-se ui-icon ui-icon-gripsmall-diagonal-se" style="z-index: 90;"></div>
   <div class="ui-resizable-handle ui-resizable-sw" style="z-index: 90;"></div>
</div>

This is the coffeescript that I am using to handle moving/resizing the divs, and then the function being called after the top events for each of those.

document.addEventListener 'turbolinks:load', ->
  $('.selector').draggable()
  $('.selector').resizable handles: 'n, e, s, w, ne, nw, se, sw'

  $('.selector').on 'resizestop', (event, ui) ->
    sizing($(this))
    return
  $('.selector').on 'dragstop', (event, ui) ->
    sizing($(this))
    return
  return

sizing = (div) ->
  oh = $('#form-layer').height()
  ow = $('#form-layer').width()
  height = (div.height() / oh * 100)
  width = (div.width() / ow * 100)
  left = (div.position().left / ow * 100)
  top = (div.position().top / oh * 100)
  Rails.ajax
    type: 'PATCH'
    dataType: 'script'
    accept: 'script'
    url: div.data('url')
    data:
      x: left
      y: top
      w: width
      h: height

The issue is that I'm not getting any of the data objects passed through into the controllers params, which come through as this:

{"controller"=>"form_fields", "action"=>"update", "document_id"=>"0a910275-5432-4c4e-a22d-dc1b4f70b958", "version_id"=>"11095c90-087d-4723-ad9d-602f97b9954f", "page_id"=>"82c4602b-0b7a-4238-a59f-f96bd5acb5df", "id"=>"67745394-df31-4231-85b6-db0cff13c4ea"}

I assume it has something to do with the formatting of the data block, but I've tried several different attempts but can't seem to find the right way to get any data. If I pass through the following I get some result, but nothing useful, anything I put after the hello is not passed.

...
    data:
      'hello'

I get

{"hello"=>nil, controller"=>"form_fields",...
mediarts
  • 1,511
  • 4
  • 18
  • 29
  • 1
    Rails UJS requires data formatted as string params. Check out the answer to this: https://stackoverflow.com/questions/45820587/how-do-you-send-json-data-in-a-rails-ujs-rails-ajax-post-call-not-using-jquery for suggestions. – rmlockerd Sep 10 '20 at 04:37
  • This was exactly the tip I was digging for and couldn't quite find with the key words I was using. Thanks so much for that! – mediarts Sep 10 '20 at 06:25
  • @rmlockerd thats not correct at all. Rack just can't process the request body of a application/javascript request. – max Sep 10 '20 at 09:33

1 Answers1

0

In order to send a request body that Rails (well technically Rack) can make sense of you need to use a Content-Type it can decode:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json

Rack just doesn't know what to do with application/javascript and thus won't parse the request body into the params hash.

Rails.ajax
    type: 'PATCH'
    dataType: 'json'
    accept: 'script'
    url: div.data('url')
    data:
      x: left
      y: top
      w: width
      h: height

Setting the Content-Type to application/json and the Accept to application/javascript tells the server you're sending JSON but you want javascript back.

max
  • 96,212
  • 14
  • 104
  • 165