Why the `-init ajax` option has to be a 'plainobject' rather than just 'object'?
Why the `-init ajax` option has to be a 'plainobject' rather than just 'object'?

Description of problem:
I was trying to encapsulate the ajax
option into an ES6 class
like:
class MyAjaxOptions {
constructor(path, getParamsFunc, dataFilterFunc, dataSrcFunc){
this.#path += path
this.data = getParamsFunc
this.dataFilter = dataFilterFunc
this.dataSrc = dataSrcFunc
}
#path = '/my-prefix'
get url(){
return myHostname + this.#path
}
}
class MyDtOptionsWithAjax {
constructor(columns, ajaxOptions){
this.columns = columns
this.ajax = ajaxOptions
}
/** A bunch of my preferred init settings
* like searching, ordering...*/
}
function getMyDtParams(data) {
const params = {
test_id : $('#test-id').val(),
/**blah blah blah... */
}
return params
}
const testAjax = new MyAjaxOptions('/test/get/list', getMyDtParams, trivialHere, trivialHere2)
const testInitOptions = new MyDtOptionsWithAjax([{title:'test',data:'test_id'}], testAjax)
$('#example-table').DataTable(testInitOptions)
And it turns out the function ajax.data
is never called, but the DataTable did initialized. So the outer option object created by a class
i.e. a constructor function
did works.
I had no clue until I referred to DataTable's source code at line 48 was there a condition:
if ( $.isPlainObject( ajax ) && ajax.data )
and since my ajax
is neither created from an object literal {}
nor a new Object()
call, it fails the test and rejected out of the block that calls my ajax.data
if ( $.isPlainObject( ajax ) && ajax.data )
{
ajaxData = ajax.data;
var newData = typeof ajaxData === 'function' ?
ajaxData( data, oSettings ) : // fn can manipulate data or return
ajaxData; // an object object or array to merge
// If the function returned something, use that alone
data = typeof ajaxData === 'function' && newData ?
newData :
$.extend( true, data, newData );
// Remove the data property as we've resolved it already and don't want
// jQuery to do it again (it is restored at the end of the function)
delete ajax.data;
}
Will there be an adjustment of this condition or I have to use a plain object for ajax
?
This question has an accepted answers - jump to answer
Answers
And for the
url
property, it doesn't invoke thegetter
so I have to change my class into this to have the datatable send request to the right location.Alright, I solved my problem simply make a copy of my constructed
ajax
like this:Maybe I can do some research to see if I can submit a PR improving this.
Hi,
Thanks for posting up this - it an interesting thread you've started!
To a large extent the use of
plainObject
is legacy, but it is also in keeping with how the object is handled. For example, just a few lines on from that check we usejQuery.extend
to combine two objects. That doesn't work with a class instance:So even just removing that plain object check and looking for a general object wouldn't be enough of a change. I'd be happy with that if it were to work, but replacing
$.extend
would be more of an undertaking!Ideally we'd use
Object.assign()
, but we aim for long term backwards compatibility with DataTables, so that isn't an option. We could include a polyfill, but jQuery already gives us$.extend
and the library is a decent size already.So what to do? Honestly, I don't have a perfect answer. Currently, I think working with a plain object is probably easiest - unless you can see a way I'm missing?
Thanks,
Allan
Hi Allan,
Thanks a lot for your kind answer.
But there is one thing I have to figure out. That is the class instances actually work with
$.extend
. And in your case,$.extend
didn't work because there is a typo which should beconstructor()
other thanconstruction()
As my case shows
$.extend
overally works with class instances but they do their jobs in diffrent ways. So I agree it's a good idea to work with plainobjects.Thanks again