0

I have the following HTML code:

<table class="viewTable">
  <tr>
    <td>Price</td>
  </tr>
</table>

and I want to insert data dynamically using Javascript as follows:

var totalPrice = 0;
map.each(function(key , value , i) {
    params = {};
    params.id = key;
    // get datas from Controller class via ajax 
    ajax(url, params, false, function(result) {
        totalPrice += setData(result , key , value);
    });
});
// alert("something!"); // this may satisfy my problem.. I have no idea..
// Total Price shown on last row
$('table.viewTable tr:last').after("<tr class='title_bar'><td colspan='5' style='text-align: right;padding-right: 35px;'>"+num2Currency(totalPrice)+"</td></tr>"); 

The setData function is:

function setData(result , partsId , count) {
var price = result.price;
html = [];
html.push("<tr>");
html.push("<td><div>"+price+"</div></td>"); 
html.push("</tr>");
$('table.viewTable').append(html.join(''));
return price;}

I used the map function from Jade's answer to this question: Map in JavaScript.

My problem is either the displaying of the results or the procedure itself isn't correct. It should be inserting price rows first and then the totalPrice row afterwards; instead, the order is reversed, with totalPrice appearing first followed by the price rows. When I inserted an alert statement before insertion of totalPrice, it worked fine. Any suggestions? What's wrong with my code? Is jQuery compiled asynchronously?

Community
  • 1
  • 1
Cataclysm
  • 7,592
  • 21
  • 74
  • 123
  • You need to move that into success callback. As `AJAX` is asynchronous. So `totalPrice` will be populated at a later time. But the statements below ajax methods will be executed immediately – Sushanth -- Aug 07 '13 at 06:03
  • @ Sushanth Thanks for replying rappidly .. Please guide me as answer. Do you want to say to use success: in ajax function ? Pls describe me how. – Cataclysm Aug 07 '13 at 06:08

2 Answers2

2

Jep. Ajax calls are asynchronous, which means they don't execute immediately. You will need to keep track of the amount of completed ajax calls, and when all of them are done you can append the total.

Something like this:

var totalPrice = 0;
var completedAjaxCalls = 0;
map.each(function(key , value , i) {
    params = {};
    params.id = key;
    // get datas from Controller class via ajax 
    ajax(url, params, false, function(result) {
        totalPrice += setData(result , key , value);
        completedAjaxCalls += 1;
        if(completedAjaxCalls == map.length) {
            $('table.viewTable tr:last').after("<tr class='title_bar'><td colspan='5' style='text-align: right;padding-right: 35px;'>"+num2Currency(totalPrice)+"</td></tr>"); 
        }
    });
});

Edit: there are probably better ways of achieving this, but since you still need to grasp the concept of asynchronous methods, I thought a simple approach was appropriate here.

Moeri
  • 9,104
  • 5
  • 43
  • 56
1

You need to try

var totalPrice = 0;
var requests = [];
map.each(function(key, value, i) {
    params = {};
    params.id = key;
    // get datas from Controller class via ajax
    // make sure that `ajax()` return the promise returned by $.ajax()
    requests.push(ajax(url, params, false, function(result) {
        totalPrice += setData(result, key, value);
    }));
});
$.when.apply($, requests).done(function() {
    // alert("something!"); // this may satisfy my problem.. I have no idea..
    // Total Price show at last row
    $('table.viewTable tr:last')
    .after("<tr class='title_bar'><td colspan='5' style='text-align: right;padding-right: 35px;'>"
           + num2Currency(totalPrice) + "</td></tr>");
})
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
  • Thanks for your valuable times. Your answer is greatly useful for me. I want to accept your answer also. Thanks in advance for you. – Cataclysm Aug 07 '13 at 06:21