Can someone please explain the ajax post method in Laravel 5.3 with a full-working minimum example?
I know there are some resources in the web, but I miss a concise, straight-forward minimum example.
I presume you have a basic understanding of the model-controler-view paradigm, a basic understanding of Laravel and a basic understanding of JavaScript and JQuery (which I will use for reasons of simplicity).
We will create an edit field and a button which posts to the server. (This works for all versions from Laravel 5.0 to 5.6)
1. The Routes
At first you need to add routes to your routes/web.php. Create one route for the view, just as you know from ordinary views:
Route::get('ajax', function(){ return view('ajax'); });
The second route you need to create is the route that handles the ajax post request. Take notice that it is using the post method:
Route::post('/postajax','AjaxController#post');
2. The Controller Function
In the (second) route you created just now, the Controller function post in the AjaxController is called. So create the Controller
php artisan make:controller AjaxController
and in the app/Http/Controllers/AjaxController.php add the function post containing the following lines:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AjaxController extends Controller {
public function post(Request $request){
$response = array(
'status' => 'success',
'msg' => $request->message,
);
return response()->json($response);
}
}
The function is ready to receive data via a Http request and returns a json-formatted response (which consists of the status 'success' and the message the function got from the request).
3. The View
In the first step we defined the route pointing to the view ajax, so now create the view ajax.blade.php.
<!DOCTYPE html>
<html>
<head>
<!-- load jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<!-- provide the csrf token -->
<meta name="csrf-token" content="{{ csrf_token() }}" />
<script>
$(document).ready(function(){
var CSRF_TOKEN = $('meta[name="csrf-token"]').attr('content');
$(".postbutton").click(function(){
$.ajax({
/* the route pointing to the post function */
url: '/postajax',
type: 'POST',
/* send the csrf-token and the input to the controller */
data: {_token: CSRF_TOKEN, message:$(".getinfo").val()},
dataType: 'JSON',
/* remind that 'data' is the response of the AjaxController */
success: function (data) {
$(".writeinfo").append(data.msg);
}
});
});
});
</script>
</head>
<body>
<input class="getinfo"></input>
<button class="postbutton">Post via ajax!</button>
<div class="writeinfo"></div>
</body>
</html>
If you wonder what's the matter with this csrf-token, read https://laravel.com/docs/5.3/csrf
Related
I have created a form and I used alpine js to add something to the array data, but I don't know how to pass it to the controller as a post method
It is super important that you read the official Laravel documentation, you are not a magician, so you must get this knowledge from somewhere.
You are not sharing a controller code, so I will assume you have this one:
Route::get('/', function () {
return view('greeting', ['name' => 'James']);
});
If you have this on your view, it will render that name:
<html>
<body>
<h1>Hello, {{ $name }}</h1>
</body>
</html>
Route:
Route::get('api/get-market-list','MemberTradesController#getMarketList');
Route::get('api/get-market-list1','MemberTradesController#getMarketListtest');
Controller :
public function getMarketListtest(Request $request){
$markets = DB::table("markets")
->pluck("market","id");
return response() -> json($markets);
}
public function getMarketList(Request $request){
$markets = DB::table("markets")
->where("exchange_id", $request->exchange_id)
->pluck("market","id");
return response() -> json($markets);
}
<title>Laravel 5 - Dynamic autocomplete search using select2 JS Ajax</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script type="text/javascript">
$('#exchange').change(function(){
var exchangeID = $(this).val();
if(exchangeID){
$.ajax({
type:"GET",
url:"{{url('api/get-market-list')}}?exchange_id="+exchangeID,
success:function(res){
if(res){
$("#market").empty();
$("#market").append('<option>Select</option>');
$.each(res,function(key,value){
$("#market").append('<option value="'+key+'">'+value+'</option>');
});
}else{
$("#market").empty();
}
}
});
}else{
$("#market").empty();
$("#symbol").empty();
}
});
</script>
http://www.yourtradelog.com/api/get-market-list1
below URL is not fetching data so.. my javascript are not giving me result
http://www.yourtradelog.com/api/get-market-list?exchange_id=+1 (not working)
I want to know why this is not woring on server but all are working fine in localhost
**
ERROR LOG
**: 2 2: https://i.stack.imgur.com/rnPfh.png
Composer update error
Database markets table
I just tested the link you provided and this is my take on the situation:
The parameter you're sending via url has a + before the id (....=+1)
On your route, you're not validating if exchange_id exists (you should). If you're planning on retrieving an ID, you may call it to be in the url, or create a validation in order to check if it's correct.
According to your error (on [2]), make sure the route (and error page) are accessible without login (since you're not working with the csrf_token as I can see). When I send a request, I receive an empty json array, so I can't replicate that error. You can always try composer update
Edit: Since you say it works on localhost, have you deployed it successfully on the production or just copy-pasta? Attention to your .env file and file permissions
I have view.blade.php like this
....
<meta name="_token" content="{!! csrf_token() !!}" />
....
<script>
jQuery(document).ready(function ($) {
$.ajaxSetup({
headers: {'X-CSRF-Token': $('meta[name="_token"]').attr('content')}
});
$.post('/download_file', {file_name: "abc"}, function (data) {
console.log(data);
});
});
</script>
In routes.php I already set route
Route::post('/download_file' , 'DownloadController#load_file');
In DownloadController.php I write code for create and download file like this
<?php
namespace App\Http\Controllers;
use Response;
use File;
use Illuminate\Http\Request;
class DownloadController extends Controller {
public function load_file(Request $request){
if($request->file_name === "abc"){
File::put("files/abc.txt", "This is content in txt file");
$file_abc = public_path() . "/files/abc.txt";
return Response::download($file_abc);
}
}
}
File abc.txt is create on server but browser doesn't download it after $.post call. In console.log(data) I see content of file. Thank for any help.
Laravel provides a response type download out of the box. Official documents states :
The download method may be used to generate a response that forces the user's browser to download the file at the given path. The download method accepts a file name as the second argument to the method, which will determine the file name that is seen by the user downloading the file. Finally, you may pass an array of HTTP headers as the third argument to the method:
return response()->download($pathToFile);
//OR
return response()->download($pathToFile, $name, $headers);
so your load_file function should response the file to download like this, no need to add jquery for this.
Scenario:
I want via ajax send chosen words to a Controller, but I am getting all the time "Internal server error" After a full Sunday of struggling and swearing I think I know why this is happening and how it could be solved. I dont have that problem if I send the word via a ordinary Form and Submit button. The issue is the mis-marriage between Ajax and the CSRF token mismatch.
So here is the Ajax snippet>
<script>
$(document).ready(function(){
$('.choose-language').on('click', function(e){
e.preventDefault();
var selectedlanguage = $(this).data('value');
alert(selectedlanguage); // it gets the value alright on clicking the paragraph
$.ajax({ // so I want to send it to the controller
type:"POST", // via post
url: 'language', // correct?
data:{'locale': selectedlanguage},
}); // HERE FINISHES THE $.POST STUFF
}); //HERE FINISHES THE CLICK FUNCTION
}); // HERE FINISHES THE DOCUMENT AND READY STUFF
</script>
Here is the HTML
<div class="choose-language">
<p class="choose-language" id="english" data-value="en" >English</p>
<p class="choose-language" id="spanish" data-value="es" >Spanish</p>
</div>
Here is the Routes:
Route::get('/', function () {
return view('welcome');
});
Route::post('language', array(
'as' =>'language',
'uses' => 'LanguageController#changelanguage'
));
And the Controller
class LanguageController extends Controller
{
public function changelanguage()
{
Session::set('locale', \Input::get('locale'));
return \Redirect::back();
}
}
So, if I go to Middleware, I can see there is a File called VerifyCSRFToken.php and inside that file there is this:
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
// code here
];
}
So, I am sure that should fix it, but I wrote 'language' where the // code here is and did not make any difference. There must be other bugs..
Thanks a lot.
UPDATE:
I have found a typo (apologies I had written redirecto instead of redirect) and I m not getting errors anymore.
Add the CSRF token to your HTML head:
<meta name="csrf-token" content="<?= csrf_token() ?>">
Add this to your JS file:
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
});
The CSRF should now pass the middleware
There was one annoying thing in this HMTL code: as you see the class "choose-language" was repeated also in the div, which caused the click to be repeated twice, and the second time without actually sending a value. So I have left it there for you to see, but you do need to remove it. Once you remove it from the div, the code works correctly. So this responds and solves the issue of Ajax and Laravel CSRF. I have tested the output of the controller and it gets the word sent. Before Laravel 5.0 you had to go through a lot of hacking in the code and fix the bugs and add also conditionals in the filter to let decide when CSRF was or not coming from an Ajax, besides having to add code in every header of every page where you had Ajax sending something etc.
Now, in Laravel 5.0 you just do as I wrote in the code and you are done.
I am having a view with 2 buttons in my codeigniter view:
<div class="btn-main col-md-3 col-md-offset-3">
<button id="simu-mono" type="button" class="btn btn-default">SIMULATION MONO SITE</button>
</div>
<div class="btn-main col-md-3">
<button id="simu-multi" type="button" class="btn btn-default">SIMULATION MULTI SITE</button>
</div>
I would like to call another a controller to launch then a view when the button is clicked
I tried out to call the controller simu_mono by javascript, putted on /controller/simu_mono.php but doesn' t work
$(document).ready(function(){
$("#simu-mono").click(function(){
type:'GET',
url:'simu_mono'
});
$("#simu-multi").click(function(){
});
});
simu_mono.php:
<?php
class simu_mono extends CI_Controller {
public function index()
{
$this->load->view('simu_mono');
echo 'Hello World!';
}
}
?>
Thanks for your helps
Cheers
Please, if u want to redirect only use following code:
$(document).ready(function(){
$("#simu-mono").click(function(){
window.location = base_url + "/simu_mono";
});
$("#simu-multi").click(function(){
window.location = base_url + "/simu_multi";
});
});
Note that you might need base_url, use this snippet to load base_url in JavaScript variable
<script>
base_url = <?= base_url()?>
</script>
put code above in some kind of view that is loaded always (before any other JavaScript code is executed)
Additional step would be to set up routes that take care of ugly underscore symbol (_)
something like:
routes.php
$route['simu-mono'] = "simu_mono";
$route['simu-multi'] = "simu_multi";
this way you go to your page and controller following way: yourserver.ufo/simu-mono and yourserver.ufo/simu-multi
You're not doing any class of AJAX call within your javascript. I assume you're using jQuery, so, your call should be something like:
$("#simu-mono").click(function(){
$.ajax({
url: "http://your-url.com/controller/method",
type: 'post', // <- Or get option, whatever you prefer
dataType: 'json', // <- This is important to manage the answer in the success function
//data: { param1: "value1", param2: "value2"}, <- You could add here any POST params you wanted
success: function(data){
if (data.view) {
$('#here_view').html(data.view); // <- '#here_view' would be the id of the container
}
if (data.error){
console.log(data.error);
}
}
});
});
This will call your method, where you will have to indicate you want to pass the view:
<?php
class simu_mono extends CI_Controller {
public function index()
{
$return = array(
'view' => $this->load->view('simu_mono')
);
echo json_encode( $return );
}
}
?>
json_encode will allow you easily pass vars and data from PHP to your javascript, and manage them in the client view. As you see in the javascript, I added data.error, this is just in case you'll have more logic, maybe change the view you're sending, send an error if you sent data and want to control them, etc.
Of course, in your javascript you could take the url from the clicked button, and in data.view parat of the success function, you may print in the screen a modal, send the view to a container, whatever you wanted, XD