After Initial Load Child_Added no longer returns full data

I have a site where the user can place orders by selecting items in a menu.

It set up so that you press the "place order" button on the menu page

http://www.waipahe.co.uk/takeaway/menu.html

then the order that has been placed appears on the orders page.

http://www.waipahe.co.uk/takeaway/orders.html

On first load the of the orders.html page, it display all data fine. But any subsequent child added doesn't load the rest of the data, or doesn't display it. If I refresh the orders.html page all loaded again.

I am probably missing something very simple, but I just cant seem to find where I have made the mistake.

edit: the code from the orders.html webpage.

var base = new Firebase('https://takeaway.firebaseio.com/');

base.child('orders').on('child_added', function(snapshot) {     

    var orderData = snapshot.val();


    var contactName = orderData.ContactName; 
    var contactNumber = orderData.ContactNumber; 
    var orderTotal = orderData.TotalCost; 

    var order ="<div class='openOrder><span class='name'>"+contactName+"</span><span class='number'>"+contactNumber+"</span></div><div class='orderItems'>";

    var itemsnapshot = snapshot.child('items');

    itemsnapshot.forEach(function(itemshot){
        var itemData = itemshot.val();

        var itemCost = itemData.cost;
        var itemName = itemData.name;

        order = order + "<div class='orderItem'><span class='itemName'>"+itemName+"</span><span class='itemCost'>"+itemCost+"</span><div class='itemOptions'>";

        var optionsnapshot = itemshot.child('options');

        optionsnapshot.forEach(function(optionshot){
            var optiData = optionshot.val();

            var optiCost = optiData.cost;
            var optiName = optiData.name;

                order = order + "<div class='itemOption'><span class='optiName'>"+optiName+"</span><span class='optiCost'>"+optiCost+"</span>";
        });

        order = order + "</div></div>"

    });
    order = order + "</div><div><span class='total'>"+orderTotal+"</span></div>"
    $('#orders').append(order);
});

Upvotes: 1

Views: 67

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599176

tl;dr

In Firebase the child_added event triggers only when the child is added. When the child is later updated, the value event triggers on the child.

What causes your problem

In menu.html you first push the new order and then populate the items of the order:

    var details = base.child('orders').push({ContactName: ContactName, ContactNumber: ContactNumber, TotalCost:totalCost});
    var detailRef = details.name();

    $('#selected > .chosenItem').each(function(){
        var itemName = $(this).children(".title").text();
        var itemCost = $(this).children(".cost").text();
        var itemOpts = $(this).children(".chosenOpts");

In orders.html you listen for child_added on orders and display the details:

base.child('orders').on('child_added', function(snapshot) {     

    var orderData = snapshot.val();

    var contactName = orderData.ContactName; 
    var contactNumber = orderData.ContactNumber; 
    var orderTotal = orderData.TotalCost; 

    var order ="<div class='openOrder'><span class='name'>"+contactName+"</span><span class='number'>"+contactNumber+"</span></div><div class='orderItems'>";

    var itemsnapshot = snapshot.child('items');

    itemsnapshot.forEach(function(itemshot){

Your on('child_added' triggers when the new order is added. At that time the items of the new order are not filled in yet, so there is nothing to display.

When you add the items, the child_added event doesn't fire again on orders, since there is no new order.

A possible solution

The solution is to first compose the complete order in menu.html and only then push it to Firebase. Since you can send arbitrarily complex JavaScript objects to Firebase, your data structure will remain the same.

A simplified sample:

var order = { ContactName: ContactName, ContactNumber: ContactNumber, TotalCost:totalCost };
order.Items = [];
$('#selected > .chosenItem').each(function(){
    var itemName = $(this).children(".title").text();
    var itemCost = $(this).children(".cost").text();
    order.Items.push({ name:itemName, cost:itemCost });
});
base.child('orders').push(order);

An added advantage is that this will save you a lot of round trips between the client and server.

Upvotes: 1

Related Questions