This is a continuation of this article.
Last time, the view file was displayed after API linkage, but this time, the data is acquired by ajax communication and the book search result is displayed. (The reason is that this is cooler lol)
(Since the appearance has been adjusted a little with css, the appearance is a little different from the previous article)
If you fill in the search form and press the search button (submit), it will be processed as follows
It is necessary to describe that the response is returned by json to the controller.
At respond_to ~
searches_controller
class SearchesController < ApplicationController
before_action :call_client, only: :index
def index
si = @client.search_items(keywords: keyword_params, SearchIndex: "Books")
@items = si.items
respond_to do |format|
format.html
format.json
end
end
private
def call_client
require 'paapi'
@client = Paapi::Client.new(access_key: Rails.application.credentials[:pa_api][:access_key_id],
secret_key: Rails.application.credentials[:pa_api][:secret_key],
market: :jp,
partner_tag: Rails.application.credentials[:pa_api][:associate_tag])
end
def keyword_params
params.require(:keyword)
end
end
jbuilder
Create ʻindex.json.jbuilder in
views / [directory with the same name as the controller name]. This time,
searches_controller.rb is created directly under
controllers, so it will be
views / searches / index.json.jbuilder`.
Since the json data is an array this time, it is necessary to write how to process each element. The data to be extracted is the information of the image, title, author, and publisher.
ruby:index.json.jbuilder
json.array! @items do |item|
json.image_url item.image_url
json.title item.title
json.authors item.authors
json.publisher item.publisher
end
api-search.js
//Write using jQuery
$(function() {
//Function to display search results
let search_list = $("#books")
function appendBook(image_url, title, author, publisher) {
const html = `<div class="search-book-content">
<div class="book-image">
<img class="book-image" src="${image_url}">
</div>
<div class="right-content">
<div class="book-info">
<div class="book-info__title">
${title}
</div>
<div class="book-info__author">
${author}
</div>
<div class="book-info__publisher">
${publisher}
</div>
</div>
</div>
</div>`
search_list.append(html);
}
//Display function being searched
function dispLoading(msg){
let dispMsg = "<div class='loadingMsg'>" + msg + "</div>";
$("body").append("<div id='loading'>" + dispMsg + "</div>");
}
//Function to turn off the display during search
function removeLoading(){
$("#loading").remove();
}
//Event fires when the search button is pressed
$("#book-search-form").on("submit", function(e) {
e.preventDefault();
const keyword = $("#keyword").val();
dispLoading("Searching...");
//Details of ajax communication
$.ajax({
url: '/searches',
type: 'GET',
data: {'keywords': keyword},
dataType: 'json',
timeout: 10000
})
//When ajax works
.done(function(items){
$(".search-book-content").remove();
items.forEach(function(item){
let image_url;
let author;
let publisher;
if (item.image_url == null) {
image_url = `/assets/no_image-267acfcb976ba4942183409c682b62a768afb48c328b6ba60de7b57fd83c3b56.png`
} else {
image_url = item.image_url
}
if (item.authors.length == 0) {
author = 'Unknown author'
} else {
author = `${item.authors[0]}`
}
if (item.publisher == null) {
publisher = 'Unknown publisher'
} else {
publisher = item.publisher
}
let title = item.title
appendBook(image_url, title, author, publisher);
})
})
//When ajax fails
.fail(function(){
alert("Search failed");
})
//Common processing regardless of whether ajax succeeds or fails
.always( function(data) {
//Lading Erase the image
removeLoading();
});
});
})
As you can see by reading the code, let's write the process flow.
■ Function definition
■ Event
Since it takes a little time to search, I try to display a gif image during ajax communication so that it is easy to understand that the search is in progress.
Also, if the search takes too long, an error will occur. (10 seconds) If you keep searching, the user will be worried.
css file
#loading {
display: table;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background-color: #fff;
opacity: 0.8;
}
#loading .loadingMsg {
display: table-cell;
text-align: center;
vertical-align: middle;
padding-top: 140px;
background: image-url("loading.gif") center center no-repeat;
}
There are several sites where you can create gif files for free, so let's create them. I made it on this site.
Make a note of what went wrong. (I would be grateful if you could tell me more about it ...)
Actually I want to use only keyword_params as an argument
When hitting the API based on keywords in the controller, it is refreshing if I pass it in hash format as keyword_params
to the argument of search_items, but for some reason it did not work .. (It feels like you won't receive it if it's an active hash ...)
It doesn't work well when turbolinks is turned off.
It seems that ajax communication may not work if turbolinks are included, so I set it not to use all the time, but on the contrary, ajax communication works well because there is no turbolinks. I didn't go there lol. I don't really understand how this area works ...
Recommended Posts