Reputation: 336
I am working on a bookstore project where books can be added to cart, a user can select many books for adding them to cart. when the user clicks on the Add to Cart
button, I am adding the IDs of the selected books in a JS array called cart
. When all the selected books are added to the cart then I want to link <a>
tag with ajax call that will hit the url of a controller function and will send the JS cart
array object to the controller function and then in the controller function, I want to return view to the browser, I do not want the controller function to return the response back to the ajax call but instead I want to return the view to the browser.
Here is the JS function that adds the ID of the selected books to the cart
JS array:
function addToCart(id)
{
if(! cart.includes(id) ) cart.push(id);
cartLength.html(cart.length);
$('#successCart'+id).html('Book added to cart.');
}
Here is the <a>
tag that calls the ajax function, the function name is showCart():
<a href="#" onclick="event.preventDefault(); showCart();">
<i class="fa fa-shopping-cart"></i>
<span id="cartLength"></span>
</a>
Here is the showCart()
function that has ajax code:
function showCart()
{
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url:"cart",
method:'post',
data:{cart:cart},
dataType: 'html'
})
.done(function(msg){
});
.fail(function(msg){
alert(msg.responseJSON.errors);
});
}
Here is the controller function - I want this function to directly return the view to the browser without sending it back to the ajax call:
public function showCart(Request $request)
{
return view('cart', ['cart' => $request->cart ]); // this should be returned to the browser and not to the ajax call
}
Here is the route for the controller function:
Route::post('/cart', 'HomeController@showCart')->name('home.cart');
EDIT:
I have temporarily solved the issue with the following tricks but that is not a permanent solution:
After calling the showCart()
function from ajax
for sending the cart
array variable from js
to laravel
controller, I used the following logic to store the books in a session variable whose ids
are stored in the cart
array:
public function showCart(Request $request)
{
session()->put('cart_books', Book::whereIn('id', $request->cart)->get());
session()->save();
return "success";
}
After storing the result of the query in a session variable, I created another GET
route for /cart
as below:
Route::get('/cart', 'HomeController@viewCart');
Then upon success of the post
ajax call, I called /cart
with get
method as below:
.done(function(msg){
console.log('calling cart');
location.href = "cart"; // Here I call the `/cart` with `get` method which will hit the `viewCart()` function of HomeController which will return the view back to the browser along with the results that were stored in the session variable.
})
And this is the viewCart()
controller function that returns the view to the browser and sends the session variable's data to the view:
public function viewCart()
{
$random_books = Book::all()->random(4);
$categories = Category::all();
return view('cart', ['cart_books' => session()->get('cart_books'),
'random_books' => $random_books, 'categories' => $categories]);
}
I want the controller function to return the view to the browser without returning it to the ajax call, any help is appreciated in advance.
Upvotes: 8
Views: 7465
Reputation: 1783
As the others said you can use
return view('cart', ['cart' => $request->cart])->render();
and in you jQuery do
.done(function(response){
document.write(response);
});
Or you can return the link that its content should be shown to the user and redirect the user in your done method. So in your back-end you'll have
return route('cart', ['cart' => $request->cart]);
and in your front-end you'll have
.done(function(response){
location.href = response;
});
Upvotes: 2
Reputation: 8989
You can return Raw html from ajax call by rendering and returning the view inside your controller as,
return view('cart', ['cart' => $request->cart])->render();
This will return the raw HTML and you can further use it. However, returning HTML from ajax is not a good way, You can return JSON from the controller and render the view in frontend according to the JSON data.
Upvotes: 3
Reputation: 2158
You're doing a XHR, so you shouldn't return the whole HTML view from your controller unless you plan to replace your existing element with the returned HTML, like how you're doing with addToCart
. What you need here is a redirection after your POST, and your temporary solution isn't actually a bad solution :) Here's a similar question as yours with the same answer. In fact, I highly recommend your temporary solution over the alternative solution below.
Since you wish to use the view returned from your controller without returning it to your ajax, a rather unorthodox approach would be to POST through a <form>
. You can dynamically create a <form>
, with the <input>
s of your data, and submit.
function postData(actionUrl, method, data) {
var mapForm = $('<form id="mapform" action="' + actionUrl + '" method="' + method.toLowerCase() + '"></form>');
for (var key in data) {
if (data.hasOwnProperty(key)) {
mapForm.append('<input type="hidden" name="' + key + '" id="' + key + '" value="' + data[key] + '" />');
}
}
$('body').append(mapForm);
mapForm.submit();
}
function showCart()
{
postData('cart', 'post', cart);
}
I borrowed the above code from here. You can do the same with vanilla JS too.
Upvotes: 0
Reputation: 380
In the controller function just add render method like the following line
public function showCart(Request $request)
{
return view('cart', ['cart' => $request->cart ])->render();
}
For js:
$.ajax({
method: 'POST', // Type of response and matches what we said in the route
url: '{{ route('home.cart') }}', // This is the url we gave in the route
data: {'cart' : cart}, // <-- this is your POST data
success: function(response){ // What to do if we succeed
console.log(response);
},
error: function(jqXHR, textStatus, errorThrown) { // What to do if we fail
console.log(JSON.stringify(jqXHR));
console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
}
});
Upvotes: 0