Как вернуть представление из функции контроллера laravel при вызове ajax? - PullRequest
7 голосов
/ 04 августа 2020

Я работаю над проектом книжного магазина, где книги могут быть добавлены в корзину, пользователь может выбрать множество книг для добавления их в корзину. когда пользователь нажимает кнопку Add to Cart, я добавляю идентификаторы выбранных книг в массив JS с именем cart. Когда все выбранные книги будут добавлены в корзину, я хочу связать тег <a> с вызовом ajax, который попадет в URL-адрес функции контроллера и отправит объект массива JS cart в функцию контроллера и затем в функции контроллера я хочу вернуть представление в браузер, я не хочу, чтобы функция контроллера возвращала ответ обратно на вызов ajax, но вместо этого я хочу вернуть представление в браузер.

Вот функция JS, которая добавляет ID выбранных книг в массив cart JS:

function addToCart(id)
{
if(! cart.includes(id) ) cart.push(id);

cartLength.html(cart.length);
$('#successCart'+id).html('Book added to cart.');

}  

Вот тег <a>, который вызывает функцию ajax, имя функции - showCart ():

<a href="#" onclick="event.preventDefault(); showCart();">
  <i class="fa fa-shopping-cart"></i>
  <span id="cartLength"></span>
</a>  

Вот функция showCart() с кодом ajax:

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);
 });
}  

Вот функция контроллера - мне нужна эта функция чтобы напрямую вернуть представление в браузер, не отправляя его обратно в вызов ajax:

public function showCart(Request $request)
{
    return view('cart', ['cart' => $request->cart ]); // this should be returned to the browser and not to the ajax call
}  

Вот маршрут для функции контроллера:

Route::post('/cart', 'HomeController@showCart')->name('home.cart');  

EDIT :

У меня есть тема временно решил проблему с помощью следующих приемов, но это не является постоянным решением:

После вызова функции showCart() из ajax для отправки переменной массива cart из js в laravel контроллер , Я использовал следующий лог c для хранения книг в переменной сеанса, ids которой хранится в массиве cart:

public function showCart(Request $request)
{

    session()->put('cart_books', Book::whereIn('id', $request->cart)->get()); 
    session()->save();
    return "success";

}  

После сохранения результата запроса в переменной сеанса , Я создал другой маршрут GET для /cart, как показано ниже:

Route::get('/cart', 'HomeController@viewCart');  

Затем, после успешного вызова post ajax, я вызвал /cart с помощью метода get, как показано ниже:

.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.

  })  

И это функция контроллера viewCart(), которая возвращает представление в браузер и отправляет данные переменной сеанса в представление:

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]); 
}

Я хочу, чтобы функция контроллера вернуть представление в браузер, не возвращая его при вызове ajax, любая помощь приветствуется заранее.

Ответы [ 4 ]

2 голосов
/ 12 августа 2020

Вы можете вернуть Raw html из вызова ajax, отрисовав и вернув представление внутри вашего контроллера как,

return view('cart', ['cart' => $request->cart])->render();

. Это вернет необработанный HTML, и вы сможете его использовать в дальнейшем. Однако возврат HTML из ajax не является хорошим способом. Вы можете вернуть JSON из контроллера и визуализировать представление во внешнем интерфейсе в соответствии с данными JSON.

0 голосов
/ 13 августа 2020

Как говорили другие, вы можете использовать

return view('cart', ['cart' => $request->cart])->render();

и в себе jQuery do

.done(function(response){
    document.write(response);
});

Или вы можете вернуть ссылку, по которой ее содержимое должно быть показано пользователю и перенаправьте пользователя в свой метод done. Таким образом, в вашем бэкенде у вас будет

return route('cart', ['cart' => $request->cart]);

, а в вашем интерфейсе -

.done(function(response){
    location.href = response;
});
0 голосов
/ 11 августа 2020

Вы выполняете XHR, поэтому вам не следует возвращать весь HTML вид из вашего контроллера, если вы не планируете заменить существующий элемент на возвращенный HTML, например, как вы ' Делаем с addToCart. Здесь вам нужно перенаправление после вашего POST, и ваше временное решение на самом деле не плохое решение :) Вот аналогичный вопрос , что и ваш, с тем же ответом. Фактически, Я настоятельно рекомендую ваше временное решение вместо альтернативного решения, приведенного ниже.

Поскольку вы используете sh, чтобы использовать представление, возвращаемое вашим контроллером, не возвращая его на ajax, довольно неортодоксальным подходом будет POST через <form>. Вы можете динамически создать <form> с <input> s ваших данных и отправить.

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);
}

Я позаимствовал приведенный выше код из здесь . Вы можете сделать то же самое и с vanilla JS.

0 голосов
/ 04 августа 2020

В функции контроллера просто добавьте метод рендеринга, как в следующей строке

public function showCart(Request $request)
{
   return view('cart', ['cart' => $request->cart ])->render();
}  

Для 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);
}
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...