Manipulate ajax.dataSrc after the fact
Manipulate ajax.dataSrc after the fact
Pre-post update: I just managed to get DataTables to behave how I wanted. Keep reading.
For starters, I have found numerous examples of delay-loading ajax data by not setting the ajax/url property at the time of table initialization but instead calling the DataTable().ajax.url('/myApi/Url').load()
at a later time. What I don't understand is why can I not also manipulate the ajax.dataSrc
property in the same way? It seems in order to be able to do anything with that, it needs to be done at initialization. Which, if I initialize with my ajax.url
, the DataTable()
hits the server upon initialization (not desired).
In my testing, I am also unable to set the ajax.dataSrc
property upon initialization without setting the url
. BUT, as posted above, I can set the url
after the fact, and it will hit the server for data just fine. The crux of this issue basically boils down to this bit of logic inside jquery.datatables.js
:
var data = _fnAjaxDataSrc( settings, json );
which ultimately runs:
var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
oSettings.ajax.dataSrc :
oSettings.sAjaxDataProp; // Compatibility with 1.9-.
This all results in the following exception which, again, has been posted many times:
Uncaught TypeError: Cannot read properties of undefined (reading 'length')
at jquery.datatables.js:7734:29
And, whoa, look at that, I was just able to force it to do what I wanted by utilizing the deprecated sAjaxDataProp
value:
__Deprecated__ The functionality provided by this parameter has now been
superseded by that provided through `ajax`, which should be used instead.
By default DataTables will look for the property `data` (or `aaData` for
compatibility with DataTables 1.9-) when obtaining data from an Ajax
source or for server-side processing - this parameter allows that
property to be changed. You can use Javascript dotted object notation to
get a data source for multiple levels of nesting.
@type string
@default data
@dtopt Options
@dtopt Server-side
@name DataTable.defaults.ajaxDataProp
@deprecated 1.10. Please use `ajax` for this functionality now.
"sAjaxDataProp": "data",
I don't think the comment above is accurate: "By default DataTables will look for the property data
." In the event you want to delay-load data in this way, IT FORCES A JSON PROPERTY called "data", there is no default; it is hard-coded.
Frankly, I'd love to simply use the ajax property but it does not support this use-case. Given that this "deprecated" property actually makes the code function as desired, may I humbly ask that you implement/expose a way to modify the ajax.dataSrc property late just as you have implemented/exposed the ability to set ajax.url late?
A couple suggestions:
myTable.DataTable().ajax.url('/myApi/Url', '').load(); //where '' is dataSrc
OR something like:
myDataTable.ajax({url: '/myApi/Url', dataSrc: ''}).load();
I prefer the latter because it's more obvious what is happening versus the former empty-string parameter.
Any help would be greatly appreciated. While I have found a way for this code to work, with sAjaxDataProp flagged as deprecated, I'm afraid at some point this work-around will no longer work.
Answers
The comment about defaulting to "data" is correct above. It is specific to the deprecated property sAjaxDataProp.
And, I'm getting a "legacy interface notice." I am running jquery.datatables.js v1.10.18. Pretty sure that notice was flagged for the included comment from the codebase.
Yes, the legacy interface notice is purely a simple regex on the contents on the post here, checking for old parameter names and giving a warning if present (
sAjaxDataProp
specifically here).I don't recall any requests for an API to change
ajax.dataSrc
after init before, but I could be forgetting them. It can be provided as a function, so you can have complete control over it at any time, equallyajax
can also be provided as a function to give complete control over the data fetch action and then data manipulation before passing it to on to DataTables.ajax.dataSrc
does indeed default todata
.Allan
Thanks Allan. I'm not so much saying my exact request has happened before, but I did find many posts touching on this.
I think my primary thought here is why is
ajax.url
exposed to be manipulated in-line butajax.dataSrc
is not? They are inter-related.I will look at trying to set a function for the
ajax
property but I was having zero luck with anything on that side of things last night. The only way I was able to achieve what I wanted was by using the deprecated propertysAjaxDataProp
.I don't recall a case where the data property name in the JSON data feed changes. For example if you load JSON with the data array in a property called
data
, you wouldn't really expect it to change topeople
on a reload. Perhaps it could be used to switch to a different array in the JSON feed, but I just don't think that is very common, which is why there isn't an API for it.Can you give me a link to a page showing what you are doing with 1.x perhaps? I might be able to see a way to do it with 2.x.
Allan
It's not changing. I'm trying for 2 things:
ajax.url
at the time of initialization because I do not want the table fetching data off the bat.ajax.dataSrc
.I need
ajax.dataSrc = ''
. I cannot set that upon initialization without also settingajax.url
. And, if I do not set it upon initialization, it forcesajax.dataSrc = 'data'
because there is no way to manipulate it after the fact.I will see if I can whip up a working example somehow to illustrate what my exact use-case is.
The API returns a list of JSON objects, it does not return a JSON document with a
data
property with a value of an array of those JSON objects.I whipped this up. I couldn't think of a good way to actually execute an ajax call in the same way as my scenario so I just put some comments inside the block where that work is performed.
https://jsfiddle.net/dg9xe61v/
The ViewModel of this page returns the initial load of data, the HTML is rendered, and then the DataTable is initialized.
There is an AJAX-specific API which is used for AJAX-only interactions. in the jsfiddle above, the delete happens via AJAX and responds to the client that it succeeded or failed. If it succeeded, I need to call the AJAX-specific API to fetch the current data and reload/redraw the table.
If I set
ajax = { url: '/myApi/Url', dataSrc: ''}
when the table is initialized, it'll hit the server again for data the UI already has. And, I am not allowed to pre-populatedataSrc
without also setting theurl
. BUT, after reading through the code, I discovered I can do exactly that withsAjaxDataProp
.So, when you said:
That's not at all the scenario.
dataSrc
is a constant''
. I just want the ability to reload the DataTable through ajax calls but I also already have it's first load of data retrieved and do not want it to hit the server a second time upon initialization.Another approach could be a new property:
fetchDataUponInitialization
is a crummy property name but you get the gist. The whole reason I am using.ajax.url('/myApi/Url
).load()` is to circumvent the DataTable re-pulling data the View already has collected.Right - I think I understand now. Thanks for the clarification. If I understand correctly, you want something like this:
I've used a
setTimeout
to load the data, but really you could use anything? The key is thatajax.url
as an empty string means no data load?That actually had been my intention with DataTables 2, but it looks like there was an error for some conditions, such as this one. I've fixed that now and the nightly build has the fix.
You can see the result here: https://live.datatables.net/dodobuge/73/edit .
Allan
You, sir, are amazing. Thanks for listening and helping!
And whoa... just saw in the DataTables 2.0 release notes that
sAjaxDataProp
was indeed dropped so my above work-around would've stopped working upon updating (which is planned soon).Thanks again, Allan!