I'm trying to parse the data that I send from my ajax form. But for some reason I cannot extract the information from the form in the php controller. Here's what I'm doing.
Here is the html:
<div style="margin-top: 100px;">
<h2>Character settings</h2>
<table class="table table-striped table-bordered table-hover">
<tr>
<th>Name</th>
<th>Map</th>
<th>Move</th>
</tr>
#foreach($chars as $char)
<tr>
<td>{{$char['name']}}</td>
<td>{{$char['map']}}</td>
<td>
{{Form::open(array('action' => 'UsersController#move', 'class' => 'mover'))}}
<input type="hidden" name="charID" class="charID" value="{{$char['id']}}" />
<button type="submit" class="btn btn-small btn-info">Move</button>
{{Form::close()}}
</td>
</tr>
#endforeach
</table>
Here is the javascript ajax processing:
$('#mover').on('submit', function(e){
e.preventDefault();
var $form = $( this ),
method = $form.attr( "method" );
$.ajax({
url: "{{action('UsersController#move')}}",
dataType: "json",
data: $form.find('.charID').val(),
type: method,
success: function (response) {
console.log(reponse['test']);
}
});
});
Here is the controller:
public function move() {
if(Auth::check()) {
Log::info(Input::get('charID')); //When I check the logs this is blank
$person = Character::where('id', '=', Input::get('charID'))->first();
$person->map = 100000000;
$person->save();
$response = array('status' => 'success', 'text' => 'Your character has been moved!');
return Response::json($response);
exit();
}
else {
return Redirect::action('PageController#showHome');
}
}
When I check the console log on submit I see the data "charID", so its being extracted by the form correctly, but I can't seem to get it in the laravel controller. Strange thing is I use the Input::get() function in other parts of my controller. So it's just this function.
Any help appreciated!
You're accessing response[test] instead of response[text].
Other things of note:
Your use of exit(); is redundant and will never be hit because you are returning above it.
Also, exit is a language construct and it can be called without parens if no status is passed. So if you are to use it without an argument, just use exit;.
Your ajax method could be optimised a bit more and it seems you also have another problem with your data, which needs to be sent as a key value pair.
You could do it as an inline string in the form of a GET request, or as an object like { "charID": $(this).find("input[name=charID]").val() },.
$("#mover").on("submit", function (e) {
e.preventDefault();
$.ajax({
"url": this.action, // <-- we can use native javascript
"dataType": "json",
"data": $(this).serialize(), // <-- collects your form data
"type": this.method,
"success": function (data) {
if (data.success !== "undefined" && data.success === 200) {
console.log(data.text);
}
}
});
});
I would recommend against using the Form helper class. It isn't very readable after-the-fact. You don't save that much time using it compared to writing out the HTML form definition anyway.
Let's optimise your controller so it's easier to understand as well:
public function move ()
{
if (Auth::check()) {
Log::info(($charID = request('charID')));
$person = Character::where('id', '=', $charID)->first();
$person->map = 100000000;
$person->save();
return response()->json([
'success' => 200, // success
'text' => 'Your character has been moved!'
]);
} else {
return response()->json([
'success' => 401 // unauthorised
]);
}
}
For a variable you're accessing more than once, I use a neat trick with parens (). If you wrap an assignment in parens e.g. ($charID = request('charID')) you can still use it's output in-line, with the added benefit that you now have access to it further into your script.
I'm opting for the helper methods like request() and redirect() instead of their class counterparts and the use of array() is a bit old hat - but that's just my opinion - I'd use square brackets [].
Your response when the user isn't authenticated is useless here assuming this controller action is only meant to handle posts from AJAX requests (if I'm not mistaken). Since it can't force your asynchronous request to redirect you. Instead we return the proper HTTP response code 401 to represent that the user was unauthorised.
You could also look up PSR-2 standards for your code structure, as that is what is used as an industry standard nowadays.
Lastly, if you are using the web middleware (with CSRF protection) on the controller here. You need to send a CSRF token with the request. You can do that by popping {{ csrf_field() }} into the form. The form helper may be doing this for you.
But another problem you would have stumbled into if you were not using $(this).serialize() in the AJAX setup is that the _token field would never have been sent along with the request.
Try
data: { 'charID': $form.find('.charID').val() },
as it is now you're only sending the value, there's no way PHP let alone Laravel will know its name
I see a few potential issues with this code.
You're initializing your form with 'class' => 'mover', but your jquery is looking for $('#mover') - So your form tag has the class 'mover' but your jquery expects an id 'mover'
You're setting the ajax method to $form.attr( "method" ); but I'm not sure if method is getting set at all in your form tag? Why not just set your ajax type/method to POST since that's the appropriate method for posting a form?
try to change as below,
$.ajax({
url: "{{action('UsersController#move')}}",
dataType: "json",
data: $form.serialize(),
type: 'post',
success: function (response) {
console.log(reponse['test']);
}
});
Related
I've Signup form in my website. It was properly submitting before. Now I wanted to submit my form using ajax and wanted to return a variable from controller into JSON that I will use into blade file.
The form is submitting and values are showing into database but after redirection, it returns error.
Undefined variable: seller in report blade
I tried to decode my variable to make it work but still the same error.
How would I make it work?
Report-Blade
#foreach(json_decode($seller, true) as $row)
<a href="{{route('Report', $row->id) }}" >
{{ __('Show Report of ')}} {{$row->car_title}}
</a>
#endforeach
Controller
$seller = Sellers::take(1)->latest()->get();
return response(view('report',array('seller'=>$seller)),200, ['Content-Type' =>
'application/json']);
JavaScript
$("#submit-all").click(function(e){
e.preventDefault();
var _token = $('input[name="_token"]').val();
$.ajax({
type: "post",
url: "{{ route('form_for_private_sellers') }}",
data : $('#msform').serialize() + "&_token=" + _token,
dataType: 'JSON',
beforeSend: function(){
// Show loading image
$("#se-pre-con").show();
},
success: function(data) {
window.location = "http://127.0.0.1:8000/report/";
},
complete:function(data){
// Hide loading image
$("#se-pre-con").hide();
}
});
});
As understood from your comments,
window.location = "http://127.0.0.1:8000/report/";
will hit the route
Route::get('/report', function () {
return view('report');
})->name('private_seller_report');
Report blade expects a variable named $seller, and it is not being sent from the route. You would need to change the route to something similar to this:
Route::get('/report', function () {
$sellers = Seller::get(); //your logic
return view('report', ['seller' => $sellers]);
})->name('private_seller_report');
Alternatively you can point the route to a method in a controller if you want to avoid bulking up your routes.
you need two route for this
first for rendering blade
return view('report');
and the second for fetch seller
$seller = Sellers::latest()->take(1)->get();
return $seller
As you can see the js and html code below are in the same page. When I press the button, ajax will return Item json. My goal is to know whether it is possible to return the json response with the $item variable at the same time in test function. This is because I wanted to use the $item variable in view blade. If so, then how to do it?
Controller
public function index()
{
$furniture = Furniture::all();
return view('index', compact('furniture'));
}
public function test(Request $request)
{
$item = Item::findOrFail($request->item_id);
return response()->json([
'data' => [
'success' => $item,
'key1' => "hello",
'key2' => "world",
]
]);
}
JS
$(document).on('click', '.edit_modal', function() {
var item_id = this.id;
$.ajax({
type: 'POST',
url: "{{ URL::route('test') }}",
headers: {'X-CSRF-TOKEN': '{{ csrf_token() }}' },
data: { "item_id" : item_id},
success: function(data){
if(data.data.success){
$('#edit_id').val(data.data.success.id); // this will output the id eg. 1
$('#edit_desc').val(data.data.success.description); // this will output the description eg. "hi there"
console.log(data.data.key1); // this will output "hello"
console.log(data.data.key2); // this will output "world"
}
}
});
View
<button type="button" class="edit_modal btn btn-primary" id="{{ $furniture->item_id }}">Button</button>
Blade views are rendered server side. The rendering has completed by the time the view is displayed on your browser.
When you run an AJAX request, there is no further rendering in the current view (by Blade or PHP). Therefore, you cannot pass additional variables through AJAX to the blade template.
If you really want this functionality, it seems strange that you are using AJAX to begin with. You should just submit the form normally and render a new view from the server side with the $item passed to that view. When using AJAX, you'll want to return a response Javascript can understand (JSON), not that PHP can understand, since Javascript will be rendering the response on the client side.
Read more about the difference between server side and client side programming here: What is the difference between client-side and server-side programming?
I am making an ajax post request to controller where i fetch some details, now i don't want to send control back to ajax rather i want to pass data to some view.
return response()->json(['students' => $students]);
instead i want to do like this
return view('frontend.student.leadThanksPage',compact('students'));
ajax call
$.ajax({
type:"POST",
url:"{{ route('check.student.detail') }}",
data:$(this).serialize(),
success: function(data){
//....... },
error: function(data){
//........ }
});
and my route is
Route::post('fetch/student/detail', [ 'as'=>'check.student.detail',uses' => 'Frontend\Student\StudentController#fetchStudentDetail' ]);
Yes, You can render a view in the Laravel by returning view.
You need to configure the route whether the AJAX request is 'get' or 'post' like below,
Route::post('/ajax/GetContent', array(
'uses' => 'AjaxController#loadContent'
));
And you can do the implementation in your controller,
public function loadContent(Request $request )
{
// you can do your coding
return view('frontend.student.leadThanksPage')->with('students', $students);
}
}
Nothing needs to return in your Ajax response.
Happy Coding,
AK
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!
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.