2

Whenever I submit the "Add Bill" form, nothing happens until I refresh the page. That's when I see my new item in the Twig loop. The same problem happens when I click on the Remove link. Nothing is removed (visually) until I refresh the page.

How do I make this stuff happen right away on the page without a page refresh? I'm thinking it might have something to do with my PHP or SQL?

JavaScript:

$(document).ready(function() {
    $(".addBill").on("click", function() {
        var billAmount = $('.billAmount').val();
        var billName = $('.billName').val();
        $.ajax({
            type: "POST",
            url: "index.php",
            data: { 
                bill_amount: billAmount, 
                bill_name: billName,
                action: 'addBill'
            }
        });
        return false;
    });

    $(".removeBill").on("click", function() {
        var id = $(this).data('id');
        $.ajax({
            type: "POST",
            url: "index.php",
            data: { 
                id_to_delete: id, 
                action: 'removeBill' 
            }
        });
        return false;
    });
});

HTML:

<form method="post" name="addBillForm">
    <input type="text" placeholder="Enter bill name" name="billName" class="billName">
    <input type="text" placeholder="Enter bill amount" name="billAmount" class="billAmount">
    <input type="submit" value="Submit" name="addBillForm" class="addBill">
</form>

<br><br>
<h2>My Bills</h2>
{% for bill in bills %}
    <p>{{ bill.billName }} - {{ bill.billAmount }} - 
        <a href="#" class="removeBill" data-id="{{ bill.id }}">Remove</a>
    </p>
{% endfor %}

Here is my PHP file:

<?php

require_once 'global.php';

if (@$_POST['action'] == 'addBill')
{
    $billName = $_POST['bill_name'];
    $billAmount = intval($_POST['bill_amount']);
    $stmt = $db->prepare("INSERT INTO bills (billName, billAmount) VALUES(?,?)");
    $stmt->bindParam(1, $billName);
    $stmt->bindParam(2, $billAmount);
    $stmt->execute();
}

if (@$_POST['action'] == 'removeBill')
{
    $id = intval($_POST['id_to_delete']);
    $stmt = $db->prepare("DELETE FROM bills WHERE id = ?");
    $stmt->bindValue(1, $id);  
    $stmt->execute();
}

$billResults = $db->query('SELECT * FROM bills');
$bills = $billResults->fetchAll(PDO::FETCH_ASSOC);

$twigContext = array(
    "bills" => $bills
);

echo $twig->render('base.html.twig', $twigContext);
shawnkauffman
  • 139
  • 1
  • 9
  • 4
    You have to add a `success` handler to your ajax calls, and manually insert whatever you're returning into the DOM, the server can't update the page before it's reloaded. – adeneo Dec 26 '15 at 16:41
  • 1
    Bingo to above comment and plus, [for cancelling only the default action use `prevent.Default()` instead of `return false`](http://stackoverflow.com/questions/1357118/event-preventdefault-vs-return-false). – Rohit416 Dec 26 '15 at 16:45

3 Answers3

1

You're not actually doing anything to the page after the AJAX call completes. For example:

$.ajax({
    type: "POST",
    url: "index.php",
    data: { 
        bill_amount: billAmount, 
        bill_name: billName,
        action: 'addBill'
    },
    success: function (data) {
        // update the page somehow
    },
    error: function () {
        // there was an error, handle it here
    }
});

The page isn't going to automatically know how it should be updated. You have to write the code in that function to do it. Likely by identifying some page elements and modifying their contents, adding/removing other page elements, etc.

David
  • 208,112
  • 36
  • 198
  • 279
  • Cool. So I figured out how to use the success handler to replace the old html with the new data, using the replaceWith method, but that doesn't seem like that would be the right and best solution. Like this: success: function(data) { $("body").replaceWith(data); } How do I only append the data I need, such as bill name and bill amount? I tried doing something like data.bill_amount in my append statement but that didn't work. Thanks! – shawnkauffman Dec 26 '15 at 17:25
  • @shawnkauffman: For starters, you don't need the AJAX response to return tons of HTML. All it needs to return is some indication of success/failure and any data that the client-side code doesn't already have. As for modifying your HTML after receiving that response, there are *countless* things you could do. For example, if you have a `div` with a bunch of `p` elements and you want to add a new one, you could use jQuery's `.append()` to add some new HTML to that `div`. – David Dec 26 '15 at 17:28
  • So my questions then would be: how do I return that new data in the success handler, and then, how would i append that new data? – shawnkauffman Dec 26 '15 at 17:40
  • @shawnkauffman: You probably want your server-side AJAX handling code to be separate from the page itself. A normal, non-template PHP file which uses something like `json_encode()` to return just a data object encoded in JSON. Appending the new data would literally use the `.append()` function in jQuery. It's just a matter of targeting the element(s) to which you want to append. For example, since you have a bunch of `p` elements, try wrapping them in a `div` with an `id`. Then call `.append()` on that `div` with a new `p`. Something like: `$('#myDiv').append('

    ' + someNewValue + '

    ');`
    – David Dec 26 '15 at 17:54
  • I think I'm almost there. I appreciate the help. I understand how to append stuff. The confusion lies in what exactly to append. I got something like this: echo json_encode($billName); echo json_encode($billAmount); Then: $.ajax({ type: "POST", url: "index.php", data: { bill_amount: billAmount, bill_name: billName, action: 'addBill' }, success: function(data) { $("#bills").append("

    " + data.bill_name - data.bill_amount + "

    "); } }); Not sure how to setup the success handler exactly.
    – shawnkauffman Dec 26 '15 at 18:01
  • @shawnkauffman: You should only echo one JSON-encoded object. Multiple echos like that results in invalid JSON in the response. You can combine multiple objects into a single parent object, or perhaps an array. The `data` in the `success` function should contain exactly one JSON object (which itself may be an array of objects). – David Dec 26 '15 at 18:09
0

You arent telling it to do anything after the ajax returns. Replace your .ajax call with this.

$.post( "index.php", { action: "add bill", time: "2pm" })
  .done(function( data ) {
    alert( "Data Loaded: " + data );
  });

Then you can replace the alert with w.e you were trying to do.

Zapp
  • 232
  • 3
  • 12
0

As apparent as it could be, you don't have anything for when Ajax request succeeds(state == 200).

First you should look into this documentation for getting the idea of how jquery's ajax method works, also refer below links for the same:

http://www.sitepoint.com/use-jquerys-ajax-function/

http://www.w3schools.com/jquery/ajax_ajax.asp

You have to specify what you need to be done as soon as the jquery.ajax method is successfull or when it has completed it's execution. Mainly you have to specify what you need to do with data you get at the end of execution of the same method, generally you would show that data you got, to a specified section in the same page or you would build the whole page to reflect the changes made with ajax.

Vicky Dev
  • 1,893
  • 2
  • 27
  • 62