Implementation of sequential search function

Overview

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.

Implementation

js file description

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.

Set up routing

config/routes.rb


resources :posts, only: [:index, :new, :create] do
    collection do
      get 'search'
    end
  end

Edit controller

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.

When an error occurs

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.

Impressions

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

Implementation of sequential search function
Implementation of search function
[Rails 6] Implementation of search function
Rails search function implementation
Implementation of pagination function
Search function [copype implementation]
[Rails] Implementation of search function using gem's ransack
Implementation of search function Learning memo (portfolio creation)
Rails fuzzy search function implementation
Use ransack Search function implementation
Implementation of like function (Ajax)
Implementation of image preview function
[Rails] Implementation of category function
Implementation of category pull-down function
[Rails] Implementation of tutorial function
[Rails] Implementation of like function
[Rails] Implementation of CSV import function
[Rails] Asynchronous implementation of like function
[Rails] Implementation of image preview function
[Rails] About implementation of like function
[Rails] Implementation of user withdrawal function
[Rails] Implementation of CSV export function
Implementation of like function in Java
Implementation of user authentication function using devise (2)
Let's create a TODO application in Java 6 Implementation of search function
Implementation of user authentication function using devise (1)
Implementation of GKAccessPoint
Rails [For beginners] Implementation of comment function
[Rails 6] Implementation of SNS (Twitter) sharing function
Implementation of user authentication function using devise (3)
[Vue.js] Implementation of menu function Implementation version rails6
[Ruby on rails] Implementation of like function
[Vue.js] Implementation of menu function Vue.js introduction rails6
Implementation of Ruby on Rails login function (Session)
[Rails 6] Implementation of inquiry function using Action Mailer
[Rails] Implementation of image enlargement function using lightbox2
[Rails] Implementation of retweet function in SNS application
[JQuery] Implementation procedure of AutoComplete function [Java / Spring]
Implementation of delete function (if you have foreign_key)
Rails hashtag search implementation
Implementation of flash messages
Comment function (Ajax) implementation
Follow function (Ajax) implementation
[Rails] Implement search function
Image preview function implementation
Applied implementation of chat-space
[Rails] Set validation for the search function using Rakuten API (from the implementation of Rakuten API)
Ruby on Rails <2021> Implementation of simple login function (form_with)
[Rails] Implementation of drag and drop function (with effect)
Implementation of Ruby on Rails login function (devise edition)
[Ruby on Rails] Implementation of tagging function/tag filtering function
[Rails] Implementation of multi-layer category function using ancestry "Preparation"
[Rails] Implementation of multi-layer category function using ancestry "seed"
[Rails] Implementation of SNS authentication (Twitter, Facebook, Google) function
Addition of guest login function
About merge processing implementation including sorting function of Stream API
Rails implementation of ajax removal
[Rails] Implementation of multi-layer category function using ancestry "Editing form"
[Swift] Simple implementation of UIImageView
[Rails] Implement User search function
Search function using [rails] ransack