Symfony 5 / Request Response : Get data with Ajax - ajax

when I try to get data in ajax, the returned object is empty
I send the id of the data I want to get in js :
function selectMessage(id) {
$.ajax({
url: '{{ path('back_translation_update') }}',
method: 'GET',
data: {id: id}
}).done(function (response) {
console.log(response)
})
}
$('.updateMessage').click(function (evt) {
evt.stopPropagation()
selectMessage($(this).data('id'))
})
in the controller I look for the data to return :
/**
* #Route("/update", name="back_translation_update", methods="GET|POST")
*/
public function getById(Request $request): Response
{
if ($request->isXMLHttpRequest()) {
$id = $request->get('id');
// dd($id);
$message = $this->translationService->getTranslationById($id);
// return new JsonResponse(['data' => $message]);
$response = new Response();
$response->setContent(json_encode([
'data' => $message,
]));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
}
I use a service because with the repository I get an error: getById () must be an instance of Symfony\Component\HttpFoundation\Response
with :
$repositoryMessage = $this->em->getRepository(TranslationMessage::class);
$message = $repositoryMessage->findOneBy(['id' => $id]);
so the service will look in the database:
public function getTranslationById($translation_id)
{
$query = $this->em->createQueryBuilder()
->from(TranslationMessage::class,'message')
->select('message')
->where('message.id = ?1')
->setParameter(1, $translation_id);
$message = $query->getQuery()->getResult();
// dd($message);
return $message;
}
all the dd() give the expected values:
into getById(): the id of the row sought
into getTranslationById(): the sought object
but in the XHR, data contains an empty object: uh:
same with a new JsonResponse, commented here
what did I miss? help

Use Aurowire to get messageRepository object and use $this->json() to return JsonResponse
/**
* #Route("/update", name="back_translation_update", methods="GET|POST")
*/
public function getById(Request $request, TranslationMessageRepository $messageRepository): JsonResponse
{
$id = $request->query->get('id');
$message = $messageRepository->find($id);
if(!$message) { return new NotFoundHttpException(); }
return $this->json([
'success' => true,
'data' => $message
]);
}
Define success function instead of done function
function selectMessage(id) {
$.ajax({
url: "{{ path('back_translation_update') }}",
method: 'GET',
data: { id: id }
success: function(data) {
console.log(data)
}
})
}

Related

How to solve SyntaxError: Unexpected token < in JSON at position 0 in Paypal checkout in Laravel

I am doing Paypal integration in Laravel. I have used composer require srmklive/paypal to install the srmklive/paypal package in this project.
When I press the PayPal button, I get this error:
Here is my code:
code from blade file:
paypal.Buttons({
createOrder: function(data, actions) {
return fetch('api/paypal/order/create/', {
method: 'post',
body:JSON.stringify({
"value":100
})
}).then(function(res) {
return res.json();
}).then(function(orderData) {
return orderData.id;
});
},
onApprove: function(data, actions) {
return fetch('/api/paypal/order/capture/', {
method: 'post',
body: JSON.stringify({
orderID: data.orderID
})
}).then(function(res) {
return res.json();
}).then(function(orderData) {
var errorDetail = Array.isArray(orderData.details) && orderData.details[0];
if (errorDetail && errorDetail.issue === 'INSTRUMENT_DECLINED') {
return actions.restart();
}
if (errorDetail) {
var msg = 'Sorry, your transaction could not be processed.';
return alert(msg); // Show a failure message (try to avoid alerts in production environments)
}
});
}
}).render('#paypal-button-container');
code from paymentController:
class PaymentController extends Controller
{
public function create(Request $request){
$data = json_decode($request->getContent(), true);
$provider = \PayPal::setProvider();
$provider->setApiCredentials(config('paypal'));
$token = $provider->getAccessToken();
$provider->setAccessToken($token);
$price = Plan::getSubscriptionPrice($data['value']);
$description = Plan::getSubscriptionDescription($data['value']);
$order = $provider->createOrder([
"intent" => "CAPTURE",
"purchase_units" => [
[
"amount" => [
"currency_code" => "USD",
"value" => $price
],
"description" => $description
]
]
]);
return response()->json($order);
}
public function capture(Request $request) {
$data = json_decode($request->getContent(), true);
$orderId = $data['orderID'];
$provider = \PayPal::setProvider();
$provider->setApiCredentials(config('paypal'));
$token = $provider->getAccessToken();
$provider->setAccessToken($token);
$result = $provider->capturePaymentOrder($orderId);
return response()->json($result);
}
}
How can I solve this error?
The route api/paypal/order/create/ is returning/outputting text that is not JSON, such as an HTML error page or something else that begins with an HTML tag.
The route must only output JSON, and must contain a valid id from the PayPal API.

The Ajax pagination to my account not run

I would like to create an Ajax pagination of my articles in my account, here is my code that I created but it does not work I do not know how to do.
MyaccountController
public function viewProfile($username) {
if($username) {
$user = User::where('username', $username)->firstOrFail();
} else {
$user = User::find(Auth::user()->id);
}
return view('site.user.account', [
'user' => $user,
'articles' => $user->articles()->orderByDesc('created_at')->paginate(4),
]);
}
I would like to have the javascript code
$(document).ready(function () {
$(document).on('click','.pagination a',function(e){
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
var url = $(this).attr('href');
$.ajax({
url: url,
method: 'GET',
data: {},
dataType: 'json',
success: function (result) {
if (result.status == 'ok'){
$('#userListingGrid').html(result.listing);
}else{
alert("Error when get pagination");
}
}
});
return false;
})
});
I would have a check on your controller for an ajax request like so:
public function viewProfile($username) {
if($username) {
$user = User::where('username', $username)->firstOrFail();
} else {
$user = User::find(Auth::user()->id);
}
if(request()->ajax()){
return response()->json(['user' => $user, 'articles' => $user->articles()->orderByDesc('created_at')->paginate(4);
}
return view('site.user.account', [
'user' => $user,
'articles' => $user->articles()->orderByDesc('created_at')->paginate(4),
]);
}
Then you don't have to load your view every time and you can let your javascript functions take care of the DOM manipulating of the results. Not sure if that's what you are looking for. I know that you would probably need a {{$articles->links()}} at the end of your view to go through each page.

How get data from ajax object in controller Laravel?

In ajax I have 3 objects 'emp_info, leave_detail, and leave_items' in controller I don't know how to get record of each object. Could you help me please?
$.ajax({
type: 'POST',
url: '/leave-request-initiator/store',
data: {_token: $('#_token').val(), emp_info: $('#frm_emp_info').serialize(), leave_detail: $('#frm_leave_detail').serialize(), leave_items: leave_items},
beforeSend: function () {
console.log('sending');
},
success: function (response) {
console.log(response);
}
});
Controller.
public function store(Request $request)
{
$data = $request->all();
foreach ($data->emp_info as $item){
$empcode = $item['EMPCODE'];
}
$leaveDetail = new HREmpLeave([
'EMPCODE' => $empcode,
'LEAVECODE' => $request->get('LEAVECODE'),
'FROMDATE' => $request->get('FROMDATE'),
'TODATE' => $request->get('TODATE'),
'BACKTOWORKON' => $request->get('BACKTOWORKON'),
'NODAY' => $request->get('NODAY'),
'REMARK1' => $request->get('REMARK1')
]);
$leaveDetail->save();
}
Change this:
$data = $request->all();
foreach ($data->emp_info as $item){
$empcode = $item['EMPCODE'];
}
to this:
$emp_info = parse_str($request->emp_info); //parse into a array
$empcode = $emp_info['EMPCODE'];

Ajax successful when laravel authentication fails

I have a problem I have two forms on regular form and one ajax processed form. The regular form works as needed but the ajax form passes as successful even when authentication of the server side fells.
My loginHandler function is below
public function handleLogin(Request $request) {
// init auth boolean to false
$auth = false;
// run validation rules
$validator = User::validation($request->all(), User::$login_validation_rules, User::$login_error_messages);
// get credentials
$credentials = $request->only('email','password');
if($validator->fails()) {
return back()
->withErrors($validator)
->withInput();
}
$credentials = array_merge($credentials,['activated' => 1]);
// get remember from request
$remember = $request->has('remember');
if (\Auth::attempt($credentials, $remember)) {
$auth = true;
}
if($request->ajax()) {
$response = response()->json([
'auth' => $auth,
'intended' => \URL::route('home')
]);
return $response;
}
return redirect()->intended('/');
}
My ajax code is this
$('#login-nav').validate({
rules : {
email : {
required : true,
email : true
},
password : {
required : true
}
},
messages : {
email : {
required : '<div class="alert-danger alert-validation">Email is a required field.</div>',
email : '<div class="alert-danger alert-validation">Please enter a valid Email.</div>'
},
password : {
required : '<div class="alert-danger alert-validation">Password is a required field.</div>'
}
},
submitHandler: function (form){
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('value')
},
type: $(form).attr('method'),
url: $(form).attr('action'),
data: $(form).serialize(),
dataType: 'json',
success: function (data) {
var html = '<div class="alert alert-success">Login Successful</div>';
$('#loginMsg').html(html);
return window.location = '/';
},
error: function (data) {
var html = '<div class="alert alert-danger">Email/Password is invalid</div>';
$('#loginMsg').html(html);
}
});
return false;
}
I would like to have the same behavior as my regular non ajax form. but instead of going to error in my ajax it's going to success. Any help would be greatly appreciated.
Auth::attempt will return you true or false, by default if you return a response()->json() without the 2nd parameter, it will be default to 200 (success). So based on the Auth::attempt you should either return 400 if it fails to login, then it should go into your ajax's error function.
$auth = \Auth::attempt($credentials, $remember);
if($request->ajax()) {
$responseCode = 200;
if( ! $auth) {
$responseCode = 400;
}
$response = response()->json([
'auth' => $auth,
'intended' => \URL::route('home')
], $responseCode);
return $response;
}

Ajax query works when adding new post but doesn't work when update an entity

I have two Select box one for the Countries and the second for the cities and the second one depends from the selected choice of the first one.
I the code is as the example Dynamic Generation for Submitted Forms in the documentation http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data
All things work fine when adding a new post , but when trying do update a post, the Ajax query to display cities doesn't work .
This is the controller
// newAction
/**
* #ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
*/
public function newAction(Agence $agence, Request $request)
{
$em = $this->getDoctrine()->getManager();
$travel = new Travel();
$form = $this->createForm(new TravelType($agence), $travel);
if ($request->getMethod() == 'POST')
{
//....
}
return $this->render('AppBundle:Dashboard/Travel:new.html.twig',
array(
'form' => $form->createView() ,
'agence' => $agence,
));
}
//editAction
/**
* #ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
* #ParamConverter("travel", options={"mapping": {"travel_id":"id"}})
*/
public function editAction(Travel $travel, Agence $agence, Request $request)
{
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(new TravelEditType($agence), $travel);
if ($request->getMethod() == 'POST'){
//....
}
return $this->render('AppBundle:Dashboard/Travel:edit.html.twig',
array(
'form' => $form->createView() ,
'travel' => $travel,
'agence' => $agence,
));
}
travelType and ti works good
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
//........
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Country;
class TravelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//....
$formModifier = function (FormInterface $form, Country $country = null) {
$cities = null === $country ? array() : $country->getCities();
$form->add('destination', 'entity', array(
'class' => 'AppBundle:CityWorld',
'choices' => $cities,
'multiple' => false,
'expanded' => false,
'property' => 'name',
'label' => 'Destination',
'attr' => array('class' => 'col-xs-10 col-sm-10', 'placeholder' => 'Destination'),
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. SportMeetup
$data = $event->getData();
$formModifier($event->getForm(), $data->getCountry());
}
);
$builder->get('country')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $country);
}
);
$builder->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
$event->stopPropagation();
}, 90000000000000); // Always set a higher priority than ValidationListener
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Travel'
));
}
public function getName()
{
return null;
}
}
This is TravelEditType
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
//........
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Country;
class TravelEditType extends TravelType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options) ;
}
public function getName()
{
return null;
}
}
This is the form and javascript code
<form method="post" action="" class="form-horizontal" role="form" {{ form_enctype(form) }} >
//.............
</form>
<script type="text/javascript">
var $county = $('#country');
$county.change(function () {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
var data = {};
data[$county.attr('name')] = $county.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: data,
success: function (html) {
// Replace current position field ...
$('#city').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#city')
);
// Position field now displays the appropriate positions.
}
});
});
Try it without parameter in URI:
dashboard_city_ajax:
path: /citiies/ajax
defaults: { _controller: AppBundle:TravelDashboard:ajaxCities }
And send data with POST:
$.ajax({
url: '{{ path('dashboard_city_ajax') }}',
type: 'POST',
data: { agence_slug: '{{ agenceSlug }}' },
You can receive it in controller:
$request->request->get('bar', 'default value if bar does not exist');
The problem is in your route matching. There is many way to solve problem. Try just include in your ajax route requirements for matching route or in $.ajax function use another route, for example
The simplest way for you (if you don't want rebuild your controller) is just rebuild your route and put in the first place your ajax route like :
dashboard_city_ajax:
path: /{ajax}/{agence_slug}/citiies
defaults: { _controller: AppBundle:TravelDashboard:ajaxCities }
requirements:
ajax: ajax
$.ajax({
url: '{{ path('dashboard_city_ajax', {'agence_slug': agence.slug, 'ajax': 'ajax' }) }}',
type: 'POST',
data: data,
But the right way IMHO is get your data from request. For example
vplanning_ajax:
path: /ajax
defaults: { _controller: VplanningPageBundle:Page:Ajax }
function getData(init) {
$.post(
{{ path('vplanning_ajax') }},
{
agence_slug: agence.slug,
yourdata2: 'yourdata2
} ,
function ( data ) {
handleData(data);
}
);
}
And in your Controller your just do
$agence_slug = $this->request->request->get('agence_slug');
$yourdata2 = $this->request->request->get('yourdata2);
...

Resources