This time, about the implementation of the sequential search function I didn't understand much when I implemented it myself while looking at the curriculum, so I will post it with the meaning of the output.
The sequential search function is, for example, when the tags "ruby", "python", and "ruby on rails" already exist in the database, when the letter r is entered, "ruby" and "ruby on rails" that match the letter r Is a function that instantly displays on the screen as a candidate.
It is commonly called ** incremental search **.
What is incremental search? This is a search function that automatically searches each time you enter a character. Implement using Ajax of JS.
Comment out Turbolinks so that tag.js can be loaded.
javascript/packs/application.js
require("@rails/ujs").start()
// require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("../tag")
Create and edit tag.js.
javascript/tag.js
if (location.pathname.match("posts/new")){
window.addEventListener("load", (e) => {
const inputElement = document.getElementById("post_tag_name");
inputElement.addEventListener("keyup", (e) => {
const input = document.getElementById("post_tag_name").value;
const xhr = new XMLHttpRequest();
xhr.open("GET", `search/?input=${input}`, true);
xhr.responseType = "json";
xhr.send();
xhr.onload = () => {
const tagName = xhr.response.keyword;
const searchResult = document.getElementById('search-result')
searchResult.innerHTML = ''
tagName.forEach(function(tag){
const parentsElement = document.createElement('div')
const childElement = document.createElement('div')
parentsElement.setAttribute('id', 'parents')
childElement.setAttribute('id', tag.id )
childElement.setAttribute('class', 'child' )
parentsElement.appendChild(childElement)
childElement.innerHTML = tag.name
searchResult.appendChild(parentsElement)
const clickElement = document.getElementById(tag.id)
clickElement.addEventListener("click", () => {
document.getElementById("post_tag_name").value = clickElement.textContent;
clickElement.remove();
})
})
}
});
})
};
From here, let's take a closer look at the code details.
javascript/tag.js
const input = document.getElementById("post_tag_name").value;
const xhr = new XMLHttpRequest();
xhr.open("GET", `search/?input=${input}`, true);
xhr.responseType = "json";
xhr.send();
Here, Ajax is described after assigning the value entered in the element with the ID name post_tag_name to "input".
In later editing, we will set the routing associated with the search action, so set the path to the search action with the "open method". At this time, the value assigned to "input" is set as the query parameter. In addition, the data type of the response is specified as "json" and it is sent.
In addition, we will describe the search action (search for tags) on the controller later.
Set it as a value corresponding to the key called keyword, and later use the description returned as json data as the controller.
javascript/tag.js
const parentsElement = document.createElement('div')
const childElement = document.createElement('div')
Here, a div element is created to display the result of the incremental search on the screen. Incremental search results will be added to the created div element.
javascript/tag.js
parentsElement.setAttribute('id', 'parents')
childElement.setAttribute('id', tag.id )
childElement.setAttribute('class', 'child' )
The ID and class name are given to the div element created earlier. Assign the ID of the tag to be displayed to childElement. It also gives a class name for assigning CSS.
javascript/tag.js
parentsElement.appendChild(childElement)
childElement.innerHTML = tag.name
searchResult.appendChild(parentsElement)
In this part, we will add childElement as a child element of parentsElement. Next, generate the HTML of the tag to be displayed on childElement. Finally, we have added parentsElement to the child elements of searchResult.
javascript/tag.js
const searchResult = document.getElementById('search-result')
searchResult.innerHTML = ''
An empty string is assigned to the searchResult so that it will not be displayed twice after the second character.
javascript/tag.js
const clickElement = document.getElementById(tag.id)
clickElement.addEventListener("click", () => {
document.getElementById("post_tag_name").value = clickElement.textContent;
clickElement.remove();
When the tag displayed as a candidate is clicked, the text element of the selected tag is set as the value of the input form. Finally, the selected tag is removed from the list of views.
The above is a series of movements of incremental search.
config/routes.rb
resources :posts, only: [:index, :new, :create] do
collection do
get 'search'
end
end
controller/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all.order(created_at: :desc)
end
---abridgement---
def search
return nil if params[:input] == ""
tag = Tag.where(['name LIKE ?', "%#{params[:input]}%"])
render json:{ keyword: tag }
end
---abridgement---
end
This completes the implementation. Let's check the operation.
The possible solution to the error in this implementation is to pay attention to the Id name when getElementById is done.
In this implementation, we have implemented an incremental search for the post_tag model of the form object.
Also, when you look at the full text of js, there is a description of the path on the first line. This time, I wanted to implement a function to search sequentially by entering tags when posting new posts, so it is posts / new.
Other than these two points, I think you can copy and paste.
Oh, don't forget to turn off Turbo Links or forget to load tag.js.
There are few opportunities to touch javascript in the curriculum, and I am not good at it, so I will do my best.
Recommended Posts