Call delete function from controller with ajax in symfony 3 - ajax

I am relatively new to symfony. I have a view page with bootstrap tables. I also have crud controller (src\AppBundle\Controller\SiftscienceTrackerController.php) created and the delete function is as follows:
public function deleteAction(Request $request, SiftscienceTracker $siftscienceTracker)
{
$form = $this->createDeleteForm($siftscienceTracker);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($siftscienceTracker);
$em->flush();
}
return $this->redirectToRoute('admin_siftsciencetracker_index');
}
My question is whether I can call this function of the controller with ajax call from a delete button in a table row and how ajax should be written? If not can I create another function inside that controller and that one to be called with ajax?

Here is an example using jQuery:
public function deleteAction(Request $request, SiftscienceTracker $siftscienceTracker)
{
$form = $this->createDeleteForm($siftscienceTracker);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($siftscienceTracker);
$em->flush();
}
$request = $this->getRequest();
if($request->isXmlHttpRequest() || $request->get('_xml_http_request')){
return new JsonResponse("{url: $this->generateUrl('admin_siftsciencetracker_index')}", 200);
}
return $this->redirectToRoute('admin_siftsciencetracker_index');
}
As you can see i check if the request is an ajax request to avoid making a separate action.
Since your action returns a redirection you just return the url as json to the script that made the ajax call and make the redirection in javascript:
$.ajax({
url: $('#my-form').prop('action');
method: 'post',
data: $('#myForm').serializeArray()
success: function(response){
window.location(response.url);
}
});

Related

Ajax to call Symfony controller

I'm trying to call a method with ajax.
ajax connection is succeed and no error message was appeared.
the JS code
$("[id^=changeStatus]").each(function(){
$(this).on("click", function(){
const id = $(this).data('id');
console.log(id);
$.ajax({
type: "POST",
url: "{{url('change_order_status')}}",
data: id,
async: false,
})
.done(function() {
console.log('success');
})
.fail(function () {
console.log('error');
});
});
but the method in the controller seemingly not working.
controller
/**
* #Method("POST")
* #Route("/%eccube_admin_route%/", name="change_order_status")
* #param $request
* #return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function changeOrderStatus(Request $request)
{
if (!$request->isXmlHttpRequest()) {
throw new BadRequestHttpException();
}
$this->logger->info("it's working");
dump($rquest);
}
I don't know what is wrong with it.
Please help.
I insert the js to every pages as an snippet is that's why it doesn't work properly.
You must return an instance of Response class in a controller . So here, what you can do is to return a JsonResponse
return new JsonResponse($request->getContent());
May be you can try this.
$("[id^=changeStatus]").each(function(){
$(this).on("click", function(){
const id = $(this).data('id');
console.log(id);
$.ajax({
type: "POST",
url: "{{ path('change_order_status') }}",
data: {
id : id
},
async: false,
})
.done(function(data) {
console.log(data)
console.log('success');
})
.fail(function () {
console.log('error');
});
});
/**
* #Route("/%eccube_admin_route%/", name="change_order_status", methods={"POST"})
* #param $request
* #return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function changeOrderStatus(Request $request)
{
if (!$request->isXmlHttpRequest()) {
throw new BadRequestHttpException();
}
$this->logger->info("it's working");
$id = $request->request->get('id');
// Try to dump your request
// dd($request);
return $this->json([
'success' => true
]);
}
I just don't know what eccube_admin_route mean.
And don't forget to extend AbstractController in your controller class
This is example from my project. Try to dump your controller object and use symfony debugbar to open your ajax request, click on url columns

Model binding for JSON api using Laravel

We are moving an older PHP project over to laravel. We are trying to post JSON to our api we created, but are not aware how to have the JSON be bound to a model. We added the model as a parameter to the function, it is created but none of the properties are set on it from the JSON. Does this type of model binding exist in laravel?
class CalculatorModel
{
/**
* Value A.
*
* #var integer
*/
public $A;
/**
* Value B.
*
* #var integer
*/
public $B;
}
class CalculatorController
{
// What is trying to be achieved.
public function add(CalculatorModel $model)
{
return Calculator::Add($model);
}
// What we are trying to avoid
// as there is a lot of properties/objects in our real world JSON
public function add(Request $request)
{
$a = $request->json()->all();
$m = new CalculatorModel();
$m->A = $a['A'];
$m->B = $a['B'];
....
return Calculator::Add($m);
}
}
// in reoutes/api.php
Route::post('add', 'API\CalculatorController#add');
// External library's class
class Calculator
{
public static function Add(CalculatorModel $m)
{
return $m->A + $m->B;
}
}
Simple JSON post
{
"A": 2,
"B": 2
}
In ASP.Net, we are able to add a [FromBody] attribute to the parameter so that ASP.Net would bind the content body as the model instead of form content. We are looking for similar functionality in laravel.
There is no such binding in Laravel. Laravel binding is about Models/DB access as #PKeidel said. All you need is controller method without any models.
public function add(Request $request)
{
return $request->A + $request->B;
}
UPD: What about new constructor for CalculatorModel class?
public function __construct(array $properties = [])
{
foreach ($properties as $key => $value) {
$this->{$key} = $value;
}
}
public function add(Request $request)
{
$m = new CalculatorModel($request->all());
return Calculator::Add($m);
}
In any case Laravel does not offer out of the box solution for this.
Try this to wrap your API, which can then be used by Eloquent as if it were a database model:
https://github.com/CristalTeam/php-api-wrapper
All what models are about is saving/reading something from the database. So if this is not what you want, forget about it. Because in Laravel models are bound to database tables ;-)
If you just want so receive some values as json, do a calculation and return a value you are thinking to complicated.
Create a route:
Route::post('add', function() {
$data = request()->json();
return $data->get('A') + $data->get('B');
});
Or:
Route::post('add', function(\Illuminate\Http\Request $r) {
return $r->A + $r->B;
});
This is all it takes.
After that just make sure to send your data with json header. Like so:
fetch('/add', {
method:"post",
headers: {'Content-Type': 'application/json'},
body: '{"A": 2,"B": 2}'
})
.then((d) => d.text())
.then((html) => {
output.innerHTML = html;
})
See it in action here: https://laravelplayground.com/#/snippets/006b4871-5d92-4a2d-b8af-8a21423024e6

Ajax call Laravel

I am attempting to call my controller that would update my product:
public function update(Request $request, $product_id)
{
$product = Product::find($product_id);
$product->name = $request->name;
$product->test = $request->session()->get('test');;
$product->save();
return response()->json($product);
}
I would like to trigger the event with ajax, a button is clicked and my controller is called with the data that then inserts it into database.
I tried to do:
$.ajax({
type: POST,
url: my_url,
data: formData,
dataType: 'json',
success: function (data) {
console.log(data);
},
error: function (data) {
console.log('Error:', data);
}
But that already posts before calling my controller, how can i just throw all data to controller instead of posting it?

No route found for POST /email

Controller:
/**
* #Route("/email/{name}/{email}/{subject}/{message}", name="email")
* #Method({"GET", "POST"})
*/
public function indexAction($name, $email, $subject, $message, Request $request){
var_dump($name, $email, $subject, $message);
die;
}
Ajax:
<script type="text/javascript">
$(document).ready(function() {
$('#contact-form').submit(function(event) {
$.ajax({
type:'POST',
url:'./email',
data:"/"+$('#name').val()+"/"+$('#email').val()+"/"+$('#subject').val()+"/"+$('#message').val(),
success:function(response){
alert(response)
}
});
event.preventDefault();
});
});
</script>
I am trying to submit ajax request to the controller. Unfortunately i get 404, and the following error:
No route found for "POST /email" (from "http://localhost/Portfolio/web/app_dev.php/")
PS. The code in the controller is for debuging purposes
You should change your controller to accept only POST request and so you don't need to pass your arguments in the path :
/**
* #Route("/email, name="email")
* #Method({"POST"})
*/
public function indexAction(Request $request){
//your code here
}
To access your post parameters in the controller, use $name = $request->request->get('name'); or consider using Symfony Forms
You also need to change your ajax call to send an object in data:
<script type="text/javascript">
$(document).ready(function() {
$('#contact-form').submit(function(event) {
$.ajax({
type:'POST',
url:'/email',
data: {
name: $('#name').val(),
subject: $('#subject').val(),
email: $('#email').val(),
message: $('#message').val()
},
success:function(response){
alert(response)
}
});
event.preventDefault();
});
});
</script>
This will properly send a POST request to /email
the route /email/{name}/{email}/{subject}/{message} means that you need to send the Request to an URL like this
/email/testName/example#gmail.com/TestSUbject/Testmessage
if you need the /email route to work just change the #Route annotation to /email
and in controller
$request->request->get('email');
//retrieve other fields
...
..
to access the values of the POST request
Also you can also use Symfony Forms to take the Advantages they offer like validation , CSRF Protection , etc

Laravel 5 : on success Validation Request function

In laravel 5, we can now use the Request classes for input validation like so :
public function store(StoreItemRequest $request)
{
$item = Item::create($request->all());
return 'success';
}
When the validation fails, I can get the errors thanks to the response function in the Request class :
public function response(array $errors) {
return response()->json(['errors' => $errors]);
}
But what if the validation succeeds? Is there a function that would get automatically triggered like so :
public function ????(){
if($request->ajax())
return response()->json(['success' => true]);
}
Note: it is required that the content of the function store does NOT get executed if the request is ajax (just as it would not get executed if the validation fails).
Yeah, I found validate method in ValidateWhenResolvedTrait which you could override in your form request class;
public function validate(){
$instance = $this->getValidatorInstance();
if($this->passesAuthorization()){
$this->failedAuthorization();
}elseif(!$instance->passes()){
$this->failedValidation($instance);
}elseif( $instance->passes()){
if($this->ajax())
throw new HttpResponseException(response()->json(['success' => true]));
}
}
Currently there is no such method. You can do this in your request with some "hacks" (like override validate method) but I do not recommend it.
Idea of Request was to move validation/authorization out of controller. If you move successful response to Request than we have the same situation as before (well, name changed).
I would suggest to let controller handle ajax too:
public function store(StoreItemRequest $request)
{
$item = Item::create($request->all());
if($request->ajax())
return response()->json(['success' => true]);
return 'success';
}
Is there a reason why you are trying to achieve this in a request?

Resources