Using ajax in a callback where the parent process itself relies on an ajax call











up vote
5
down vote

favorite












I'm working with an application that uses DataTables to generate a HTML table which is populated by data from an ajax request.



This is fairly simple:



var substancesTable = $('#substancesTable').DataTable({
"processing": true,
"serverSide": true,
"searching": false,
"ajax": {
"url": "/get-substances.json",
"method": "POST",
"cache": false,
"dataSrc": function (json) {

// Update non-Datatables UI elements and perform other functions based on the ajax response
$('#numSubstances').html(json.recordsTotal);
drawOptionsButton(json.isFiltering);

// Must return data for DataTables to work
return json.data;
}
},
// ...
});


There is a callback which DataTables provides, called rowCallback (https://datatables.net/reference/option/rowCallback) which allows post processing of table rows after the table has been drawn. The key thing here is that it's after the ajax request to /get-substances.json; the table must be populated with data because this callback is used to manipulate data within it at that point.



Within rowCallback I'm providing an array of row ID's in my table - that is to say ID's which correspond to <tr> elements inside #substancesTable - and I go on to expand these rows. I can do this manually by hardcoding in an array of row ID's, e.g.



 var substancesTable = $('#substancesTable').DataTable({
// ...
"rowCallback": function(row) {
var id = $(row).find('td:first').text();
var index = $.inArray(id, ['4', '7']); // hardcoded array

if (index !== -1) {
var tr = $(row).closest('tr');
var row = substancesTable.row( tr );
row.child.show();
tr.addClass('active');
}
});


The array I've hardcoded means rows 4 and 7 are expanded after the table has been populated, which is equivalent to the user clicking on them.



The problem I have is that I don't want to hardcode the array. The application stores the equivalent of var index in Redis (cache) meaning that we can grab the data easily even if the user leaves the page. So I have added a second ajax request (outside the var substancesTable... block) to obtain the Redis data. This makes an ajax request to populate an array, activeRows:



var activeRows = ;
$.ajax({
url: '/view-substance/get-active-rows',
method: 'post',
cache: false,
}).done(function(data) {
activeRows = data;
console.log(activeRows);
});


I understand that the nature of ajax means my code is asynchronous. In some cases the ajax request shown above will complete before the DataTable is drawn, so I get the console.log(activeRows) appearing before the table is rendered, and in other cases it happens afterwards.



What is the correct way to make this second ajax request such that the values from it can be used in place of the hardcoded array? I appreciate I will need to convert the response to an array (since it's still JSON in the console.log statement). But my question is focused on where to put this code such that it can be used reliably inside rowCallback?



I have read How do I return the response from an asynchronous call? and understand about the async nature. I can't work out how to structure this to be used in a callback that's already part of an ajax request.



Any advice would be appreciated.



The application uses DataTables version 1.10.16 and jquery 3.2.1










share|improve this question
























  • You can call var substancesTable = ... block with in done callback of '/view-substance/get-active-rows' ajax request.
    – Chinmoy Samanta
    Nov 12 at 10:26















up vote
5
down vote

favorite












I'm working with an application that uses DataTables to generate a HTML table which is populated by data from an ajax request.



This is fairly simple:



var substancesTable = $('#substancesTable').DataTable({
"processing": true,
"serverSide": true,
"searching": false,
"ajax": {
"url": "/get-substances.json",
"method": "POST",
"cache": false,
"dataSrc": function (json) {

// Update non-Datatables UI elements and perform other functions based on the ajax response
$('#numSubstances').html(json.recordsTotal);
drawOptionsButton(json.isFiltering);

// Must return data for DataTables to work
return json.data;
}
},
// ...
});


There is a callback which DataTables provides, called rowCallback (https://datatables.net/reference/option/rowCallback) which allows post processing of table rows after the table has been drawn. The key thing here is that it's after the ajax request to /get-substances.json; the table must be populated with data because this callback is used to manipulate data within it at that point.



Within rowCallback I'm providing an array of row ID's in my table - that is to say ID's which correspond to <tr> elements inside #substancesTable - and I go on to expand these rows. I can do this manually by hardcoding in an array of row ID's, e.g.



 var substancesTable = $('#substancesTable').DataTable({
// ...
"rowCallback": function(row) {
var id = $(row).find('td:first').text();
var index = $.inArray(id, ['4', '7']); // hardcoded array

if (index !== -1) {
var tr = $(row).closest('tr');
var row = substancesTable.row( tr );
row.child.show();
tr.addClass('active');
}
});


The array I've hardcoded means rows 4 and 7 are expanded after the table has been populated, which is equivalent to the user clicking on them.



The problem I have is that I don't want to hardcode the array. The application stores the equivalent of var index in Redis (cache) meaning that we can grab the data easily even if the user leaves the page. So I have added a second ajax request (outside the var substancesTable... block) to obtain the Redis data. This makes an ajax request to populate an array, activeRows:



var activeRows = ;
$.ajax({
url: '/view-substance/get-active-rows',
method: 'post',
cache: false,
}).done(function(data) {
activeRows = data;
console.log(activeRows);
});


I understand that the nature of ajax means my code is asynchronous. In some cases the ajax request shown above will complete before the DataTable is drawn, so I get the console.log(activeRows) appearing before the table is rendered, and in other cases it happens afterwards.



What is the correct way to make this second ajax request such that the values from it can be used in place of the hardcoded array? I appreciate I will need to convert the response to an array (since it's still JSON in the console.log statement). But my question is focused on where to put this code such that it can be used reliably inside rowCallback?



I have read How do I return the response from an asynchronous call? and understand about the async nature. I can't work out how to structure this to be used in a callback that's already part of an ajax request.



Any advice would be appreciated.



The application uses DataTables version 1.10.16 and jquery 3.2.1










share|improve this question
























  • You can call var substancesTable = ... block with in done callback of '/view-substance/get-active-rows' ajax request.
    – Chinmoy Samanta
    Nov 12 at 10:26













up vote
5
down vote

favorite









up vote
5
down vote

favorite











I'm working with an application that uses DataTables to generate a HTML table which is populated by data from an ajax request.



This is fairly simple:



var substancesTable = $('#substancesTable').DataTable({
"processing": true,
"serverSide": true,
"searching": false,
"ajax": {
"url": "/get-substances.json",
"method": "POST",
"cache": false,
"dataSrc": function (json) {

// Update non-Datatables UI elements and perform other functions based on the ajax response
$('#numSubstances').html(json.recordsTotal);
drawOptionsButton(json.isFiltering);

// Must return data for DataTables to work
return json.data;
}
},
// ...
});


There is a callback which DataTables provides, called rowCallback (https://datatables.net/reference/option/rowCallback) which allows post processing of table rows after the table has been drawn. The key thing here is that it's after the ajax request to /get-substances.json; the table must be populated with data because this callback is used to manipulate data within it at that point.



Within rowCallback I'm providing an array of row ID's in my table - that is to say ID's which correspond to <tr> elements inside #substancesTable - and I go on to expand these rows. I can do this manually by hardcoding in an array of row ID's, e.g.



 var substancesTable = $('#substancesTable').DataTable({
// ...
"rowCallback": function(row) {
var id = $(row).find('td:first').text();
var index = $.inArray(id, ['4', '7']); // hardcoded array

if (index !== -1) {
var tr = $(row).closest('tr');
var row = substancesTable.row( tr );
row.child.show();
tr.addClass('active');
}
});


The array I've hardcoded means rows 4 and 7 are expanded after the table has been populated, which is equivalent to the user clicking on them.



The problem I have is that I don't want to hardcode the array. The application stores the equivalent of var index in Redis (cache) meaning that we can grab the data easily even if the user leaves the page. So I have added a second ajax request (outside the var substancesTable... block) to obtain the Redis data. This makes an ajax request to populate an array, activeRows:



var activeRows = ;
$.ajax({
url: '/view-substance/get-active-rows',
method: 'post',
cache: false,
}).done(function(data) {
activeRows = data;
console.log(activeRows);
});


I understand that the nature of ajax means my code is asynchronous. In some cases the ajax request shown above will complete before the DataTable is drawn, so I get the console.log(activeRows) appearing before the table is rendered, and in other cases it happens afterwards.



What is the correct way to make this second ajax request such that the values from it can be used in place of the hardcoded array? I appreciate I will need to convert the response to an array (since it's still JSON in the console.log statement). But my question is focused on where to put this code such that it can be used reliably inside rowCallback?



I have read How do I return the response from an asynchronous call? and understand about the async nature. I can't work out how to structure this to be used in a callback that's already part of an ajax request.



Any advice would be appreciated.



The application uses DataTables version 1.10.16 and jquery 3.2.1










share|improve this question















I'm working with an application that uses DataTables to generate a HTML table which is populated by data from an ajax request.



This is fairly simple:



var substancesTable = $('#substancesTable').DataTable({
"processing": true,
"serverSide": true,
"searching": false,
"ajax": {
"url": "/get-substances.json",
"method": "POST",
"cache": false,
"dataSrc": function (json) {

// Update non-Datatables UI elements and perform other functions based on the ajax response
$('#numSubstances').html(json.recordsTotal);
drawOptionsButton(json.isFiltering);

// Must return data for DataTables to work
return json.data;
}
},
// ...
});


There is a callback which DataTables provides, called rowCallback (https://datatables.net/reference/option/rowCallback) which allows post processing of table rows after the table has been drawn. The key thing here is that it's after the ajax request to /get-substances.json; the table must be populated with data because this callback is used to manipulate data within it at that point.



Within rowCallback I'm providing an array of row ID's in my table - that is to say ID's which correspond to <tr> elements inside #substancesTable - and I go on to expand these rows. I can do this manually by hardcoding in an array of row ID's, e.g.



 var substancesTable = $('#substancesTable').DataTable({
// ...
"rowCallback": function(row) {
var id = $(row).find('td:first').text();
var index = $.inArray(id, ['4', '7']); // hardcoded array

if (index !== -1) {
var tr = $(row).closest('tr');
var row = substancesTable.row( tr );
row.child.show();
tr.addClass('active');
}
});


The array I've hardcoded means rows 4 and 7 are expanded after the table has been populated, which is equivalent to the user clicking on them.



The problem I have is that I don't want to hardcode the array. The application stores the equivalent of var index in Redis (cache) meaning that we can grab the data easily even if the user leaves the page. So I have added a second ajax request (outside the var substancesTable... block) to obtain the Redis data. This makes an ajax request to populate an array, activeRows:



var activeRows = ;
$.ajax({
url: '/view-substance/get-active-rows',
method: 'post',
cache: false,
}).done(function(data) {
activeRows = data;
console.log(activeRows);
});


I understand that the nature of ajax means my code is asynchronous. In some cases the ajax request shown above will complete before the DataTable is drawn, so I get the console.log(activeRows) appearing before the table is rendered, and in other cases it happens afterwards.



What is the correct way to make this second ajax request such that the values from it can be used in place of the hardcoded array? I appreciate I will need to convert the response to an array (since it's still JSON in the console.log statement). But my question is focused on where to put this code such that it can be used reliably inside rowCallback?



I have read How do I return the response from an asynchronous call? and understand about the async nature. I can't work out how to structure this to be used in a callback that's already part of an ajax request.



Any advice would be appreciated.



The application uses DataTables version 1.10.16 and jquery 3.2.1







javascript jquery ajax






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago

























asked Nov 8 at 10:47









Andy

2,1491840




2,1491840












  • You can call var substancesTable = ... block with in done callback of '/view-substance/get-active-rows' ajax request.
    – Chinmoy Samanta
    Nov 12 at 10:26


















  • You can call var substancesTable = ... block with in done callback of '/view-substance/get-active-rows' ajax request.
    – Chinmoy Samanta
    Nov 12 at 10:26
















You can call var substancesTable = ... block with in done callback of '/view-substance/get-active-rows' ajax request.
– Chinmoy Samanta
Nov 12 at 10:26




You can call var substancesTable = ... block with in done callback of '/view-substance/get-active-rows' ajax request.
– Chinmoy Samanta
Nov 12 at 10:26












2 Answers
2






active

oldest

votes

















up vote
3
down vote



accepted
+50










You can actually use the ajax option to:




  1. Make the first AJAX request which retrieves the active rows.


  2. Once the active rows are retrieved, make the second AJAX request which retrieves the table data.



Example: (see full code and demo here)



var activeRows = ;

function getActiveRows() {
return $.ajax({
url: '/view-substance/get-active-rows',
type: 'POST',
dataType: 'json'
...
}).done(function(data){
activeRows = data;
console.log(activeRows);
});
}

function getTableData(data, callback) {
return $.ajax({
url: '/get-substances.json',
type: 'POST',
dataType: 'json',
'data': data // must send the `data`, but can be extended using $.extend()
...
}).done(callback); // and call callback() once we've retrieved the table data
}

$('#example').dataTable({
ajax: function(data, callback){
getActiveRows().always(function(){
getTableData(data, callback);
});
},
rowCallback: function(row, data){
...
}
});


UPDATE



In the above example, I separated the AJAX calls into two different functions mainly to avoid long indentation in the ajax option when you call the $('#example').dataTable(). The code would otherwise look like:



var activeRows = ;

$('#example').dataTable({
ajax: function(data, callback){
// 1. Retrieve the active rows.
$.ajax({
url: '/view-substance/get-active-rows',
type: 'POST',
dataType: 'json'
...
}).done(function(res){
activeRows = res;
console.log(activeRows);
}).always(function(){
// 2. Retrieve the table data.
$.ajax({
url: '/get-substances.json',
type: 'POST',
dataType: 'json',
'data': data // must send the `data`, but can be extended using $.extend()
...
}).done(callback); // and call callback() once we've retrieved the table data
});
},
rowCallback: function(row, data){
...
}
});


I used the .always() so that the table data would still be retrieved in case of failures in retrieving the active rows.






share|improve this answer























  • This looks good. Please can you add some information about how it works, particularly the code inside the $('#example').dataTable({ block which references the other functions? I'm trying to understand the flow of this so I can use the same principles in other parts of my application. Thanks in advance.
    – Andy
    Nov 13 at 15:17










  • I updated the answer.. if you still need clarification, let me know. I've also updated the demo, but it still uses the functions.
    – Sally CJ
    Nov 13 at 15:46










  • this is brilliant and works really well. Only question is that I was performing some other tasks during the ajax callback to /get-substances.json. I've updated the original question - see the comment that starts // Update non-Datatables UI elements. Here I'm writing to a div with the ID #numSubstances the number of records returned from the JSON data and running another custom function called drawOptionsButton(). I don't know where this fits in to the code you've provided. Please can you explain? I guess it's somewhere near .done(callback) but not sure where to go from here. Thanks.
    – Andy
    2 days ago












  • .done(callback) is really a shortcut for .done( function( data ){ callback( data ); } ). So (I think) you could just add that $('#numSubstances').html(json.recordsTotal); and drawOptionsButton(json.isFiltering); in that done function - after the callback( data ) part. Alternatively, you can also "save" those two properties (recordsTotal and isFiltering) just as with the activeRows variable - e.g. var activeRows = , recordsTotal = 0, isFiltering;, and then access/use them from a function hooked to a DataTables event such as draw or preDraw.
    – Sally CJ
    2 days ago


















up vote
1
down vote













You could solve your problem with Promises. Promises are objects that help you manage and coordinate asynchronous tasks. Your case would look something like this:



var activeRows = ;
var substancesTable = $('#substancesTable').DataTable({
// ...
});

var pDataTable = new Promise(function(resolve, reject){
// you wan't to resolve just once,
// after the table has finished processing the received data.
// (You may want to change draw to an event that's more suitable)
substancesTable.one('draw', resolve);
});

var pOpenRows = new Promise(function( resolve, reject ){

$.ajax({
url: '/view-substance/get-active-rows',
method: 'post',
cache: false,
}).done(function(data) {
// you can either save your rows globaly or give them to the resolve function
// you don't have to do both
activeRows = data;
resolve( data );
});

});

// Here we basically create a third promise, which resolves (or rejects)
// automatically based on the promises in the array.
Promise.all([pDataTable, pOpenRows])
.then(function( values ){
// expand your table rows here
// Note: if you gave your rows to the resolve function you can access
// them here in values[1] (pDataTable's data would be in values[0])
});


In case you want to learn more about Promises:




  • https://developers.google.com/web/fundamentals/primers/promises

  • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

  • https://scotch.io/tutorials/javascript-promises-for-dummies


For details on browser support you may look here:





  • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

  • https://caniuse.com/#search=Promise






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53206138%2fusing-ajax-in-a-callback-where-the-parent-process-itself-relies-on-an-ajax-call%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote



    accepted
    +50










    You can actually use the ajax option to:




    1. Make the first AJAX request which retrieves the active rows.


    2. Once the active rows are retrieved, make the second AJAX request which retrieves the table data.



    Example: (see full code and demo here)



    var activeRows = ;

    function getActiveRows() {
    return $.ajax({
    url: '/view-substance/get-active-rows',
    type: 'POST',
    dataType: 'json'
    ...
    }).done(function(data){
    activeRows = data;
    console.log(activeRows);
    });
    }

    function getTableData(data, callback) {
    return $.ajax({
    url: '/get-substances.json',
    type: 'POST',
    dataType: 'json',
    'data': data // must send the `data`, but can be extended using $.extend()
    ...
    }).done(callback); // and call callback() once we've retrieved the table data
    }

    $('#example').dataTable({
    ajax: function(data, callback){
    getActiveRows().always(function(){
    getTableData(data, callback);
    });
    },
    rowCallback: function(row, data){
    ...
    }
    });


    UPDATE



    In the above example, I separated the AJAX calls into two different functions mainly to avoid long indentation in the ajax option when you call the $('#example').dataTable(). The code would otherwise look like:



    var activeRows = ;

    $('#example').dataTable({
    ajax: function(data, callback){
    // 1. Retrieve the active rows.
    $.ajax({
    url: '/view-substance/get-active-rows',
    type: 'POST',
    dataType: 'json'
    ...
    }).done(function(res){
    activeRows = res;
    console.log(activeRows);
    }).always(function(){
    // 2. Retrieve the table data.
    $.ajax({
    url: '/get-substances.json',
    type: 'POST',
    dataType: 'json',
    'data': data // must send the `data`, but can be extended using $.extend()
    ...
    }).done(callback); // and call callback() once we've retrieved the table data
    });
    },
    rowCallback: function(row, data){
    ...
    }
    });


    I used the .always() so that the table data would still be retrieved in case of failures in retrieving the active rows.






    share|improve this answer























    • This looks good. Please can you add some information about how it works, particularly the code inside the $('#example').dataTable({ block which references the other functions? I'm trying to understand the flow of this so I can use the same principles in other parts of my application. Thanks in advance.
      – Andy
      Nov 13 at 15:17










    • I updated the answer.. if you still need clarification, let me know. I've also updated the demo, but it still uses the functions.
      – Sally CJ
      Nov 13 at 15:46










    • this is brilliant and works really well. Only question is that I was performing some other tasks during the ajax callback to /get-substances.json. I've updated the original question - see the comment that starts // Update non-Datatables UI elements. Here I'm writing to a div with the ID #numSubstances the number of records returned from the JSON data and running another custom function called drawOptionsButton(). I don't know where this fits in to the code you've provided. Please can you explain? I guess it's somewhere near .done(callback) but not sure where to go from here. Thanks.
      – Andy
      2 days ago












    • .done(callback) is really a shortcut for .done( function( data ){ callback( data ); } ). So (I think) you could just add that $('#numSubstances').html(json.recordsTotal); and drawOptionsButton(json.isFiltering); in that done function - after the callback( data ) part. Alternatively, you can also "save" those two properties (recordsTotal and isFiltering) just as with the activeRows variable - e.g. var activeRows = , recordsTotal = 0, isFiltering;, and then access/use them from a function hooked to a DataTables event such as draw or preDraw.
      – Sally CJ
      2 days ago















    up vote
    3
    down vote



    accepted
    +50










    You can actually use the ajax option to:




    1. Make the first AJAX request which retrieves the active rows.


    2. Once the active rows are retrieved, make the second AJAX request which retrieves the table data.



    Example: (see full code and demo here)



    var activeRows = ;

    function getActiveRows() {
    return $.ajax({
    url: '/view-substance/get-active-rows',
    type: 'POST',
    dataType: 'json'
    ...
    }).done(function(data){
    activeRows = data;
    console.log(activeRows);
    });
    }

    function getTableData(data, callback) {
    return $.ajax({
    url: '/get-substances.json',
    type: 'POST',
    dataType: 'json',
    'data': data // must send the `data`, but can be extended using $.extend()
    ...
    }).done(callback); // and call callback() once we've retrieved the table data
    }

    $('#example').dataTable({
    ajax: function(data, callback){
    getActiveRows().always(function(){
    getTableData(data, callback);
    });
    },
    rowCallback: function(row, data){
    ...
    }
    });


    UPDATE



    In the above example, I separated the AJAX calls into two different functions mainly to avoid long indentation in the ajax option when you call the $('#example').dataTable(). The code would otherwise look like:



    var activeRows = ;

    $('#example').dataTable({
    ajax: function(data, callback){
    // 1. Retrieve the active rows.
    $.ajax({
    url: '/view-substance/get-active-rows',
    type: 'POST',
    dataType: 'json'
    ...
    }).done(function(res){
    activeRows = res;
    console.log(activeRows);
    }).always(function(){
    // 2. Retrieve the table data.
    $.ajax({
    url: '/get-substances.json',
    type: 'POST',
    dataType: 'json',
    'data': data // must send the `data`, but can be extended using $.extend()
    ...
    }).done(callback); // and call callback() once we've retrieved the table data
    });
    },
    rowCallback: function(row, data){
    ...
    }
    });


    I used the .always() so that the table data would still be retrieved in case of failures in retrieving the active rows.






    share|improve this answer























    • This looks good. Please can you add some information about how it works, particularly the code inside the $('#example').dataTable({ block which references the other functions? I'm trying to understand the flow of this so I can use the same principles in other parts of my application. Thanks in advance.
      – Andy
      Nov 13 at 15:17










    • I updated the answer.. if you still need clarification, let me know. I've also updated the demo, but it still uses the functions.
      – Sally CJ
      Nov 13 at 15:46










    • this is brilliant and works really well. Only question is that I was performing some other tasks during the ajax callback to /get-substances.json. I've updated the original question - see the comment that starts // Update non-Datatables UI elements. Here I'm writing to a div with the ID #numSubstances the number of records returned from the JSON data and running another custom function called drawOptionsButton(). I don't know where this fits in to the code you've provided. Please can you explain? I guess it's somewhere near .done(callback) but not sure where to go from here. Thanks.
      – Andy
      2 days ago












    • .done(callback) is really a shortcut for .done( function( data ){ callback( data ); } ). So (I think) you could just add that $('#numSubstances').html(json.recordsTotal); and drawOptionsButton(json.isFiltering); in that done function - after the callback( data ) part. Alternatively, you can also "save" those two properties (recordsTotal and isFiltering) just as with the activeRows variable - e.g. var activeRows = , recordsTotal = 0, isFiltering;, and then access/use them from a function hooked to a DataTables event such as draw or preDraw.
      – Sally CJ
      2 days ago













    up vote
    3
    down vote



    accepted
    +50







    up vote
    3
    down vote



    accepted
    +50




    +50




    You can actually use the ajax option to:




    1. Make the first AJAX request which retrieves the active rows.


    2. Once the active rows are retrieved, make the second AJAX request which retrieves the table data.



    Example: (see full code and demo here)



    var activeRows = ;

    function getActiveRows() {
    return $.ajax({
    url: '/view-substance/get-active-rows',
    type: 'POST',
    dataType: 'json'
    ...
    }).done(function(data){
    activeRows = data;
    console.log(activeRows);
    });
    }

    function getTableData(data, callback) {
    return $.ajax({
    url: '/get-substances.json',
    type: 'POST',
    dataType: 'json',
    'data': data // must send the `data`, but can be extended using $.extend()
    ...
    }).done(callback); // and call callback() once we've retrieved the table data
    }

    $('#example').dataTable({
    ajax: function(data, callback){
    getActiveRows().always(function(){
    getTableData(data, callback);
    });
    },
    rowCallback: function(row, data){
    ...
    }
    });


    UPDATE



    In the above example, I separated the AJAX calls into two different functions mainly to avoid long indentation in the ajax option when you call the $('#example').dataTable(). The code would otherwise look like:



    var activeRows = ;

    $('#example').dataTable({
    ajax: function(data, callback){
    // 1. Retrieve the active rows.
    $.ajax({
    url: '/view-substance/get-active-rows',
    type: 'POST',
    dataType: 'json'
    ...
    }).done(function(res){
    activeRows = res;
    console.log(activeRows);
    }).always(function(){
    // 2. Retrieve the table data.
    $.ajax({
    url: '/get-substances.json',
    type: 'POST',
    dataType: 'json',
    'data': data // must send the `data`, but can be extended using $.extend()
    ...
    }).done(callback); // and call callback() once we've retrieved the table data
    });
    },
    rowCallback: function(row, data){
    ...
    }
    });


    I used the .always() so that the table data would still be retrieved in case of failures in retrieving the active rows.






    share|improve this answer














    You can actually use the ajax option to:




    1. Make the first AJAX request which retrieves the active rows.


    2. Once the active rows are retrieved, make the second AJAX request which retrieves the table data.



    Example: (see full code and demo here)



    var activeRows = ;

    function getActiveRows() {
    return $.ajax({
    url: '/view-substance/get-active-rows',
    type: 'POST',
    dataType: 'json'
    ...
    }).done(function(data){
    activeRows = data;
    console.log(activeRows);
    });
    }

    function getTableData(data, callback) {
    return $.ajax({
    url: '/get-substances.json',
    type: 'POST',
    dataType: 'json',
    'data': data // must send the `data`, but can be extended using $.extend()
    ...
    }).done(callback); // and call callback() once we've retrieved the table data
    }

    $('#example').dataTable({
    ajax: function(data, callback){
    getActiveRows().always(function(){
    getTableData(data, callback);
    });
    },
    rowCallback: function(row, data){
    ...
    }
    });


    UPDATE



    In the above example, I separated the AJAX calls into two different functions mainly to avoid long indentation in the ajax option when you call the $('#example').dataTable(). The code would otherwise look like:



    var activeRows = ;

    $('#example').dataTable({
    ajax: function(data, callback){
    // 1. Retrieve the active rows.
    $.ajax({
    url: '/view-substance/get-active-rows',
    type: 'POST',
    dataType: 'json'
    ...
    }).done(function(res){
    activeRows = res;
    console.log(activeRows);
    }).always(function(){
    // 2. Retrieve the table data.
    $.ajax({
    url: '/get-substances.json',
    type: 'POST',
    dataType: 'json',
    'data': data // must send the `data`, but can be extended using $.extend()
    ...
    }).done(callback); // and call callback() once we've retrieved the table data
    });
    },
    rowCallback: function(row, data){
    ...
    }
    });


    I used the .always() so that the table data would still be retrieved in case of failures in retrieving the active rows.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 13 at 15:56

























    answered Nov 13 at 14:49









    Sally CJ

    7,2722416




    7,2722416












    • This looks good. Please can you add some information about how it works, particularly the code inside the $('#example').dataTable({ block which references the other functions? I'm trying to understand the flow of this so I can use the same principles in other parts of my application. Thanks in advance.
      – Andy
      Nov 13 at 15:17










    • I updated the answer.. if you still need clarification, let me know. I've also updated the demo, but it still uses the functions.
      – Sally CJ
      Nov 13 at 15:46










    • this is brilliant and works really well. Only question is that I was performing some other tasks during the ajax callback to /get-substances.json. I've updated the original question - see the comment that starts // Update non-Datatables UI elements. Here I'm writing to a div with the ID #numSubstances the number of records returned from the JSON data and running another custom function called drawOptionsButton(). I don't know where this fits in to the code you've provided. Please can you explain? I guess it's somewhere near .done(callback) but not sure where to go from here. Thanks.
      – Andy
      2 days ago












    • .done(callback) is really a shortcut for .done( function( data ){ callback( data ); } ). So (I think) you could just add that $('#numSubstances').html(json.recordsTotal); and drawOptionsButton(json.isFiltering); in that done function - after the callback( data ) part. Alternatively, you can also "save" those two properties (recordsTotal and isFiltering) just as with the activeRows variable - e.g. var activeRows = , recordsTotal = 0, isFiltering;, and then access/use them from a function hooked to a DataTables event such as draw or preDraw.
      – Sally CJ
      2 days ago


















    • This looks good. Please can you add some information about how it works, particularly the code inside the $('#example').dataTable({ block which references the other functions? I'm trying to understand the flow of this so I can use the same principles in other parts of my application. Thanks in advance.
      – Andy
      Nov 13 at 15:17










    • I updated the answer.. if you still need clarification, let me know. I've also updated the demo, but it still uses the functions.
      – Sally CJ
      Nov 13 at 15:46










    • this is brilliant and works really well. Only question is that I was performing some other tasks during the ajax callback to /get-substances.json. I've updated the original question - see the comment that starts // Update non-Datatables UI elements. Here I'm writing to a div with the ID #numSubstances the number of records returned from the JSON data and running another custom function called drawOptionsButton(). I don't know where this fits in to the code you've provided. Please can you explain? I guess it's somewhere near .done(callback) but not sure where to go from here. Thanks.
      – Andy
      2 days ago












    • .done(callback) is really a shortcut for .done( function( data ){ callback( data ); } ). So (I think) you could just add that $('#numSubstances').html(json.recordsTotal); and drawOptionsButton(json.isFiltering); in that done function - after the callback( data ) part. Alternatively, you can also "save" those two properties (recordsTotal and isFiltering) just as with the activeRows variable - e.g. var activeRows = , recordsTotal = 0, isFiltering;, and then access/use them from a function hooked to a DataTables event such as draw or preDraw.
      – Sally CJ
      2 days ago
















    This looks good. Please can you add some information about how it works, particularly the code inside the $('#example').dataTable({ block which references the other functions? I'm trying to understand the flow of this so I can use the same principles in other parts of my application. Thanks in advance.
    – Andy
    Nov 13 at 15:17




    This looks good. Please can you add some information about how it works, particularly the code inside the $('#example').dataTable({ block which references the other functions? I'm trying to understand the flow of this so I can use the same principles in other parts of my application. Thanks in advance.
    – Andy
    Nov 13 at 15:17












    I updated the answer.. if you still need clarification, let me know. I've also updated the demo, but it still uses the functions.
    – Sally CJ
    Nov 13 at 15:46




    I updated the answer.. if you still need clarification, let me know. I've also updated the demo, but it still uses the functions.
    – Sally CJ
    Nov 13 at 15:46












    this is brilliant and works really well. Only question is that I was performing some other tasks during the ajax callback to /get-substances.json. I've updated the original question - see the comment that starts // Update non-Datatables UI elements. Here I'm writing to a div with the ID #numSubstances the number of records returned from the JSON data and running another custom function called drawOptionsButton(). I don't know where this fits in to the code you've provided. Please can you explain? I guess it's somewhere near .done(callback) but not sure where to go from here. Thanks.
    – Andy
    2 days ago






    this is brilliant and works really well. Only question is that I was performing some other tasks during the ajax callback to /get-substances.json. I've updated the original question - see the comment that starts // Update non-Datatables UI elements. Here I'm writing to a div with the ID #numSubstances the number of records returned from the JSON data and running another custom function called drawOptionsButton(). I don't know where this fits in to the code you've provided. Please can you explain? I guess it's somewhere near .done(callback) but not sure where to go from here. Thanks.
    – Andy
    2 days ago














    .done(callback) is really a shortcut for .done( function( data ){ callback( data ); } ). So (I think) you could just add that $('#numSubstances').html(json.recordsTotal); and drawOptionsButton(json.isFiltering); in that done function - after the callback( data ) part. Alternatively, you can also "save" those two properties (recordsTotal and isFiltering) just as with the activeRows variable - e.g. var activeRows = , recordsTotal = 0, isFiltering;, and then access/use them from a function hooked to a DataTables event such as draw or preDraw.
    – Sally CJ
    2 days ago




    .done(callback) is really a shortcut for .done( function( data ){ callback( data ); } ). So (I think) you could just add that $('#numSubstances').html(json.recordsTotal); and drawOptionsButton(json.isFiltering); in that done function - after the callback( data ) part. Alternatively, you can also "save" those two properties (recordsTotal and isFiltering) just as with the activeRows variable - e.g. var activeRows = , recordsTotal = 0, isFiltering;, and then access/use them from a function hooked to a DataTables event such as draw or preDraw.
    – Sally CJ
    2 days ago












    up vote
    1
    down vote













    You could solve your problem with Promises. Promises are objects that help you manage and coordinate asynchronous tasks. Your case would look something like this:



    var activeRows = ;
    var substancesTable = $('#substancesTable').DataTable({
    // ...
    });

    var pDataTable = new Promise(function(resolve, reject){
    // you wan't to resolve just once,
    // after the table has finished processing the received data.
    // (You may want to change draw to an event that's more suitable)
    substancesTable.one('draw', resolve);
    });

    var pOpenRows = new Promise(function( resolve, reject ){

    $.ajax({
    url: '/view-substance/get-active-rows',
    method: 'post',
    cache: false,
    }).done(function(data) {
    // you can either save your rows globaly or give them to the resolve function
    // you don't have to do both
    activeRows = data;
    resolve( data );
    });

    });

    // Here we basically create a third promise, which resolves (or rejects)
    // automatically based on the promises in the array.
    Promise.all([pDataTable, pOpenRows])
    .then(function( values ){
    // expand your table rows here
    // Note: if you gave your rows to the resolve function you can access
    // them here in values[1] (pDataTable's data would be in values[0])
    });


    In case you want to learn more about Promises:




    • https://developers.google.com/web/fundamentals/primers/promises

    • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

    • https://scotch.io/tutorials/javascript-promises-for-dummies


    For details on browser support you may look here:





    • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

    • https://caniuse.com/#search=Promise






    share|improve this answer

























      up vote
      1
      down vote













      You could solve your problem with Promises. Promises are objects that help you manage and coordinate asynchronous tasks. Your case would look something like this:



      var activeRows = ;
      var substancesTable = $('#substancesTable').DataTable({
      // ...
      });

      var pDataTable = new Promise(function(resolve, reject){
      // you wan't to resolve just once,
      // after the table has finished processing the received data.
      // (You may want to change draw to an event that's more suitable)
      substancesTable.one('draw', resolve);
      });

      var pOpenRows = new Promise(function( resolve, reject ){

      $.ajax({
      url: '/view-substance/get-active-rows',
      method: 'post',
      cache: false,
      }).done(function(data) {
      // you can either save your rows globaly or give them to the resolve function
      // you don't have to do both
      activeRows = data;
      resolve( data );
      });

      });

      // Here we basically create a third promise, which resolves (or rejects)
      // automatically based on the promises in the array.
      Promise.all([pDataTable, pOpenRows])
      .then(function( values ){
      // expand your table rows here
      // Note: if you gave your rows to the resolve function you can access
      // them here in values[1] (pDataTable's data would be in values[0])
      });


      In case you want to learn more about Promises:




      • https://developers.google.com/web/fundamentals/primers/promises

      • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

      • https://scotch.io/tutorials/javascript-promises-for-dummies


      For details on browser support you may look here:





      • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

      • https://caniuse.com/#search=Promise






      share|improve this answer























        up vote
        1
        down vote










        up vote
        1
        down vote









        You could solve your problem with Promises. Promises are objects that help you manage and coordinate asynchronous tasks. Your case would look something like this:



        var activeRows = ;
        var substancesTable = $('#substancesTable').DataTable({
        // ...
        });

        var pDataTable = new Promise(function(resolve, reject){
        // you wan't to resolve just once,
        // after the table has finished processing the received data.
        // (You may want to change draw to an event that's more suitable)
        substancesTable.one('draw', resolve);
        });

        var pOpenRows = new Promise(function( resolve, reject ){

        $.ajax({
        url: '/view-substance/get-active-rows',
        method: 'post',
        cache: false,
        }).done(function(data) {
        // you can either save your rows globaly or give them to the resolve function
        // you don't have to do both
        activeRows = data;
        resolve( data );
        });

        });

        // Here we basically create a third promise, which resolves (or rejects)
        // automatically based on the promises in the array.
        Promise.all([pDataTable, pOpenRows])
        .then(function( values ){
        // expand your table rows here
        // Note: if you gave your rows to the resolve function you can access
        // them here in values[1] (pDataTable's data would be in values[0])
        });


        In case you want to learn more about Promises:




        • https://developers.google.com/web/fundamentals/primers/promises

        • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

        • https://scotch.io/tutorials/javascript-promises-for-dummies


        For details on browser support you may look here:





        • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

        • https://caniuse.com/#search=Promise






        share|improve this answer












        You could solve your problem with Promises. Promises are objects that help you manage and coordinate asynchronous tasks. Your case would look something like this:



        var activeRows = ;
        var substancesTable = $('#substancesTable').DataTable({
        // ...
        });

        var pDataTable = new Promise(function(resolve, reject){
        // you wan't to resolve just once,
        // after the table has finished processing the received data.
        // (You may want to change draw to an event that's more suitable)
        substancesTable.one('draw', resolve);
        });

        var pOpenRows = new Promise(function( resolve, reject ){

        $.ajax({
        url: '/view-substance/get-active-rows',
        method: 'post',
        cache: false,
        }).done(function(data) {
        // you can either save your rows globaly or give them to the resolve function
        // you don't have to do both
        activeRows = data;
        resolve( data );
        });

        });

        // Here we basically create a third promise, which resolves (or rejects)
        // automatically based on the promises in the array.
        Promise.all([pDataTable, pOpenRows])
        .then(function( values ){
        // expand your table rows here
        // Note: if you gave your rows to the resolve function you can access
        // them here in values[1] (pDataTable's data would be in values[0])
        });


        In case you want to learn more about Promises:




        • https://developers.google.com/web/fundamentals/primers/promises

        • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

        • https://scotch.io/tutorials/javascript-promises-for-dummies


        For details on browser support you may look here:





        • https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise

        • https://caniuse.com/#search=Promise







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 12 at 11:23









        Fitzi

        1387




        1387






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53206138%2fusing-ajax-in-a-callback-where-the-parent-process-itself-relies-on-an-ajax-call%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Guess what letter conforming each word

            Port of Spain

            Run scheduled task as local user group (not BUILTIN)