-1

I have the following js/jquery code:

var trigger             = $('#loadTableData');
var wrapperClass        = 'tableAccordionWrapper';
var url                 = 'data/tableData.json';
var template            = 'includes/tableInput.html';
var parentWrapper       = $('#selectedTables .sub-content .input-controls');
var href;
var intID;
var items;
var i;

// retrieve node data send from exteral source
addExternalTableInput = function(){
    $('.tableAccordionWrapper').remove();
    $.ajax({
        type:           'GET',
        url:            url,
        dataType:       'json',
        success:function(data){
            items = data.items
            for(i in items){ // this loops 3 times
                addExternalTemplate();
            }
        },
        error:function(status){
            console.log(status, "Something went wrong");
        },
        complete:function(){

        }
    });
}

// append table input to document
addExternalTemplate = function(){
    var wrapper;
    $.ajax({
        type:           'GET',
        url:            template,
        dataType:       'html',
        success:function(data){
            intID = i;
            wrapper = $('<li/>');
            wrapper.addClass(wrapperClass);
            wrapper.attr('data-id','table-' +intID);
            href = $('<a href="#"/>');
            wrapper.append(href);
            wrapper.append(data).insertBefore(parentWrapper);
            var anchor = wrapper.find('> a');
            anchor.html(items[intID].tableName); // this returns 'DB_SOURCE_3' for all 3 templates added to the DOM
        },
        error:function(status){
            console.log(status, "Something went wrong");
        },
        complete:function(){

        }
    });
}

The concept is that I am using a small json file to run another ajax request. The length of the data in the json file determines how many times the consecutive function should be fired.

The json contains very basic data, but as I loop through it I want the second ajax function to append a template of html to the document (at which point I want to be able to run other functions). One part of data from the json file needs to be injected into the template as it is iterating through the loop.

It appears that the loop works in that in this example the html template gets appended to the dom 3 times, but it passes the last table name in the json to each template that is added to the dom. The second function appears to run after the loop has finished.

Example JSON:

{  
    "items":[  
        {  
            "tableName": "DB_SOURCE_1",
            "tableID" : "14739",
            "tableDescription" : "Main customer table" 
        },
        {
            "tableName": "DB_SOURCE_2",
            "tableID" : "184889",
            "tableDescription" : "Partitions table" 
        },
        {
            "tableName": "DB_SOURCE_3",
            "tableID" : "9441093",
            "tableDescription" : "Loans Table" 
        }
    ]
}

I have tried passing the function in the ajax complete function.

I have also tried to trigger the second ajax function inside the first ajax success function like so:

addExternalTableInput = function(){
    $('.tableAccordionWrapper').remove();
    $.ajax({
        type:           'GET',
        url:            url,
        dataType:       'json',
        success:function(data){
            items = data.items
            for(i in items){
                $.ajax({
                    type:           'GET',
                    url:            template,
                    dataType:       'html',
                    success:function(data){
                        intID = i;
                        wrapper = $('<li/>');
                        wrapper.addClass(wrapperClass);
                        wrapper.attr('data-id','table-' +intID);
                        href = $('<a href="#"/>');
                        wrapper.append(href);
                        wrapper.append(data).insertBefore(parentWrapper);
                        var anchor = wrapper.find('> a');
                        anchor.html(items[intID].tableName);
                    },
                    error:function(status){
                        console.log(status, "Something went wrong");
                    },
                    complete:function(){

                    }
                });
            }
        },

But everything I have tried seems to return the same results.

lharby
  • 3,057
  • 5
  • 24
  • 56
  • You could iterate over your JSON file, and use Promise.all. – Amiga500 May 30 '17 at 09:06
  • Can you give an example. I thought promise would wait until the event is finished, I need a way to fire the second function whilst iterating through the loop. – lharby May 30 '17 at 09:08
  • Since you use jQuery, please have a look here: https://stackoverflow.com/questions/16026942/how-do-i-chain-three-asynchronous-calls-using-jquery-promises – Amiga500 May 30 '17 at 09:11
  • @VedranMaricevic unless I am mistaken, chaining is the opposite of what I want. – lharby May 30 '17 at 10:06

1 Answers1

0

The code has been rewritten somewhat, but here is what I am doing.

var templateData;

addExternalTableInput = function(){
    $('.tableAccordionWrapper').remove();
    $.ajax({
        type:           'GET',
        url:            url,
        dataType:       'json',
        success:function(data){
            var items = data.items;
            for(var i in items){
                addExternalTemplate(items[i], i); // pass parameters to this function
            }
        },
        error:function(status){
            // etc. 
        }
    });
}

addExternalTemplate = function(item, intID){ // add parameters to our function so we can access the same data
    var wrapper;
    // load template data once
    if(!templateData){ // only run this function if !templateData (should only run once).
        $.ajax({
            type:           'GET',
            url:            template,
            dataType:       'html',
            async:          false, // wait until we have a response before progressing
            success:function(data){
                templateData = data;
            },
            error:function(status){
                console.log(status, "Something went wrong");
            }
        });
    }
    // append templateData to the dom
    if(templateData){
        var href = $('<a href="#"/>');
        var tableNameInput = wrapper.find('[name="tables"]');
        tableNameInput.val(item.tableName);
        // etc
    }
    // update for, id and name attributes etc.
    updateInputAttributes = function(){
        // do other stuff to each instance of the template
    }();
}

I have moved alot of the global variables out and instead I am using function parameters.

I am only calling the html template once, but for each iteration of the loop I can run functions to update certain atrributes in that instance of the template as well as match items in the json to items in the template.

lharby
  • 3,057
  • 5
  • 24
  • 56