[RUBY] Mise en œuvre du formulaire de sélection de catégorie en utilisant JS dans la création d'applications frima

introduction

Je fais un clone de l'application Furima pour la tâche finale d'une certaine école de programmation. Je décrirai le contenu du travail de mise en œuvre de la «fonction de sélection de catégorie» requise pour la fonction de liste de produits.

--Création d'un formulaire de sélection déroulant à l'aide de JavaScript

Ce que vous pouvez voir dans cet article

--Affichez un formulaire de sélection de catégorie en 3 étapes via la communication Ajax

Objectifs que vous souhaitez atteindre avec cette fonctionnalité

Lorsque l'élément parent (dames) est sélectionné comme indiqué ci-dessous, le formulaire de sélection d'élément enfant est affiché, et lorsque l'élément enfant est sélectionné, le formulaire de sélection d'élément petit-enfant est affiché ** par communication asynchrone **. De plus, si vous modifiez les choix des enfants et des petits-enfants, le contenu du formulaire sera initialisé ou le formulaire lui-même disparaîtra. Image from Gyazo

Environnement de développement

Écoulement brutal

  1. Installer la gemme
  2. Créez un fichier JS, un contrôleur pour utiliser JS, et décrivez l'appel.
  3. Ajoutez un routage.
  4. Réglez la fonction #search pour rechercher des données sur le contrôleur.
  5. Modifiez le fichier js.
  6. Modifiez le fichier json.jbuilder utilisé pour la communication Ajax.
  7. Répétez 4-6 ci-dessus avec les éléments enfants et petits-enfants.
  8. Ajoutez une action lorsque l'élément enfant / petit-enfant est modifié.
  9. Achèvement

Comme prémisse

Procédure de montage spécifique

0. Installer la gemme

Tout d'abord, installez la gemme requise.

gem jquery-rails
bundle install

1. Écrivez pour utiliser JavaScript

app/javascript/packs/application.js


require('jquery')
require('item/category')

config/webpack/environment.js


const { environment } = require('@rails/webpacker')
const webpack = require('webpack')

environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    jquery: 'jquery',
  })
)

module.exports = environment

Ce sur quoi je suis immédiatement tombé sur le fait que mon environnement de développement était rails6. La plupart des articles que j'ai recherchés sur le net sont des informations avant rails5, Dans rails6, il semble que l'emplacement de génération du fichier application.js et la description de l'appel soient différents, J'étais confus car il ne se chargeait pas bien au début.

Lors du développement, vérifiez la version et décrivez-la en fonction de votre propre environnement.

Je me suis référé à cet article pour l'introduction de jquery dans rails6. => Comment installer jquery dans rails6

2. Ajouter un routage

Pour ajouter une action de recherche au contrôleur d'éléments ultérieurement Ajoutez le routage à l'action de recherche.

routes.rb


Rails.application.routes.draw do
  resources :items do
    collection do
      get :search
    end
  end
end

3. Créez un formulaire de sélection de catégorie dans la vue

Ceci est juste pour référence de ma description. De cette façon, j'ai d'abord créé un formulaire pour la catégorie parent.

ruby:qpp/view/items/new.html.haml


=form_with model @item do |f|
= f.collection_select :category_id, @parents, :id, :name, {prompt: "Veuillez sélectionner"}, {class: "categoryForm", id: "category_form"}

4. Ajouter une action de recherche au contrôleur

Obtenez l'enregistrement avec la nouvelle action.

items_controller


  def new 
    @item = Item.new
    @item_image = ItemImage.new
  end

De plus, j'ai défini before_action parce que je veux obtenir les informations de l'élément parent avant la nouvelle action et créer une action.

ite,s_controller.rb


  before_action :set_parents, only: [:new, :create]

  def set_parents
    @parents = Category.where(ancestry: nil)
  end

ancestry = nil, c'est-à-dire que la valeur de l'élément parent est acquise et affectée à la variable @parents. La raison pour laquelle set_parents est nécessaire non seulement pour new mais aussi pour create est J'ai fait référence à l'article dans ici. (Honnêtement, quand j'écrivais le code, je le savais, je ne savais pas ...)


Ensuite, définissez l'action de recherche pour la recherche par catégorie d'enfants et petits-enfants.

items_controller.rb



  def search
    respond_to do |format|
      format.html
      #communication ajax démarrée
      format.json do
          #Informations sur la catégorie enfant@Substitut pour les enfants
          @childrens = Category.find(params[:parent_id]).children
      end
    end
  end

En passant, je me sentais mal à l'aise d'ajouter «s» au pluriel «enfants». Je pensais qu'il serait difficile de comprendre comment utiliser correctement les enfants et les enfants, alors j'ai décidé d'utiliser des enfants.

5. Créez un fichier json.jbulder

ruby:app/view/items/search.json.jbuilder


json.array! @childrens do |children|
  json.id children.id
  json.name children.name
end

Pour le moment, seuls les éléments enfants sont répertoriés pour l'instant.

6. Modifiez le fichier js et recevez les données envoyées par l'action ci-dessus

  1. Commencez par créer un "formulaire de sélection d'élément enfant" qui apparaît après la sélection de l'élément parent.

category.js


//Formulaire pour sélectionner les éléments enfants
function add_childSelect_tag() {
  let child_select_form = `
              <select name="item[category_id]" id="item_category_id" class="child_category_id">
              <option value="">Choisir une catégorie</option>
              </select>
            `
  return child_select_form;
}

Je ne suis pas doué pour écrire cette partie HTML, mais je pense qu'il est plus facile d'écrire en regardant la forme de l'élément parent avec l'outil de validation de vue.

name = "item [category_id] est la destination des données.

Plus tard, je souhaite supprimer ou initialiser la forme de l'élément enfant (lorsque l'élément parent est modifié, etc.), j'ai donc également ajouté le nom de classe spécifique à l'élément enfant.
2. Décrivez l'option d'acquisition de données dans le formulaire de sélection affiché.

category.js


function add_Option(children) {
  let option_html = `
                    <option value=${children.id}>${children.name}</option>
                    `
  return option_html;
}


3. Définissez l'événement qui se produit après la sélection de la catégorie parent.

category.js


//Événements après sélection d'une catégorie parente
$("#category_form").on("change", function() {
  let parentValue = $("#category_form").val();
  if (parentValue.length !== 0) {
    $.ajax({
      url: '/items/search',
      type: 'GET',
      data: { parent_id: parentValue},
      dataType: 'json'
    })
    .done(function (data){
      let child_select_form = add_childSelect_tag
      $(".ItemInfo__category--form").append(child_select_form);
      data.forEach(function(d){
        let option_html = add_Option(d)
        $(".child_category_id").append(option_html);
      });
    })
    .fail(function (){
      alert("Échec de l'obtention de la catégorie");
});

Comme un flux brutal,

  1. Récupérez les données de l'élément parent et affectez-les à parentValue.
  2. Si les données ne correspondent pas à la valeur initiale dans if ~, communication ajax.
  3. Utilisez append in .done pour afficher le formulaire d'élément enfant créé à l'étape précédente après le formulaire d'élément parent.
  4. Extrayez les données extraites par option une par une et affichez-les.

Ceci termine l'affichage des éléments enfants!
Si vous sélectionnez l'élément parent, le formulaire d'élément enfant sera affiché.

4. Créez un affichage des éléments petits-enfants.

En gros, répétez simplement les étapes pour les éléments enfants.

ruby:app/views/items/search.json.jbuilder


json.array! @grandchildrens do |grandchildren|
  json.id grandchildren.id
  json.name grandchildren.name
end

category.js


//Formulaire de sélection d'élément petit-enfant
function add_grandchildSelect_tag(){
  let grandchild_select_form = `
              <select name="item[category_id]" id="item_category_id" class="grandchild_category_id">
              <option value="">Choisir une catégorie</option>
              </select>
            `
  return grandchild_select_form
}

categroy.js


//Événements après la sélection d'une catégorie enfant
$(document).on("change", ".child_category_id", function(){
  let childValue = $(".child_category_id").val();
  if (childValue.length !=0){
    $.ajax({
      url: '/items/search',
      type: 'GET',
      data: { children_id: childValue},
      dataType: 'json'
    })
    .done(function (gc_data){
      let grandchild_select_form = add_grandchildSelect_tag
      $(".ItemInfo__category--form").append(grandchild_select_form);
      gc_data.forEach(function (gc_d){
        let option_html = add_Option(gc_d);
        $(".grandchild_category_id").append(option_html);
      })
    })
    .fail(function (){
      alert("Échec de l'obtention de la catégorie");
    });
})

Désormais, lorsque vous sélectionnez un élément enfant, le formulaire de sélection d'élément petit-enfant apparaît.

5. Ajoutez une description pour initialiser le formulaire.

À première vue, il semble qu'il a été effectué aux étapes 1 à 4, Si cela reste tel quel, les problèmes suivants se produiront.

En bref, si vous jouez avec la catégorie enfant ou petit-enfant, le formulaire sera ajouté à l'infini.

Donc, en tant que comportement souhaitable

--Lorsque vous modifiez la catégorie parente, le formulaire de catégorie de petit-enfant disparaît et le contenu du formulaire de catégorie d'enfant passe au contenu associé à la catégorie parente. --Si vous modifiez la catégorie enfant, le contenu de la catégorie petit-enfant sera remplacé par les données associées à la catégorie enfant. --Si vous définissez la catégorie parent ou enfant sur la valeur initiale (non sélectionnée), le formulaire de la hiérarchie suivante disparaît.

Ce comportement doit être atteint. Par conséquent, la description suivante a été ajoutée.

category.js


//Événements après sélection d'une catégorie parente
$("#category_form").on("change", function() {
  let parentValue = $("#category_form").val();
  if (parentValue.length !== 0) {
    $.ajax({
      url: '/items/search',
      type: 'GET',
      data: { parent_id: parentValue},
      dataType: 'json'
    })
    .done(function (data){
      $(".child_category_id").remove();
      $(".grandchild_category_id").remove();
      let child_select_form = add_childSelect_tag
      $(".ItemInfo__category--form").append(child_select_form);
      data.forEach(function(d){
        let option_html = add_Option(d)
        $(".child_category_id").append(option_html);
      });
    })
    .fail(function (){
      alert("Échec de l'obtention de la catégorie");
    })
  }else{
    $(".child_category_id").remove();
    $(".grandchild_category_id").remove();  
  }
});

J'ai ajouté ces deux lignes après ①.done

      $(".child_category_id").remove();
      $(".grandchild_category_id").remove();

(2) Cette partie est divisée par else après .fail.

else{
    $(".child_category_id").remove();
    $(".grandchild_category_id").remove();  
  }

Chaque fois que le contenu de la catégorie parent change dans ①, la catégorie enfant / petit-enfant est supprimée une fois, puis la catégorie enfant apparaît. Après l'instruction else dans ②, lorsque le parent sélectionne la valeur initiale.

J'ai ajouté le même code à la partie événement après avoir sélectionné la catégorie enfant.

Et pour activer ces JS après avoir chargé toutes les pages

category.js


window.addEventListener('load', function () {
}

Ceci conclut tout le code.

C'est vraiment complet! !!


Après cela, j'ai oublié par inadvertance de dire aux membres de l'équipe "db: seed", Il y avait une situation comme "Je ne peux pas sélectionner une catégorie !! Pourquoi?!", Mais j'ai pu la résoudre en toute sécurité.

Articles référencés

[Rails] Comment implémenter la fonction de catégorie d'une certaine application frima Fonction de catégorie de l'application Furima ~ Utiliser gem: ancestry ~ [Rails] Création d'une zone de catégorie à l'aide de la communication Ajax

Recommended Posts

Mise en œuvre du formulaire de sélection de catégorie en utilisant JS dans la création d'applications frima
[Rails] Implémentation de la fonction de catégorie multicouche à l'aide de l'ascendance "Formulaire de création"
Implémentation du regroupement de chiffres dans l'application Furima
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "Edit Form Edition"
Politique de contre-mesure CSRF et exemple de mise en œuvre dans une application REST utilisant "Spring Boot" + "EXT JS"
[Rails] Implémentation de la fonction de catégorie multicouche à l'aide de l'ascendance "seed edition"
[Rails] Implémentation de la fonction de catégorie
Mise en œuvre de la fonction déroulante de catégorie
Implémentation Java de tri-tree
Implémentation de HashMap avec kotlin
[Rails] Implémentation d'une nouvelle fonction d'enregistrement au format assistant à l'aide de devise
Créons une application TODO en Java 4 Implémentation de la fonction de publication
Créons une application TODO en Java 6 Implémentation de la fonction de recherche
Créons une application TODO en Java 8 Implémentation des fonctions d'édition