CodeIgniter + jQuery Ajax runs successfully but error callback is called - php

I have a pretty simple CodeIgniter project that does some simple database work. Currently I have a controller method that deletes an item in the database. In my view, the code uses the jQuery ajax object to reference that controller, then displays either success or failure through its callbacks.
The problem is, although the controller works fine (deletes the item in the DB as expected), the ajax "error" callback is being called, instead of "success".
I'm sure I'm missing something super basic here...
Here is my controller method:
public function delete_note()
{
$this->load->helper('url');
$this->load->model('auth/user', 'User');
$this->load->database();
$note_id = $this->input->post('id');
$this->db->delete('admin_notes', array('id' => $note_id));
$this->db->query();
$this->output->set_status_header('200'); // Attempting to force the issue
}
And here is the code within the view:
$('.delete_note').each(function(){
var current = this;
this.onclick = function(event)
{
var note_id = this.title;
$.ajax({
type: "POST",
url: "/admin/delete_note",
data: { id: note_id },
success: function(data) { alert('I never see this!');},
error: function () { alert('I *always* see this!');}
});
}
});
Any answer attempts are appreciated. Any correct answers are doubly appreciated ;)
Thanks!

Just because the database logic is working, you may be receiving issues related to something else (cross-browser perhaps?). To see the error, change your error function to be like this:
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus);
alert(errorThrown);
}

I'd like to thank WojtekT for reminding me to check my responses in Firebug. I was actually receiving back a 500 status code for PHP errors. My extraneous $this->db->query(); call needed to be removed.
Everything works great now.
Thanks!

Related

Laravel 5.2 return with errors - how to tell which form is submitted

I'm using Laravel 5.2. On my index page, I've got a button to add a new entry, which brings up the form in a lightbox. This form then submits via the create method.
I also have each entry listed on this page, with the ability to edit them inline, which submits via the update method.
I've setup validation via a Request. This means when someone misses something on the add, it redirects to the index method with errors. The errors only show though, when the lightbox is triggered by the user.
I know I can use $errors to see any errors, but I don't see how I can differentiate between the create and update forms for the sake of forcing the lightbox to appear on reload with create errors. Is there a way to do that?
Update:
Suggestion was made to use AJAX to bypass the reload issue, but now I'm getting a 422 return:
AJAX call:
(function(){
var submitAjaxRequest = function(e){
var form = $(this);
var method = form.find('input[name="_method"]').val() || 'POST';
$.ajax({
type: method,
url: form.prop('action'),
data: form.serialize(),
success: function(data){
console.log(data)
}
});
e.preventDefault();
}
$('form[data-remote]').on('submit', submitAjaxRequest);
})();
Request:
public function response(array $errors)
{
$response = parent::response($errors);
if ($this->ajax() || $this->wantsJson()) {
return $response;
}
return $response->with('requestMethod', $this->method());
}
I've also tested the ajax call and it works fine when the validation rules are met. It only fails if the validation comes back with something incorrect in the input.
You could override the response method so that you can flash the type of request.
In you Request class you could add
public function response(array $errors)
{
$response = parent::response($errors);
if ($this->ajax() || $this->wantsJson()) {
return $response;
}
return $response->with('requestMethod', $this->method());
}
(With ajax you wouldn't need to worry about the page reload so we can just return the original response.)
In the above I'm assuming you're using POST for your create methods and PUT or PATH for your update methods. If this is not the case you could use a way that make sense to you to differentiate between the requests.
Then in your view you could do something like:
#if(session('requestMethod') == 'POST')
https://laravel.com/docs/5.2/responses#redirecting-with-flashed-session-data
If you are going to use ajax, as I mentioned in the comment above, you will need to make sure you use the error method within the ajax call:
$.ajax({
type: method,
url: form.prop('action'),
data: form.serialize(),
success: function (data) {
console.log('success', data)
},
error: function (data) {
console.log('error', data)
}
});
Hope this helps!

Sending jQuery.serialize form via POST, expecting JSON response from controller

I would like to ask you how could I send ajax request with serialized by jQuery form and recieve JSON response from controller? I have been trying many solutions but none of them worked for me. I have a little experience in that matter.
Can you provide any good example? Thank You!
Send post with serialized form (POST) by AJAX
Process action in controller function and obtain JSON response in ajax -> success
I'm using CakePHP 2.4.1
My ajax request
$.ajax({
type: "post",
url: location.pathname + "/edit",
data: data,
success: function(response) {
$("#content").html(response); // i would like to recieve JSON response
alert(response); // here ;C
},
error: function(){
alert("error");
}
});
Part of my function in controller
public function admin_edit(){
//................ some logic passed
if($this->request->is('ajax')){
$this->layout = 'ajax';
$this->autoRender = false;
$this->set(compact('user'));
$this->disableCache();
foreach($this->request->data['User'] as $key => $value){
if(empty($value)){
unset($this->request->data['User'][$key]);
}
}
$this->User->id = $this->request->data['User']['id'];
if($this->User->save($this->request->data)){
$this->Session->setFlash('Użytkownik został zmodyfikowany');
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash('Nie zmodyfikowano użytkownika');
}
}
What i would like to recieve is JSON response from the controller.
example
[{"id":"1", "username":"test", ... }]
Ok, I think what confuse you are little stuff, but mixed together can be a bit hard to debug for someone with little experience. I'll post a basic example of what should work for you, and you iterate over that. Tell us if there's another error (it's easier to check for specific errors rather than the view/controller possible error).
First, in the ajax call, change for console.log(response); to debug better
//alert(response);
console.log(response);
},
error: function(){
alert("error");
console.log(response);
}
});
And in the controller
public function admin_edit(){
//................ some logic passed
if($this->request->is('ajax')){
/* layout not necessary if you have autoRender = false */
//$this->layout = 'ajax';
/* actually, no need for this either with _serialize, but add it if you have unwanted html rendering problems */
//$this->autoRender = false;
$this->set(compact('user'));
/* other code that doesn't really matter for the example ... */
$this->User->id = $this->request->data['User']['id'];
if($this->User->save($this->request->data)){
/* NO!! */
//$this->Session->setFlash('Użytkownik został zmodyfikowany');
//return $this->redirect(array('action' => 'index'));
$status = 'OK';
$message = 'Użytkownik został zmodyfikowany';
$this->set(compact('message', 'status'));
}
/* NO EITHER!! */
//$this->Session->setFlash('Nie zmodyfikowano użytkownika');
$status = 'NOT-OK';
$message = 'Not sure what your flash says but let\'s assume it an error alert';
$this->set(compact('message', 'status'));
//serialize variables you have set for the "ghost" view
$this->set('_serialize', array('user', 'message', 'status'));
}
}
I think your major flaw here is to return a redirect. That's a no no for json. What you are doing with that is giving the ajax call the html for the index action. That makes no sense. If you want the action to return JSON, then all cases must return json, no html whatsoever. So, no setFlash, no redirect. What I normally do here is to return the JSON data with a status and a message (like in the code above). Then, in the ajax call, on success, you parse the JSON data, read the status, if ok you redirect (via js), and if not, show the error message you got.
Hope it clear things for you.
[tiny edit]: json_encode will also work, but when in CakePHP, do what CakePHP(ians?) do (serialize) (because you don't need to echo the variables).
There's an example at JQuery.com
Example: Post to the test.php page and get content which has been returned in json format
<?php echo json_encode(array("name"=>"John","time"=>"2pm")); ?>
.
$.post( location.pathname + "/edit", data, function( data ) {
console.log( data.name ); // John
console.log( data.time ); // 2pm
}, "json");
So plugging in your ajax call is something like:
$.post( "test.php", data, function(response) {
$("#content").html(response);
alert(response);
}, "json");
Edit: If you're not getting the correct response, please show the php code that echos or returns the json..it's not anywhere in that function you provided.

Sending json to symfony controller

I need to pass json data to my Symfony Controller. My ajax function looks like this:
var data = '{"firstname":"John"}';
$.ajax({
type: "POST",
url: save_url, //path to controller action
data: {json:data},
success: function(response) {
// Do something
}
});
In my controller, I try to get my data through:
public function createAction(Request $request) {
$data = $this->getRequest()->get('firstname');
return $this->render('MyBundle:Counter:test.html.twig', array(
'data' => $data
));
Just to see if this works, I send $data to be echoed in a template. In Firebug I can see the data being sent and everything seems to work, but $data is empty and nothing is echoed. Where am I doing this wrong?
EDIT: When I check the response in Fireburg console, I see my data there, in place, but it never appears in the template. var_dump($data) tells that $data is null. So, it seems data is being sent but the controller ignores it.
As Marek noticed:
$this->getRequest()
already returns the request object, you're accessing the request property of the request, that doesn't add up. Either try:
$data = $this->request->get('json');
Or use:
$data = $this->getRequest()->get('json');
You can, of course assign the return value of $this->getRequest() to a variable, and call the get method on that var from there on end... anyway, here's my initial answer, it does contain some more tips, and considerations you may find useful:
You should be able to get the data this way, though AJAX requests + echoing in a template? That does sound a bit strange. I don't see you passing the $data variable to a $this->render call anywhere.
This is a copy-paste bit from a controller action in one of my projects. It works just fine there:
public function indexAction()
{
if (!$this->getRequest()->isXmlHttpRequest())
{//check if request is AJAX request, if not redirect
return $this->redirect(
$this->generateUrl('foo_bar_homepage')//changed this, of course
);
}
$id = $this->getRequest()->get('id',false);//works fine
However, I can't begin to grasp why you're doing this:
var data = '{"firstname":"John"}';
Why not simply go for:
$.ajax({
type: "POST",
url: url,//post how you get this URL please...
data: {firstname: 'John'},//jQ will sort this out for you
success: function(response)
{
console.log(response);
}
error: function()
{
console.log('an error occured');
console.log(arguments);//get debugging!
}
});
Then, in your controller you're able to:
$this->getRequest()->get('firstname');//it should be John
You could even pass {json:{firstname: 'john'}} as the data param to $.ajax, the only difference in your controller will be, that you have to do this:
$data = $this->getRequest()->get('json');
$firstName = $data['firstname'];
That should work just fine, unless there's somthing you're not telling us :)
RECAP:
This is what I'd write:
public function createAction()
{//no Request param in controller
if (!$this->getRequest()->isXmlHttpRequest())
{//no ajax request, no play...
$this->redirect(
$this->generateUrl('homepage_route')
);
}
$data = $this->getRequest()->get('firstname');
//return json response:
return new Response(json_encode(array('dataReceived' => $data));
//return rendered HTML page:
return $this->render('MyBundle:Counter:test.html.twig', array(
'data' => $data
));
}
Of course, then the JS code should read:
$.ajax({
type: "POST",
url: 'route/to/create'
data: {firstname:'John'},
success: function(response)
{
console.log(response);
}
});
I have tested this, and I see no reason why this shouldn't work. It works just fine for me...
Please note this was #EliasVanOotegem original example but there are some obvious steps missing
in the controller i'm reading a few replies as in "I cannot see how this works as i'm getting null" this is because your not correctly keying your object.
i.e.
var data = { name : 'john' };
$.ajax({
type: "POST",
url: url,//post how you get this URL please...
data: {json : data},//jQ will sort this out for you
success: function(response)
{
console.log(response);
}
error: function()
{
console.log('an error occured');
console.log(arguments);//get debugging!
}
});
as you can now see accessing the requerst object like
$request->get('json');
refers to the post key for the json data
Is the content what you're trying to retrieve, neither params nor headers.
Try:
$request->getContent();
In your case $request->request->get('json') should do.

PHP and JQuery Button trigger not working

Im currently new to PHP and JQuery after having using ASP.Net and C Sharp for the 2 years. I have this major problem in which i require some assistance in.
I have a HTML <input type="submit" id="btnWL" value="Add to Wishlist"> button. Basically when this button is pressed a table called 'wishlist' in the database is checked to see if the current product is already in a wishlist. If no the button will trigger a database save else it will return a JQuery alert pop up error message.
I having difficulty in passing 2 PHP variables: $_SESSION["username"] and $_GET["ProductId"] into this JQuery method:
<script type="text/javascript">
$(document).ready(function() {
$('#btnWL').live('click', function() {
$.post("addToWishlist.php");
});
});
</script>
As you can see this JQuery method must pass those values to an external PHP File which checks for an already exsisting record in the 'wishist' table with those details.
<?php
$WishlistDAL = new WishlistDAL();
$result = $WishlistDAL->get_ProductInWishlistById($_GET["ProductId"]);
if (isset($_POST["isPostBack"])) {
if (isset($_SESSION["username"])) {
if (isset($_GET["btnWL"])) {
//Check if ProductId is in Cart
if (mssql_num_rows($result)>0)
{
//Return an error
//Sumhow this has to trigger an alert box in the above JQuery method
}
else
{
//Write in Wishlist Table
$WishlistDAL->insert_ProductInWishlist($_GET["ProductId"], $_SESSION["username"]);
}
}
}
else
{
//Return Error
}
}
?>
Another problem I have is then displaying an alert box using the same JQuery method for any errors that where generated in the php file.
Any Ideas how I can implement this logic? Thanks in advance.
Your "$.post()" call isn't passing any parameters, and has no callback for interpreting the results:
$.post('addToWishlist.php', { username: something, password: something }, function (response) {
});
The "something" and "something" would probably come from your input fields, so:
$.post('addToWishlist.php', { username: $('#username').val(), password: $('#password').val() }, function (response) {
});
Now the callback function would interpret the response from the server:
$.post('addToWishlist.php', { username: $('#username').val(), password: $('#password').val() }, function (response) {
if (response === "FAIL") {
alert("fail");
}
else {
// ... whatever ...
}
});
Exactly what that does depends on your server code; that "FAIL" response is something I just made up as an example of course.
jQuery accepts an callback:
$(document).ready(function() {
$('#btnWL').live('click', function() {
$.post("addToWishlist.php", {'isPostBack':1}, function(res){
if (res.match(/err/i)){
alert(res);
}
});
});
});
Then, in the php, just (echo('Error adding record')) for this jquery to see there's an error string in the response and pop up the error message.
Other methods would be to use json, or http status codes and $.ajaxError(function(){ alert('error adding'); });.
from what i can tell so far is you'll only need to pass in the product id in and you can do this by appending your $.post call with the value; this will pass to your php script as a query string variable. i'm not sure which php script you posted, but if you're sending your data with jquery, it's using post and not get, so you may need to make an adjustment there and the session data should be available regardless, since it's the same session.
again this is without seeing all the code and since some of it isn't labeled, it's hard to determine. another thing, i like to use $.ajax for most actions like this, you have a lot more room to define and structure, as well as create one generic ajax function to call the methods and post data, as well as make a response callback. here's the documentation for you to look into $.ajax
i hope this helps.

Some ajax help?

I have a php script that takes some user form input and packs some files into a zip based on that input. The problem is that sometimes the server errors, so all the form data is lost. I was told I could use ajax instead so that the user never even has to change the page. I've never used ajax, and looking at http://api.jquery.com/jQuery.ajax/ without any experience in ajax is quite difficult.
The page says that you can accept returns from an ajax call. How do you set up returns in the PHP file for an ajax call? If the server errors with the ajax call, how will I know?
edit: Also, is there a way to send an ajax request with javascript and jquery as if it were a submitted form?
How do you set up returns in the PHP file
just echo it in ajax page that will return as response
Simple Tutorial
client.php
$.post('server.php',({parm:"1"}) function(data) {
$('.result').html(data);
});
server.php
<?php
echo $_POST['parm'];
?>
result will be 1
edit on OP comments
Is there a way to use ajax as if you were submitting a form
Yes, there is
You can use plugins like jQuery form
Using submit
If you using jquery validation plugin, you can use submit handler option
using sumit
$('#form').submit(function() {
//your ajax call
return false;
});
every ajax function has a function param to deal with server returns.and most of them has the param msg,that is the message from server.
server pages for example php pages you can just use echo something to return the infomation to the ajax funciton . below is an example
$.ajax({
url:yoururl,
type:post,
data:yourdata,
success:function(msg){
//here is the function dealing with infomation form server.
}
});
The easiest way to get information from PHP to JavaScript via AJAX is to encode any PHP data as JSON using json_encode().
Here's a brief example, assuming your server errors are catchable
<?php
try {
// process $_POST data
// zip files, etc
echo json_encode(array('status' => true));
} catch (Exception $e) {
$data = array(
'status' => false,
'message' => $e->getMessage()
);
echo json_encode($data);
}
Then, your jQuery code might look something like this
$('form').submit(function() {
var data = $(this).serialize();
$.ajax(this.action, {
data: data,
type: 'POST',
dataType: 'json',
success: function(data, textStatus, jqXHR) {
if (!data.status) {
alert(data.message);
return;
}
// otherwise, everything worked ok
},
error: error(jqXHR, textStatus, errorThrown) {
// handle HTTP errors here
}
});
return false;
});

Categories