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
--Affichez un formulaire de sélection de catégorie en 3 étapes via la communication Ajax
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.
Comme prémisse
Tout d'abord, installez la gemme requise.
gem jquery-rails
bundle install
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
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
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"}
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 ...)
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.
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.
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,
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.
À 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.
[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