Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Support for ajaxSetup data #259

Open
ReubenM opened this Issue · 10 comments

2 participants

@ReubenM

jQuery's ajaxSetup offers the ability to set up default data objects to be appended to all ajax requests made. (and to not overwrite key value pairs with the same key name that are set locally)

While working on a personal project that make heavy use of XHR, I found that elements who's ajax functionality was set through jQuery included the default data, while those generated by rails using methods like form_for and link_to with ":remote => true" did not.

The workaround for this for my situation was going to be quite gross, so I hacked the functionality into the jquery_ujs handleRemote.

I'm including a link to a patch rather than an actual pull request since I'm not sure if this is the best solution, or if it might break other functionality elsewhere. But please consider adding the functional equivalent of this patch to UJS.

Patch: http://pastebin.com/1Tjw7nh4

@ReubenM

Realized that when I was checking to see if the key had been set locally, is was checking both key and value match rather than just to see if the key was defined.

Updated Patch: http://pastebin.com/8gqAexqT

@ReubenM

One more small change to fix the chance of a false positives when checking for keys that have been serialized into a string. (I'm not familiar with what type of element triggers the code path dealing with rails.inputChangeSelector, so that chunck of code isn't very well tested)

Update: http://pastebin.com/F1ibyLwF

@ReubenM

Ugh. More fixes. (check if ajaxSetup data is defined)

Hopefully last update: http://pastebin.com/SBS6UeeG

@JangoSteve
Collaborator

I appreciate the efforts, but it's a lot of code, and I don't fully understand why it's necessary. The $.rails.ajax method simply calls jQuery's $.ajax method, so the defaults in $.ajaxSettings should already be used. In fact, jquery-ujs even adds a $.ajaxPrefilter, so I know that's being used in the ajax requests.

It seems like your issue is that you add something to the data parameter in ajaxSetup, but then it's totally overridden with remote forms, because jquery-ujs sets the data parameter from the form data. However, jquery-ujs actually is not overriding your default data, it's only setting the data parameter on the ajax request; it is jQuery that has decided that this should override the data parameter rather than appending to it. According to the jQuery docs for $.ajaxSetup:

All subsequent Ajax calls using any function will use the new settings, unless overridden by the individual calls, until the next invocation of $.ajaxSetup().

So, this is jQuery's intended functionality, which means I don't think your patch is correct behavior.

However, I do think you're on to something. Notice that jquery-ujs only adds the url parameter to the request object if it's present. This is because, jQuery has some default magic it works on the url parameter of an ajax request if it's not there, but if you set the value to null, jQuery still considers that a value (most likely checking just for undefined), and so it doesn't perform it's magic.

I think the same might be happening here with the data parameter. I'll need to look at it a bit more, but perhaps we should make sure that data is undefined rather than null when there are no data parameters to send with the specific request, and that would probably ensure that the data from $.ajaxSetup is used in that scenario.

@ReubenM

I have an app I'm building that interacts with the server using only XHR calls after the initial page load. I'm wanting to use

$.ajaxSetup({
data: {
foo: <%= @bar %>
}
});

in my XHR responses as a means of tracking some stateful data that need to be included with each request. This is working for all XHR requests that are called directly using jQuery ajax calls, however XHR requests create procedurally from remote form_for and similar methods do not include these pieces of data.

Maybe I misunderstand the documentation, but I am under the impression that what is supposed to happen is that when collecting the data to be sent in an ajax call, that the data key-value pairs defined in ajaxSetup would be the data template to start with, with any data set in the ajax call parameters to be appended to that template, and overwrite any of the default values in the template if they are defined in the local ajax call.

So the patch goes about it a bit backwards and appends ajaxSetup.data element to the local data, but checks first to make sure the keys are not already defined in the local ajax call.

The better solution would be to set the local data as an instance of ajaxSetup.data and then mask it with the serialized data from the form. (My javascript foo is not to the level yet where I've figured out how to take one array and mask over it with a second array that clobbers any duplicates in the first array without iterating over the arrays and comparing values. If there is a quick and dirty one-liner way to do that I'd love to learn how)

Hope that make more sense what I'm trying to do. Basically I'm working from the idea that ajaxSetup defines all your defaults for ajax calls that can then be appended to or overridden.

Thanks for looking into this. Much appreciated.

@ReubenM

Oh, and almost forgot, that I was also under the impression that the jquery documentation you referenced meant that individual key-value pairs would be "overridden by the individual calls", not the whole data object/array itself. Perhaps the documentation is a bit ambiguous as to what exactly is getting overwritten.

@JangoSteve
Collaborator

Like I said, jquery-ujs isn't doing anything different or special with the data attribute, so whatever you're describing is happening in jquery, not in jquery-ujs. However, if jquery is treating it differently because of jquery-ujs sending null data when no data- parameter is specified, instead of undefined, then that's something we could fix.

@ReubenM

I guess I don't understand how that would apply to this situation where the data parameter is defined, both in ajaxSetup, and for the form data.

@JangoSteve
Collaborator

Ah, I wasn't clear that was the case here. I'll look into it.

@ReubenM

I've created a small demo app to demonstrate the problem. Hopefully that will be better for showing exactly what I'm talking about.

https://dl.dropbox.com/u/38727164/databug.tar.gz (~35k)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.