This question came up in a forum where I drop by now & then. It is also something that I recall answering previously on one or two occasions. So I thought I’d write about it here with a rudimentary example to provide a gist of how it works.
There’s no mystery or secret voodoo involved in having AJAX work in a Laravel app. On its own Laravel 4 (current version) doesn’t have any API for implementing AJAX, so you’ll need to do the footwork yourself. The basic concept that applies everywhere else applies here as well; grab the data from a HTML form, create an AJAX request and send it to server to a URL on which data is expected. Form data is retrieved on server just like any normal form data would be, the only key part is since you’re dealing with an AJAX request you can’t send back a normal View as response, you’ll need to make your own response with proper headers.
Note: I’ve assumed availability of jQuery in this example to avoid writing too much boilerplate. If you use any other library then you can use that as well, usage of jQuery is just to demonstrate the concept.
Lets add example routes to our routes.php
file:
//Settings: show form to create settings
Route::get( '/settings/new', array(
'as' => 'settings.new',
'uses' => 'SettingsController@add'
) );
//Settings: create a new setting
Route::post( '/settings', array(
'as' => 'settings.create',
'uses' => 'SettingsController@create'
) );
Then we create a view which has a form for adding a new setting:
{{ Form::open( array(
'route' => 'settings.create',
'method' => 'post',
'id' => 'form-add-setting'
) ) }}
{{ Form::label( 'setting_name', 'Setting Name:' ) }}
{{ Form::text( 'setting_name', '', array(
'id' => 'setting_name',
'placeholder' => 'Enter Setting Name',
'maxlength' => 20,
'required' => true,
) ) }}
{{ Form::label( 'setting_value', 'Setting Value:' ) }}
{{ Form::text( 'setting_value', '', array(
'id' => 'setting_value',
'placeholder' => 'Enter Setting Value',
'maxlength' => 30,
'required' => true,
) ) }}
{{ Form::submit( 'Add Setting', array(
'id' => 'btn-add-setting',
) ) }}
{{ Form::close() }}
After this comes the Javascript which is loaded into our view which makes the AJAX call:
jQuery( document ).ready( function( $ ) {
$( '#form-add-setting' ).on( 'submit', function() {
//.....
//show some spinner etc to indicate operation in progress
//.....
$.post(
$( this ).prop( 'action' ),
{
"_token": $( this ).find( 'input[name=_token]' ).val(),
"setting_name": $( '#setting_name' ).val(),
"setting_value": $( '#setting_value' ).val()
},
function( data ) {
//do something with data/response returned by server
},
'json'
);
//.....
//do anything else you might want to do
//.....
//prevent the form from actually submitting in browser
return false;
} );
} );
And now that Javascript and form UI are in place, its time to do the backend stuff in our controller:
class SettingsController extends BaseController {
/**
* show a view with form to create settings
*/
public function add() {
return View::make( 'settings/new' );
}
/**
* handle data posted by ajax request
*/
public function create() {
//check if its our form
if ( Session::token() !== Input::get( '_token' ) ) {
return Response::json( array(
'msg' => 'Unauthorized attempt to create setting'
) );
}
$setting_name = Input::get( 'setting_name' );
$setting_value = Input::get( 'setting_value' );
//.....
//validate data
//and then store it in DB
//.....
$response = array(
'status' => 'success',
'msg' => 'Setting created successfully',
);
return Response::json( $response );
}
//end of class
}
As you can see, it is quite straightforward. You create a POST request to the URI with data and the controller method on server receives data as nomral form data. It then parses it, do with it whatever it wants and responds back with the header of content type application/json
(or it can be XML or any other data format) which the Javascript in browser is expecting.
Just the usual AJAX stuff. You can ofcourse find and use PHP/Javascript libraries which will do the heavy lifting for you so you can just make few API calls instead of writing your own Javascript boilerplate.
UPDATE: Updated the code example above to use Response::json()
instead of the custom function which created a Response
object and set the content type header to application/json
.
Wonderful. Was looking for this piece of information
Thank you for the helpful article.
I am having an issue however.
I call a js file with my ajax from the blade view.
Then the .post call is being made to my controller and I am pretty sure it gets inside the controller/action. But then my browser console is outputting a 500 error:
POST http://localhost/admin/categories/new 500 (Internal Server Error) jquery.1.10.2.min.js:6
send jquery.1.10.2.min.js:6
x.extend.ajax jquery.1.10.2.min.js:6
x.(anonymous function) jquery.1.10.2.min.js:6
(anonymous function) custom_js.js:73
x.event.dispatch jquery.1.10.2.min.js:5
v.handle
I am confused as to where the error is occurring.. I have copied create and make_response methods in my controller and it seems to be crashing at the make_response function call….
any ideas?
Thanks!
I really can’t glean anything from what you’ve posted. HTTP 500 is a server error meaning something is crashing in PHP (seems likely). You’ll need to either step through your code to debug what’s breaking (xdebug is an excellent tool to have) or examine your error logs & see if there’s anything helpful in there.
_make_response() that I’ve posted above in example is rather straight forward & is a quick wrapper for Laravel code. So instead of doing this:
[sourcecode lang=”php”]
return $this->_make_response( json_encode( $my_array ) );
[/sourcecode]
you can also do this:
[sourcecode lang=”php”]
return Response::make( json_encode( $my_array ) )->header( ‘Content-Type’, ‘application/json’ );
[/sourcecode]
Just make sure that whatever you pass to
Response::make()
needs to be a string, in this case a JSON encoded string.Hey, just wanted to say thanks for this article, very helpful and detailed!
Glad you found it useful. :tup:
In Laravel 4 you can simply
return Response::json([]);
You can also just return an array in the controller action & Laravel 4 converts it JSON before sending it to browser but that doesn’t set the content type header to
application/json
. Seems likeResponse::json()
sets the proper headers, hadn’t seen that one. Thanks. :tup:Thanks for the post! Must needed information.
Im implementing this…
In your javascript file, what exactly is the ‘json’ on line 19 for?
The data type expected from server (ref jQuery.post()). jQuery parses it & makes it available for use. See
SettingsController
line #34, we’re returning a response as JSON.Brilliant…
Can you help me with a code
accept data->as date->go to DB -> check if date is added previously -> if added return the entire row -> to the same page where date was accepted -> BUT BUT must have no submit button it should have only ONSELECT DATE OPTION (using jquery)
————laravel——–
thanks in advance
In your jQuery code listen for the
change
event of your select drop-down like:[js]
jQuery( ‘#date-dropdown’ ).on( ‘change’, function() {
//fire the form submit event here
jQuery( ‘#my-form’ ).trigger( ‘submit’ );
} );
[/js]
So anytime your drop-down list (of ID
date-dropdown
) has a change in value, it will trigger the submission of your form (of IDmy-form
). If you’re using AJAX for form submission then all you need to do is write code to handle form submit.Just wanted to point out, that with a little effort, this stuff really works. I realized this is the post that got me actually sending stuff back and forth from the server. I use this technique several times a day now, with several variations for purpose. thanks again!
Hi Im getting “Unsupported operand types ”
on
$response – array(
‘status’ => ‘success’,
‘msg’ => “Registration Failed – $messages”
);
return Response::json($response);
in Laravel4 … any clues?
Ok found the error was a silly typo.. had a “-” instead of “=” next to $response. Now I get and out put of
{“status”:”success”,”msg”:”Registration Failed”}
But how to I redirect back to the original form?
can I combine this JS Jquery with jquery form validation?
How?
Thanks.
Ofcourse, this is just like any other Javascript code for AJAX using jQuery, you can add whatever you want to it.
Hi,
I want to know from where you are extracting the token
on this line
“_token”: $( this ).find( ‘input[name=_token]’ ).val()
thanks
Its a hidden input field that Laravel adds automatically with a CSRF protection token when
Form::open()
is used. That’s what we validate in line 15 ofSettingsController
. Check the Laravel docs here.Thank you very much for this wonderful article. It took me 2 days for me playing with my codes trying to figure out the same thing before landed on this page. It helped me a lot.
Hi, just a little tip, you can replace :
“_token”: $( this ).find( ‘input[name=_token]’ ).val(),
“setting_name”: $( ‘#setting_name’ ).val(),
“setting_value”: $( ‘#setting_value’ ).val()
…
With this :
$(this).serialize()
It’s really usefull when you have a huge form 🙂
( Or to get the AJAX working for other forms, with the same code )
Thanks for pointing it out Tom. The JS here is just for illustration purposes to show how to use AJAX in a Laravel app & so I kept it as simple as possible. 🙂