Send data from Ajax to Laravel controller. Vuejs - javascript

I have a little moment that I don't understand because I'm new to development.
I'm collecting data from multi step form and want to handle all form inputs at one ajax request on my controlle. I did it successfully, but can't figure out how to use data from $request if it's an array from ajax.
I can use if it $request->input('name') but in my case I need something like $request->input('firstGrant.issue_date') because of my data format. Please tip me which way to dig.
My method:
submitCompany() {
axios.post('/onboarding', {
name: this.step1.name,
type: this.step1.type,
shares_amount: this.step2.shares_amount,
par_value: this.step2.par_value,
firstGrant: {
issue_date: this.step3.firstGrant.issue_date,
certificate: this.step3.firstGrant.certificate,
share_price: this.step3.firstGrant.share_price,
shares_amount: this.step3.firstGrant.shares_amount
}
})
.then(function (response) {
console.log(response);
alert('Information saved!');
})
.catch(function (error) {
console.log(error);
alert('Wrong!');
});
}
My Controller:
public function store(Request $request)
{
$userId = Auth::user()->id;
$issueDate = $request->input('firstGrant.issue_date'); //How to do it right way?
$certificate = $request->input('firstGrant.certificate');//How to do it right way?
$sharePrice = $request->input('firstGrant.share_price');//How to do it right way?
$sharesAmount = $request->input('firstGrant.shares_amount');//How to do it right way?
$equityGrant = EquityGrant::create([
'user_id' => $userId,
'share_id' => 91,
'vesting' => 0,
'status' => 'active',
'issue_date' => $issueDate,
'certificate' => $certificate,
'share_price' => $sharePrice,
'shares_amount' => $sharesAmount,
]); }

You might have to configure axios to send a header along with every request that will make Laravel recognize the request as being XHR. Once it does, the $request->input('x.y') statements should work.
Object.assign(axios.defaults.headers, {
'X-Requested-With': 'XMLHttpRequest',
});
If this still does not work you might also want to check whether axios properly includes the CSRF-token in a request header.

Related

Axios get call in Vue3 not working, although curl and javascript work as expected

I'm trying to make an API call from my Vue3 app. The prepared API has an endpoint like http://localhost:8888/api/dtconfigsearch, where one needs to pass a json payload like { "Modelname": "MyFancyModel"} to get the full dataset with the given modelname. Pure get functions without a payload / a body do work from my Vue3 project to the golang backend, but I'm having problems with passing a payload to the backend.
Test with curl -> ok
$ curl -XGET localhost:8888/api/dtconfigsearch -d '{"Modelname" : "MyFancyModel" }'
{"ID":4,"Modelname":"MyFancyModel","ModelId":"96ee6e80-8d4a-b59a-3524-ced3187ce7144000","OutputTopic":"json/fancyoutput"}
$
This is the expected output.
Test with javascript ok
Source file index.js:
const axios = require('axios');
function makeGetRequest() {
axios.get(
'http://localhost:8888/api/dtconfigsearch',
{
data: { Modelname : "MyFancyModel" },
headers: {
'Content-type' : 'application/json'
}
}
)
.then(resp => {
console.log(resp.data)
})
.catch(err => {
console.log(err)
})
}
makeGetRequest()
Output
$ node index.js
{
ID: 4,
Modelname: 'MyFancyModel',
ModelId: '96ee6e80-8d4a-b59a-3524-ced3187ce7144000',
OutputTopic: 'json/fancyoutput'
}
$
Here, I also get the desired output.
Test within Vue fails :-(
Source in the Vue one file component:
onSelection(event) {
let searchPattern = { Modelname : event.target.value }
console.log(event.target.value)
console.log("searchPattern = " + searchPattern)
axios.get("http://localhost:8888/api/dtconfigsearch",
{
data : { Modelname : "Windshield"},
headers: {
'Content-type' : 'application/json',
'Access-Control-Allow-Origin': '*'
}
})
.then(response => {
console.log(response.data)
})
.catch(err => {
console.log(err)
alert("Model with name " + event.target.value + " not found in database")
})
},
Output in browser:
In the image you can see in the terminal log on the right side that the backend is not receiving the body of the API call. However, in the browser information of the call there is content in the config.data part of the object tree, which is the payload / the body. The only thing that bothers me that it is not a json object, but stringified json, although it was entered as json object. According to the documentation, the parameter name (data) in the call should be correct to hold the body content of the api call.
I've tried different header information, looked if it could be a CORS issue, what it isn't to my opinion, exchanged key data with body, used axios instead of axios.get and adapted parameter, all without success. The version of the axios library is 0.27, identical for Vue and vanilla javascript. After checking successfully in javascript, I was sure that it would work the same way in Vue, but it didn't.
Now I'm lost and have no further ideas how to make it work. Maybe someone of you had similar issues and could give me a hint? I'd be very grateful for some tipps!!

How to get JSON in Laravel from vue.js axios POST?

I have some problem with receiving JSON data from vuex with axios in my Laravel Backend.
I have vuex store like this, and I want to send it to backend on click.
order: {
delivery_id: null,
user_id: null,
is_active: true,
bill: null,
name: null,
surname: null,
father_name: null,
phone: null,
payment_type: 'cash',
delay: null,
cashback_paid: null,
card: null,
payment_screenshot: null,
cart: null,
}
In vue component I have this method:
sendOrder() {
let order = this.$store.state.order.order;
console.log(order)
axios
.post('/api/products', order, {
header: {
'Content-Type': 'application/json'
}
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
})
}
And this is my pretty simple Laravel Controller:
$test = json_decode($request->getContent(), true);
$test = $test['payment_type'];
return response($test);
But when I'm doing this POST request, I'm receiving empty data in response.
Also, I've tried to check my API with Postman, and it's working fine. I just send request, then go to F12 > Network > find my request and copy Request Payload source data. Then I've pasted it into Postman body (raw, json) and make request with this data to same url (http://localhost:8000/api/orders), and its return 'cash' as expected. So I decided, that it's vue.js or axios problem, but I have no idea how to fix that. Thank you!
UPDATED
I already have tried to remove Content-Type from axios, JSON.stringify order and had the same result - empty data on response.
I think, before you use order in axios you should stringify the JSON data:
let order = JSON.stringify(this.$store.state.order.order);
Second part of the answer after some comments:
Are you sure about the routes file? I would call the controller from the web.php file (same folder) with a declared function (for example mytest), like this:
Route::post('/api/products', 'ProductController#mytest');
and put your controller logic in that function:
public function mytest()
{
$test = json_decode($request->getContent(), true);
$test = $test['payment_type'];
return response($test);
}
If that doesn't work (also in combination with JSON.stringify), my only idea is a typo in your "pretty simple Laravel Controller" ;)...

Vue js parameter can't get in route

I use VueJS and laravel but now I can't get parameter value, please help me to solve this problem.
my VueJS code:
getTestData:function () {
let config = {
params: {
id: 1
}
};
axios.post('{{ route('get_user_data') }}', config)
.then(function (response) {
console.log(response);
// app.posts=response.data;
})
.catch(error => {
})
},
My Controller code:
public function testData(Request $request)
{
// how to get this value?
}
My route
Route::post('get-user-data','TestController#testData')->name('get_user_data');
You don't actually need a post request to get some values out of database. A get request would be more suitable.
You need to have the param in the route definition
Route::get('get-user-data/{id}','TestController#testData')->name('get_user_data');
//If you want to use post route
Route::post('get-user-data/{id}','TestController#testData')->name('get_user_data');
Then in controller method you can get the value out of the request
public function testData(Request $request)
{
$id = $request->route('id');
}
params are the URL parameters to be sent with the request
You could retrieve input from query string in your controller as:
public function testData(Request $request)
{
$id = $request->query('id');
}

JS JSON Error 400, Value could not be converted to List

I'm working on a college project and I'm at the finish line but I lack the knowledge to fix one bug and a few hours of googling hasn't brought me anywhere closer so this is my last resort.
I'm making a web-based quiz using JS AJAX and C# but the 'post' method always returns a error 400.
The JSON value could not be converted to
System.Collections.Generic.List`1[FrontEndGevorderdQuiz.Web.Models.QuizAntwoord].
I put all the answers the users inputs in an array antwoorden[] and want to post this to my QuizController.cs so it can calculate how much answers are correct and so it can give me back the correct percentage.
My POST-Method
fetch("/api/quiz",
{
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(antwoorden)
})
.then((antwoorden) => {
return antwoorden.json();
})
.then((data) => {
document.getElementById("extraDisplay").innerText = JSON.stringify(data);
})
.catch((error) => {
console.error(error);
})
My QuizController Function
public QuizResultaat Post([FromBody] IEnumerable<QuizAntwoord> antwoorden)
{
int aantalJuisteAntwoorden = 0;
foreach (QuizAntwoord antwoord in antwoorden)
{
QuizVraag vraag = _vragen
.FirstOrDefault(v => v.Id == antwoord.VraagId);
if (vraag.JuisteAntwoordIndex == antwoord.GekozenAntwoordIndex)
{
aantalJuisteAntwoorden++;
}
}
float scorePercentage = ((float)aantalJuisteAntwoorden / (float)_vragen.Count) * 100;
return new QuizResultaat()
{
Percentage = scorePercentage
};
}
Any help is much appreciated. Thank you for your time.
The error message 400 Bad Request mean :
The 400 (Bad Request) status code indicates that the server cannot
or will not process the request due to something that is perceived
to be a client error (e.g., malformed request syntax, invalid
request message framing, or deceptive request routing).
HTTP standards
and the message :
The JSON value could not be converted to
System.Collections.Generic.List ...
Indicate a problem with the model,
you can start to double check if the data that you are sending are same with the model in controller is waiting for ...
If you need more help, you can add your model and your javascript function that create antwoorden
Also here is a link that can help you : AJAX Posts In Razor Pages And HTTP 400 Errors
I think the issue may in your antwoorden.
You can see my example.
public class Binder
{
public int Id { get; set; }
public string Name { get; set; }
}
The antwoorden in ajax example,you need to notice the antwoorden format:
var antwoorden=
[
{ id: 1,name:"A" },
{ id: 2, name: "B"},
{ id: 3, name: "C"}
]
fetch("/Home/Test",
{
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(antwoorden)
})
.then((antwoorden) => {
return antwoorden.json();
})
.then((data) => {
document.getElementById("extraDisplay").innerText = JSON.stringify(data);
})
.catch((error) => {
console.error(error);
})
Action:
[HttpPost]
public IActionResult Test([FromBody] IEnumerable<Binder> antwoorden)
{
//....
}
Test Result:

Why use 'php://input' over the POST superglobal - Stripe SCA example

Stripe are soon to roll out their use of Strong Customer Authentication for payments with their platform. There's a fairly substantial section in their documentation about it.
https://stripe.com/docs/payments/payment-intents/quickstart#manual-confirmation-flow
The process has the following flow:
The vanilla PHP implementation is like so:
<?php
# vendor using composer
require_once('vendor/autoload.php');
\Stripe\Stripe::setApiKey(getenv('STRIPE_SECRET_KEY'));
header('Content-Type: application/json');
# retrieve json from POST body
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
$intent = null;
try {
if (isset($json_obj->payment_method_id)) {
# Create the PaymentIntent
$intent = \Stripe\PaymentIntent::create([
'payment_method' => $json_obj->payment_method_id,
'amount' => 1099,
'currency' => 'gbp',
'confirmation_method' => 'manual',
'confirm' => true,
]);
}
if (isset($json_obj->payment_intent_id)) {
$intent = \Stripe\PaymentIntent::retrieve(
$json_obj->payment_intent_id
);
$intent->confirm();
}
generatePaymentResponse($intent);
} catch (\Stripe\Error\Base $e) {
# Display error on client
echo json_encode([
'error' => $e->getMessage()
]);
}
function generatePaymentResponse($intent) {
# Note that if your API version is before 2019-02-11, 'requires_action'
# appears as 'requires_source_action'.
if ($intent->status == 'requires_action' &&
$intent->next_action->type == 'use_stripe_sdk') {
# Tell the client to handle the action
echo json_encode([
'requires_action' => true,
'payment_intent_client_secret' => $intent->client_secret
]);
} else if ($intent->status == 'succeeded') {
# The payment didn’t need any additional actions and completed!
# Handle post-payment fulfillment
echo json_encode([
"success" => true
]);
} else {
# Invalid status
http_response_code(500);
echo json_encode(['error' => 'Invalid PaymentIntent status']);
}
}
?>
The necessary JavaScript for its use with Stripe Elements looks like this:
var cardholderName = document.getElementById('cardholder-name');
var cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', function(ev) {
stripe.createPaymentMethod('card', cardElement, {
billing_details: {name: cardholderName.value}
}).then(function(result) {
if (result.error) {
// Show error in payment form
} else {
// Otherwise send paymentMethod.id to your server (see Step 2)
fetch('/ajax/confirm_payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_method_id: result.paymentMethod.id })
}).then(function(result) {
// Handle server response (see Step 3)
result.json().then(function(json) {
handleServerResponse(json);
})
});
}
});
});
function handleServerResponse(response) {
if (response.error) {
// Show error from server on payment form
} else if (response.requires_action) {
// Use Stripe.js to handle required card action
stripe.handleCardAction(
response.payment_intent_client_secret
).then(function(result) {
if (result.error) {
// Show error in payment form
} else {
// The card action has been handled
// The PaymentIntent can be confirmed again on the server
fetch('/ajax/confirm_payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_intent_id: result.paymentIntent.id })
}).then(function(confirmResult) {
return confirmResult.json();
}).then(handleServerResponse);
}
});
} else {
// Show success message
}
}
In my own project I'm using Laravel which is entirely based on the MVC architecture and it fairly nice to you when it comes to most things.
I have tried to refactor a little but I have a question.
Why would you use this line $json_str = file_get_contents('php://input'); over just trying to grab the posted variables from the Request object used in Laravel?
I also read the following article from the PHP Manual:
https://www.php.net/manual/en/wrappers.php.php
To be perfectly honest I've been away from procedural PHP so this has confused me to no end.
Why use 'php://input' over the POST superglobal - Stripe SCA example
The body is encoded as JSON. You can tell because the next line explicitly decodes it.
PHP doesn't understand application/json requests. It will only populate $_POST if the data is encoding using the application/x-www-form-urlencoded or multipart/form-data formats.
Why would you use this line $json_str = file_get_contents('php://input'); over just trying to grab the posted variables from the Request object used in Laravel?
If you were using Laravel, there's no reason to do that.
Since there is no sign of anything Laravel in the example you gave, it is presumably not written with the intention of introducing a dependency on Laravel.

Categories

Resources