Richard Michael
Richard Michael

Reputation: 1624

Rails UJS link_to :remote does AJAX GET and normal <a href> GET

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')))

Upvotes: 1

Views: 4802

Answers (3)

nickh
nickh

Reputation: 4841

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.

Upvotes: 5

James
James

Reputation: 4807

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'

Upvotes: 1

nickh
nickh

Reputation: 4841

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.

Upvotes: 5

Related Questions