Return laravel view from JavaScript Ajax - javascript

I'm having trouble trying to show the view I want after calling the controller method from Ajax.
This is the JavaScript function where I call the controller Method 'create_pedido' with an Ajax post.
$('.small-box').on('click', function(e) {
e.preventDefault();
let camarero_id = document.getElementById('id_camarero').value;
let mesa_id = e.currentTarget.parentElement.attributes.idMesa.value;
let mesa_estado = e.currentTarget.parentElement.attributes.disponible.value;
console.log('ID Mesa: ' + mesa_id);
console.log('Disponible: ' + mesa_estado);
console.log('ID Camarero: ' + camarero_id);
if (mesa_estado == 1) {
console.log('Crear')
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
type: "POST",
url: 'create_pedido',
data: { mesa: mesa_id, camarero: camarero_id }
}).done(function(msg) {
console.log('Success');
});
} else {
console.log('Editar')
}
});
This is the controller method which does everything but returning the view where it should go after.
public function create(Request $request)
{
$mesa = Mesa::find($request->mesa);
$camarero = Trabajador::find($request->camarero);
$alimentos = Alimento::all();
$categorias = Categoria::all();
Log::channel('stderr')->info($mesa);
Log::channel('stderr')->info($camarero);
return view('pedido.create', compact('mesa', 'camarero','categorias', 'alimentos'));
}
Instead of going to the 'pedidos.create' view after the 'Log::channel...' stay in the same view where it was called.
Here are my routes:
Route::resource('/', 'IndexController');
Route::resource('inicio', 'IndexController');
Route::resource('trabajador', 'TrabajadorController');
Route::resource('pedido', 'PedidoController');
Route::post('create_pedido','PedidoController#create');
Route::resource('alimento', 'AlimentoController');
Route::resource('orden', 'OrdenController');
Route::resource('mesa', 'MesaController');
Route::post('mesa_changestate', 'MesaController#change_state');

Its likely returning to the same view because you are not telling it the base URL of the app. Laravel has a nice method to help here, which will prepend the route with the appropriate base:
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
type: "POST",
url: '{{url("create_pedido")}}', // use blade to add in the Laravel url() method here
data: { mesa: mesa_id, camarero: camarero_id }
}).
Also for the return statement in the controller create method - is the folder 'pedido' or 'pedidos' - make sure to call the right view :)

Related

POST and GET methods on the same button

I am currently learning asp.net core 3 and I can't find any help regarding this issue that I have.
I have a form that submits a value with a POST request. But I want the same button to have a GET request that populates another field with a .ajax / xmlhttprequest. But I want the POST method to be executed first and then the GET method. Is it possible to do it? I've tried doing it but I got stuck.
These are the methods inside my controller.
[HttpGet]
public async Task<IActionResult> GetConvertedAmount()
{
var rate = await _db.ExchangeRates.Where(x => x.Name.Equals(_tM.Currency)).ToListAsync();
_tM.convertToCurrency(rate[0].Rate);
var amount = _tM.Amount;
return Json(amount);
}
[HttpPost]
public ActionResult CalculateExchangeRatio(int amount_give, string type_to_give)
{
_tM.Amount = amount_give;
_tM.Currency = type_to_give;
return Ok();
}
And this is my JS script
$('#calculateButton').on("click", function () {
$.ajax({
url: "/trade/getconvertedamount",
type: "get",
success: function (amount) {
console.log(amount);
alert(amount);
}
});
})
You can use the $.ajax 'done' chaining to complete the entire process:
$('#calculateButton').on("click", function () {
$.ajax({
url: "/trade/calculateexchangeratio",
data: { amount_give: 9.99, type_to_give: 'blahblah' },
type: "post"
})
.done(function(){
$.ajax({
url: "/trade/getconvertedamount",
type: "get"
})
.done(function (amount) { console.log(amount); alert(amount); });
});
})
You can add the similar to the end of the POST method implementation return RedirectToAction("CalculateExchangeRatio", new { amount_give = 1, type_to_give = 2 });
So your POST method will be called first and it will call the GET method.
Here is the documenttation.

Passing parameters in Ajax post back in MVC

I am trying to pass ID parameter from a view to a controller on a click delete link available on a selected row.
Simplified View Layout
#using (Html.BeginForm("#", "Schedule", FormMethod.Post, htmlAttributes: new { #class = "floating-labels" }))
{
#Html.AntiForgeryToken()
Delete
}
JavaScript
<script type="text/javascript">
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
$.ajax({
type: "POST",
url: '#Url.Action("Delete", "Schedule", new { id = "id" })',
contentType: "application/json",
data: { id },
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
Controller
namespace Controllers
{
public class ScheduleController
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id)
{
//do stuff
}
}
}
But on the click of a delete link I get below error and code does not hit controller action.
I am not able to figure out what mistake I am making...
Here is my locally tested implementation that is working.
ScheduleController class:
public class ScheduleController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Delete(int id)
{
return Ok(id);
}
}
Page that sends the post request:
#Html.AntiForgeryToken()
Delete
<div id="ScheduleList"></div>
<script>
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
var uri = '/Schedule/Delete?id=' + id;
var tokenElement = document.getElementsByName('__RequestVerificationToken')[0];
var data = {
__RequestVerificationToken: tokenElement.value
}
$.ajax({
type: "POST",
url: uri,
data: data,
success: function (result) {
success(result);
}
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
The page does nothing but render the html, and the javascript handles the actual Ajax post. What I believe you were missing is the Validation token in your request.
It is because you are not actullay posting the form pass it correctly and add _token in the ajax data list and value for that token will come from #Html.AntiforgeryToken()
reading the error the request is most probably send correctly and there is an internal server error as mentioned in the 500 respond so please check the code that is inside the controller
Try this, you are accesing a javascript variable on c# code, and you cant do that.
If correct, please mark as answer.
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
var url = '#Url.Action("Delete", "Schedule")?id=' + id;
$.ajax({
type: "POST",
url: url,
contentType: "application/json",
data: { id },
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
I think none of the answers above solve the issue. First of all I would replace your target url:
url: '#Url.Action("Delete", "Schedule", new { id = "id" })',
with
url: '#Url.Action("Delete", "Schedule", new { id = actualIdVariable })',
(replace "id" with the actual id variable from the model you're passing to the view).
Note how your browser response is telling you that the url you're posting to is Schedule/Delete/id. That said, I'm not sure you even need the routeValues in this case (the new { id = ...} parameter). this is a POST action, and action parameters wouldn't come from route unless specified by by attribute routing (i.e. [Route("~/Schedule/Delete/{id}")] attribute on your action).
I think your post action is failing because it is trying to parse the "id" string as an int.
Second, I would change the data property of the ajax call and include the anti forgery token. Just because the anchor element you're binding the click event to, is inside the form with #Html.AntiforgeryToken() doesn't mean the generated token will be posted in the ajax request. You're not actually submitting/posting the form, you're just clicking a button.
it should be something like
data: {
'id': id,
'__RequestVerificationToken': $('[name="__RequestVerificationToken"]').val()
}
try this, it solve the error on routing (different url Action) and the parameter on the controller:
JavaScript
<script type="text/javascript">
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
$.ajax({
type: "POST",
url: '#Url.Action("Delete", "Schedule")',
data: "id=" + id ,
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(string id)
{
//do stuff
}
Nicola.

Passing data from View to Controller using Ajax results in 404 error on the controller method

I'm trying to pass data from View to Controller Action method. Using Ajax to pass the data to the controller but the controller doesn't receive the data and it is always null resulting in 404 error.
Can someone review this and point out what needs to be fixed?
Ajax call in View -
function openErrorDetails(errors) {
$.ajax({
type: 'POST',
url: "/Home/ErrorDetails",
dataType: 'json',
data: JSON.stringify({ errors }),
success: function (data) {
var win = window.open();
win.document.write(data);
}
});
}
Calling the Ajax funtion using a anchor tag OnClick event to open a new window with the errors details -
var exception = "onClick='openErrorDetails(" + JSON.stringify(data) + ")'> View details";
Controller -
[HttpPost]
public ActionResult ErrorDetails(string errors)
{
if (errors != null)
{
dynamic errorMessages = JsonConvert.DeserializeObject(errors);
return View("ErrorDetails", errorMessages);
}
else
{
return new HttpNotFoundResult();
}
}
this solved it
data: { errors: JSON.stringify({ errors }) },

like and unlike with javascript and Laravel

I'm trying to implement a functionality where user can like and unlike product using javascript I followed this Laravel - Favourite / Un-Favourite button but it doesn't work for me, the button can't be clicked, any idea on how I can fix this?
Routes
Route::get('product/like/{id}', ['as' => 'product.like', 'uses' => 'LikeController#likeProduct']);
Route::get('product/{product}/unlike','LikeController#destroy')->name('product.unlike');
Javascript
<script>
function addToFavourites(productid, userid) {
var user_id = userid;
var product_id = productid;
$.ajax({
type: 'post',
url: 'product/like/{id}',
data: {
'user_id': user_id,
'product_id': product_id,
},
success: function () {
// hide add button
$('#addfavourites' + product_id).hide();
// show delete button
$('#deletefavourite' + product_id).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
}
Blade file
#if($product->isLiked)
<div id="addfavourites{{$product->id}}" onClick="addToFavourites({{$product->id}}, {{ Auth::user()->id }})"> unlike </div>
#else
<div id="deletefavourite{{$product->id}}" onClick="deleteFromFavourites({{$product->id}}, {{ Auth::user()->id }})" > like </div>
#endif
Make your routes accept a post method because you're posting through Ajax
Route::post('product/like/{id}', ['as' => 'product.like', 'uses' => 'LikeController#likeProduct']);
Route::post('product/{product}/unlike', 'LikeController#destroy')->name('product.unlike');
And use ES6 template string and add a CSRF token header to the Ajax request
function addToFavourites(productid, userid) {
// Redundant
// var user_id = userid;
// var product_id = productid;
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `/product/like/${productid}`, // Use ES6 template and point to the url from root /
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
// hide add button
$('#addfavourites' + productid).hide();
// show delete button
$('#deletefavourite' + productid).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
}
Hope this helps

How to prevent sending duplicate request with a single click in AngularJs

I have an angularJs application that has an api call with a click on a link . but everytime i click on the link it sends 2 same api calls to the server. Why this occurs and how can i resolve this.
my service is like: SomethingService
function getData() {
return apiSettings.getApiInformation().then(function (response) {
var url = response.data.Url + "/odata/Something?$expand=Something";
var data = {
url: url,
type: "GET",
token: response.data.Token,
data: {},
async: true,
cache: false,
headers: {
"accept": "application/json; charset=utf-8",
'Authorization': 'Bearer ' + response.data.Token
},
dataType: "json",
success: {},
error: {},
complete: {},
fail:{}
};
return $http(data);
});
}
Api Settings :
angular.module('myApp.services')
.factory('apiSettings', apiSettings);
apiSettings.$inject = ['$http'];
function apiSettings($http) {
return {
getApiInformation: function () {
return $http.get(baseUrl+ '/api/GetApiInformation', {cache: true});
}
}
}
SomethingController:
var vm = this;
function getSlots(filterCriteria, selectedValue) {
somethingService.getData().then(function (response) {
if (response && response.value.length > 0) {
vm.someData = response.value;
}
});
View:
clicking on this link calls getSlots that sends duplicate request
<a ui-sref="something" class="action-icons" id="slotNav"><i class="fa fa-square-o fa-fw"></i>
something
</a>
this view displays data
<div ng-repeat="data in vm.someData">
<p> {{data.Name}}</p>
</div>
Issue: For a single trigger browser sends duplicate requests like the following. the first call doesn't have callback but the second call has callback:
someuls?$expand=something&_=1432722651197
someuls?$expand=something&_=1432722651197
I had a similar problem which I fixed by checking this answer. I had declared "ng-controller" in HTML as well as routed to it using routeProvider. Fixed the issue by removing the "ng-controller" property in HTML.
Hope this helps.

Categories

Resources