I'm trying to use AJAX (vanilla JS) to submit a form to a Laravel 5.5 controller that will search the Amazon products API.
The AJAX is submitting the correct keywords and category inputs and the request is passing a form request that requires both keywords and category, but the keywords and category are not available in the controller. I do get a placeholder response from the controller.
The request payload in Chrome's Network tab in Developer Tools shows the AJAX is sending the correct terms.
HTML form
<form method="POST" action="http://local.example.com/api/products/search" accept-charset="UTF-8" id="product-search-form">
<input name="_token" type="hidden" value="qcXA3xVIoltX9tSpeJeWuKVa3alUkq1p5tuIlKJ5">
<div class="form-group">
<label for="keywords" class="required">Keywords</label>
<input id="keywords" placeholder="Enter keywords" aria-required name="keywords" type="text">
</div>
<div class="form-group ">
<label for="category">Category</label>
<select id="category" name="category">
<option selected="selected" value="">Choose a category...</option>
<option value="All">All</option>
<option value="Apparel">Apparel</option>
<option value="Books">Books</option>
<option value="DVD">DVD</option>
<option value="Electronics">Electronics</option>
<option value="Music">Music</option>
<option value="Software">Software</option>
<option value="SoftwareVideoGames">SoftwareVideoGames</option>
<option value="Toys">Toys</option>
<option value="VideoGames">VideoGames</option>
<option value="UnboxVideo">Video on Demand</option>
</select>
</div>
<div>
<button id="search-products-submit" type="submit" class="button-primary">Search</button>
</div>
</form>
JavaScript AJAX post request on submit
function getProducts(keywords, category) {
let path = "api/products/search";
let searchTerms = {
keywords: keywords,
category: category,
_token: getCsrfToken(),
};
ajaxPostRequest(path, showProducts, searchTerms);
}
AJAX requests
function ajaxPostRequest(path, callback, formId) {
return ajaxRequest("POST", path, callback, formId);
}
function ajaxRequest(method, path, callback, data = null) {
let xhr = new XMLHttpRequest();
let url = getFullUrl(path);
addEventListeners(xhr);
xhr.open(method, url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
let parsedResponse = JSON.parse(xhr.responseText);
callback(parsedResponse);
}
};
setRequestHeaders(xhr, method);
xhr.send(JSON.stringify(data));
}
AJAX request payload
{
keywords: "aaa",
category: "All",
_token: "qcXA3xVIoltX9tSpeJeWuKVa3alUkq1p5tuIlKJ5"
}
Form request
class SearchProductsFormRequest extends Request
{
/**
* Determine if the user is authorized to make this request
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request
*
* @return array
*/
public function rules(): array
{
return [
'keywords' => 'required',
'category' => 'required'
];
}
}
Controller
/**
* @param SearchProductsFormRequest $request
* @return JsonResponse
*/
public function create(SearchProductsFormRequest $request): JsonResponse
{
if ($request->has('keywords')) {
\Log::info('Got keywords');
} else {
\Log::info('Did not get keywords');
}
if ($request->has('keywords')) {
\Log::info('Got category');
} else {
\Log::info('Did not get category');
}
\Log::info(print_r($request, true));
\Log::info('keywords: ' . $request->input('keywords'));
\Log::info('category: ' . $request->input('category'));
return response()->json([
'name' => 'Abigail',
'state' => 'CA'
]);
}
Log output
[2018-04-08 19:26:15] local.INFO: Did not get keywords
[2018-04-08 19:26:15] local.INFO: Did not get category
[2018-04-08 19:26:15] local.INFO: keywords:
[2018-04-08 19:26:15] local.INFO: category:
console.log of server response (dummy data for testing)
{name: "Abigail", state: "CA"}
So the controller is getting called and responding, but can't read the input data.
setRequestHeaders()
function setRequestHeaders(xhr, method) {
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader("X-CSRF-TOKEN", getCsrfToken());
if (method === 'GET') {
xhr.setRequestHeader('Content-Type', 'application/json');
} else {
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
}