1

EDIT:

In addition to the helpful comments below, two excellent articles by Steve Schwartz explain everything clearly:

Rails 3.2.2 / jquery-rails 2.0.1 (uses jquery 1.7.1)

I have link which sends an AJAX request to add additional file upload fields to a form. Everything page-related works correctly - the new form field HTML fragment is retrieved from the server and appended to a div inside the form.

However,

The server receives two GET requests. One is the AJAX request ; the other appears to be the "normal" anchor element GET. I expected the "normal" GET would be stopped by Rails UJS.

Am I supposed to disable the normal link action myself? Can someone please explain what I have misunderstood, and what I should be doing instead [to prevent the second request]?

I've seen this question: Rails 3 UJS - controller gets called twice by link_to :remote. Accordingly, I tried changing the asset pipeline compilation config.assets.debug = false, but it had no effect. Moreover, this is not a double-AJAX GET request, so I think it's a different issue.

Thanks for any help!

Server log snippet:

Started GET "/files/new?asset_number=2" for 127.0.0.1 at 2012-03-23 15:23:27 +0100

Started GET "/files/new" for 127.0.0.1 at 2012-03-23 15:23:27 +0100

Browser HTML:

<a href="/files/new" data-remote="true" id="add_another_file" position="after" update="files">Add another file</a>

View:

<%= link_to 'Add another file', new_file_path, :remote   => true,
                                               :update   => 'files',
                                               :position => 'after',
                                               :id       => 'add_another_file' %>

Controller's coffeescript:

$( ->
  $('a#add_another_file').click( ->
    url = '/files/new?asset_number=' + $('#files input').length
    $.get(url, ((data) -> $('#files').append(data)), 'html')))
Community
  • 1
  • 1
Richard Michael
  • 1,540
  • 16
  • 19

3 Answers3

5

If you're adding a click event to a#add_another_file , then you don't need to use :remote => true , because you're making the Ajax request manually.

Also, the click event should prevent the default action from occurring. This can be accomplished by adding event.preventDefault(); to the beginning of the click event's callback. Note that the callback needs to accept the event argument.

nickh
  • 4,721
  • 2
  • 29
  • 31
  • I'm following along in Rails 3 In Action, which provided the code. I think using `:remote` would be the right way. If there should not be a manual `$.get()`, then I'm confused about how it works period, I'll investigate. And thanks for the event tip! – Richard Michael Mar 23 '12 at 15:47
  • this answer totally saved me, -> while using backbone events + jquery bind, browsers handled it OK, ie8 though didnt, because of what you explained. Great insight! – Sergey Sob May 26 '14 at 10:25
5

If you want to use the :remote => true option, you should remove the custom click event that you've added. This is because the :remote => true option tells the *jquery_ujs* library to hijack clicks on a#add_another_file. Thus, you needn't make your own HTTP request.

Next, to dictate what's done with the response, bind to the various events that will occur on a#add_another_file, such as success and error.

Here's the full list of Ajax events that you can bind to.

nickh
  • 4,721
  • 2
  • 29
  • 31
1

It's actually pretty simple, your remote link_to is sending one request (without params) and you've added a click event on that link to send another one (with params).

You should simplify your link_to as:

<%= link_to 'Add another file', new_file_path, :id => 'add_another_file' %>

Then in your click event you should return false so it doesn't follow the url.

It looks like you're using a lot of unnecessary parentheses in your coffeescript.

$ ->
  $('a#add_another_file').click ->
    url = '/files/new?asset_number=' + $('#files input').length
    $.get url, ((data) -> $('#files').append(data)), 'html'
James
  • 4,797
  • 25
  • 29
  • `event.preventDefault();` should be used instead of `return false;` . See this article for more info: http://fuelyourcoding.com/jquery-events-stop-misusing-return-false/ – nickh Mar 23 '12 at 15:34
  • As below, I'd like to do this with `:remote`. Thanks also for the coffeescript feedback, I'll clean up the style. – Richard Michael Mar 23 '12 at 15:53