0

I have an ajax request that gets called several times based on the number of request objects in an array. The order in which these objects are in inside of the array is important, and needs to be reflected in a dynamically generated list in that same order. When the server sends back each response I update a <ul> as shown below.

     $.ajax({
        type: 'POST',
        url: baseServiceURL + 'report/',
        processData: false,
        dataType: 'json',
        contentType: 'application/json',
        data: payload,
        crossDomain: true,
    })
    .done(function (response) {
        updateUI(response);
    })
    .fail(function (jqXHR, textStatus) {
       // handle failure 
    });


var updateUI = function (response) {
    // Update the drop-down list
    $('#dropdown').append('<li><a class="dd-option" data-value="' + response.ReportName + '" data-path="' + response.ReturnURL + '" href="#">' + response.ReportName + '</a></li>');

    // do more stuf...
};

How can I dynamically build the list in such a way to where the response display in the proper order? One thing I have done is add a order param to the request who's value is the index of the request object in the array. My thought is my service can send that value back in the response so the javascript can act on it.

EDIT: The question here is asking basically the same thing except rather than using a getJSON command and appending divs I'm using a post and appending <li> elements.

Community
  • 1
  • 1
Stavros_S
  • 2,145
  • 7
  • 31
  • 75

1 Answers1

1

There are two possible strategies here.

  1. Update your UI immediately upon receiving response and then re-render if a new value is received
  2. Wait until all ajax replies have finished and then render your UI

For (1) you should just keep a running total of all items

var $dropdown = $('#dropdown');
var renderDropdown = function(reports) {
   //use lodash or underscore.js here cause implementing this manually is annoying
   var sortedSelections = _.sortBy(reports, 'order');
   var htmlPerItem = sortedSelections.map(function(item) {
      return '<li><a ..... </li>';
   });
   $dropdown.html(htmlPerItem.join(''));
}

var reportSelections = [];
payloads.map(function(payload) {
  $.ajax({ ... })
   .then(function(response) {
      reportSelections.push(response);
      renderDropdown(reportSelections);
   })
})

for (2) you can use jquery $.when

var gettingResults = payloads.map(function(payload) {
    return $.ajax({ .... });
});
$.when(gettingResults).then(function() {
  //the first arg will be response1, the second response2, etc
  var reportSelections = _.sortBy(arguments, 'order');
  renderDropdown(reportSelections);
});

Note in (1) you render once per item but get an updating view as items come in. In (2) you render only once but have to wait until all loading is complete.

Of course a variation of (1) is that you don't re-render anything, but merely insert items into the correct location as they are loaded. That's going to be more difficult to debug and more code so I leave it as an exercise for the reader (use jquery's $.fn.data to store the original item with the element).

George Mauer
  • 117,483
  • 131
  • 382
  • 612
  • Strategy 2 is not possible in this case as the UI needs to update with each response for perceived performance reasons. I will try out item 1 though and see how it works out. Thanks! – Stavros_S Mar 12 '15 at 15:42
  • Your example shows states using lodash or underscore.js which is also something I really want to avoid since this is a one off case of rendering html from JS in the app. – Stavros_S Mar 12 '15 at 15:43
  • 1
    @Stavros_S that's fine, don't use lodash or underscore, but I don't feel like re-implementing `_.sortBy`. just implement it yourself. It's like 5 lines of code. I *do* recommend one of these though and learning them very well, they are insanely useful in any project. – George Mauer Mar 12 '15 at 15:46