Welcome Guest, Not a member yet? Register   Sign In
Handling errors differently when calling from Ajax
#1

[eluser]Fumigator[/eluser]
I'd like to handle errors with a different template when calling from Ajax (with JSON as the return type) but I don't quite know what class I need to extend to make this change.

Currently I'm using the normal controller and model classes when calling via Ajax, and then inside a method in, say, the model class:

Code:
class M_accounts extends CI_Model {
function updateBankBalance($accountId, $amt)
    {
  $this->load->database();
  
  $query = $this->db->query("
    UPDATE t_accounts
    SET  bank_balance_am = $amt
    WHERE account_id = $accountId
  ");
  
  $updateCount = $this->db->affected_rows();
  return $updateCount;
}

If this query produces an error, it's buried in the Ajax response and is not JSON formatted so my Javascript doesn't know what to do with it.

I've isolated the spot in the CI core code I'd like to change, it's in system\database\DB_driver.php in the display_error() function. Instead of
Code:
echo $error->show_error($heading, $message, 'error_db');
I want to do
Code:
echo $error->show_error($heading, $message, 'error_ajax', 200);
With that error_ajax being a template I created that outputs a json encoded error.

I'm just not sure what class to extend to provide for this different output. I don't want to change the actual DB_driver.php, that'll break normal non-ajax errors, and I'm sure it's the wrong way to do it.

Can anyone point me in the right direction?
#2

[eluser]jonez[/eluser]
I solved this using JavaScript by creating a conduit system for all AJAX calls. Instead of calling $.ajax you call a method on your module and pass in the normal params and a callback function. You wrap the callback param in another function that attempts to json decode the server response. If the decode fails you throw an error. If it succeeds you pass the decoded object to the original callback. This requires every AJAX response to be in JSON, so if you send back HTML blobs you can't send raw HTML you have to wrap it in a JSON object. Ideally you should only send data back from AJAX and compile the view on the client.

Also you never want to run un-escaped queries like that use the db->update method or parametrized queries.
Code:
$this->db->where( 'account_id', $accountId );
$this->db->update( 't_accounts', array( 'bank_balance_am' => $amt ) );

//or

$query = $this->db->query("
    UPDATE t_accounts
    SET  bank_balance_am = ?
    WHERE account_id = ?
  ", array($amt, $accountId));
#3

[eluser]Fumigator[/eluser]
I'm really close to grasping what you're describing, and I think I understand how that's going to work, but I'm not quite able to put all the pieces together.

First confusion-- to initiate the server call on the client side, I have to make an Ajax call somehow, (I mostly use $.post() to do this), so I don't know how I'd get around this. (You mentioned don't do an $.ajax call) Can you give an example of how you start the server call?

I think I can make my way through the rest of what you described if I get my head around this part.
#4

[eluser]jonez[/eluser]
It's not quite ready for release (why I haven't posted it yet) but you can see example code in my Github repo: https://github.com/monsterlane/codeigniter3-app

Download that and follow the install notes to setup a new site. In the controllers/example folder you'll see some JS files. In script.js you'll see a call to this.getConduit( ).ajax. It's a wrapper that accepts an object (your $.post parameters) and calls $.ajax within that function. It wraps the callback you pass in in another function that does the decode etc.

https://github.com/monsterlane/codeignit.../assets/js
Check out the JS files and you'll see all the parts that make up that call.

app.js is a global object used to namespace everything.
app.module.js is the base client side module (example's script.js extends this)
app.conduit.js is the AJAX conduit system, modules create instances of conduits when called

You don't need all that if you just want to create your own wrapper. Once you see the flow feel free to copy/paste out whatever pieces you need. The documentation isn't the best yet, if you have questions let me know where and I'll add more comments.




Theme © iAndrew 2016 - Forum software by © MyBB