Nous avons implémenté une fonction pour modifier dynamiquement les choix en utilisant les données de catégorie créées par l'ascendance.
Publiez comme mémo d'apprentissage. Je ne suis toujours pas familier avec cela, mais j'espère que cela aide!
Formulaire rempli
https://gyazo.com/8a5adc080698873d544b8665855c0901
Voici le code complété!
routes
resources :products, except: [:index] do
get 'new/children_category', to: 'products#children_category'
get 'new/grandchildren_category', to: 'products#grandchildren_category'
end
puroducts_controller
before_action :set_categories, only: [:edit, :update]
~ abrégé ~
def children_category
@children_category = Category.where(ancestry: params[:parent_category_id])
render json: @children_category
end
def grandchildren_category
@grandchildren_category = Category.where(ancestry: "#{params[:parent_category_id]}/#{params[:children_category_id]}")
render json: @grandchildren_category
end
puroducts/new_html_haml
.input-field__contents
.input-field__contents-data
%p.subline
Détails du produit
.input-field__contents-image__headline
.headlabel
= f.label :category_id, "Catégorie"
%span.necessary
Obligatoire
.sell__about__right__wrap-box.parent
%select.select-box1#parent
%option{value: 0} ---
- @parents.each do |parent|
%option{value: "#{parent.id}"} #{parent.name}
.child
%select.select-box2#child
.grand_child
.select-box3
= f.collection_select(:category_id, [], :id, :name, {prompt: "---"}, {id: "grand_child"})
category_js
$(function(){
let buildPrompt = `<option value>---</option>`
let buildHtmlOption = function(parent) {
let option = `<option value ="${parent.id}">${parent.name}</option>`
return option
}
$('#parent').change(function() {
let parent_id = $(this).val();
$.ajax({
type: 'GET',
url: 'products/new/children_category',
data: {parent_category_id: parent_id},
dataType: 'json'
})
.done(function(parent) {
$('.child').css('display', 'block');
$('#child').empty();
$('.grand_child').css('display', 'none');
$('#child').append(buildPrompt);
parent.forEach(function(child) {
var html_option = buildHtmlOption(child);
$('#child').append(html_option);
});
})
.fail(function() {
alert('Erreur')
});
});
$(this).on("change", "#child", function() {
let parent_id = $("#parent").val();
let child_id = $("#child").val();
$.ajax({
type: 'GET',
url: 'products/new/grandchildren_category',
data: {
parent_category_id: parent_id,
children_category_id: child_id
},
dataType: 'json'
})
.done(function(parent) {
$('.grand_child').css('display', 'block');
$('#grand_child').empty();
$('#grand_child').append(buildPrompt);
parent.forEach(function(child) {
var html_option = buildHtmlOption(child);
console.log(buildHtmlOption(html_option));
$('#grand_child').append(html_option);
});
})
});
})
・ Après avoir sélectionné la catégorie parent et déclenché l'événement, ajoutez la catégorie ** enfant **. ・ Après avoir sélectionné la catégorie enfant et déclenché l'événement, ajoutez la catégorie ** petit-fils **. · Utilisez ajax pour créer un ** chemin ** pour les catégories enfants et petits-enfants à afficher ・ Enfin, la valeur de la catégorie petit-enfant sera enregistrée.
C'est à peu près comme ça.
Jetons un coup d'oeil un par un!
En tant que flux de processus du programme, affichez enfin la catégorie enfant et la catégorie parent en vue. Il effectue en fait le traitement avec le contrôleur et js, donc il crée un chemin vers le contrôleur lorsque la demande se réunit.
routes
resources :products, except: [:index] do
#children_catégorie Chemin pour passer à l'action
get 'new/children_category', to: 'products#children_category'
#grandchildren_catégorie Chemin pour passer à l'action
get 'new/grandchildren_category', to: 'products#grandchildren_category'
end
En principe, comme le traitement ajax est effectué, accédez au contrôleur après le traitement ajax effectué par js. À ce moment, le contrôleur doit trouver la valeur de la catégorie et la renvoyer à js. Par conséquent, écrivez comme suit.
puroducts_controller
before_action :set_categories, only: [:edit, :update]
~ abrégé ~
def children_category
#.Utilisez où trouver la valeur de l'ascendance et l'assignez à la variable d'instance
@children_category = Category.where(ancestry: params[:parent_category_id])
#Je retournerai la valeur recherchée de l'ascendance à js
render json: @children_category
end
def grandchildren_category
#.Utilisez où trouver la valeur de l'ascendance et l'assignez à la variable d'instance
@grandchildren_category = Category.where(ancestry: "#{params[:parent_category_id]}/#{params[:children_category_id]}")
#Je retournerai la valeur recherchée de l'ascendance à js
render json: @grandchildren_category
end
Dans js, l'événement sera déclenché chaque fois qu'une catégorie est sélectionnée. Plus précisément ・ Lorsque la catégorie ** parent ** est sélectionnée, l'événement se déclenche et la catégorie d'élément ** enfant ** est affichée. ・ Lorsque la catégorie ** enfant ** est sélectionnée, l'événement se déclenche et la catégorie d'élément ** petit-fils ** s'affiche.
En tant que processus, lorsque l'événement se déclenche, ajax obtient la valeur du contrôleur et ** for Each ** exprime tout.
category_js
//①=====Définir la vue à afficher en HTML ===========================
$(function(){
let buildPrompt = `<option value>---</option>`
let buildHtmlOption = function(parent) {
let option = `<option value ="${parent.id}">${parent.name}</option>`
return option
}
//=================================================
//②=====Traitement pour sélectionner la catégorie parente et appeler la catégorie enfant ============
$('#parent').change(function() {
let parent_id = $(this).val();
//Envoyer au contrôleur avec ajax
$.ajax({
type: 'GET',
url: 'products/new/children_category',
data: {parent_category_id: parent_id},
dataType: 'json'
})
//Ce qui suit est le traitement après la réponse du contrôleur
.done(function(parent) {
$('.child').css('display', 'block');
$('#child').empty();
$('.grand_child').css('display', 'none');
$('#child').append(buildPrompt);
//Obtenez toutes les valeurs obtenues du contrôleur avec forEach,.Ajouter à l'élément HTML avec ajout
parent.forEach(function(child) {
var html_option = buildHtmlOption(child);
$('#child').append(html_option);
});
})
.fail(function() {
alert('Erreur')
});
});
//=============================================
//②=====Traitement pour sélectionner une catégorie enfant et appeler une catégorie petit-enfant ============
$(this).on("change", "#child", function() {
let parent_id = $("#parent").val();
let child_id = $("#child").val();
//Envoyer au contrôleur avec ajax
$.ajax({
type: 'GET',
url: 'products/new/grandchildren_category',
data: {
parent_category_id: parent_id,
children_category_id: child_id
},
dataType: 'json'
})
//Ce qui suit est le traitement après la réponse du contrôleur
.done(function(parent) {
$('.grand_child').css('display', 'block');
$('#grand_child').empty();
$('#grand_child').append(buildPrompt);
//Obtenez toutes les valeurs obtenues du contrôleur avec forEach,.Ajouter à l'élément HTML avec ajout
parent.forEach(function(child) {
var html_option = buildHtmlOption(child);
console.log(buildHtmlOption(html_option));
$('#grand_child').append(html_option);
});
})
});
//=============================================
})
Le seul point à noter en HTML est de savoir si l'attribut id dans js et l'attribut id dans HTML sont incohérents.
Cependant, une petite astuce est nécessaire pour enregistrer la valeur de la dernière catégorie de petit-enfant.
puroducts/new_html_haml
.input-field__contents
.input-field__contents-data
%p.subline
Détails du produit
.input-field__contents-image__headline
.headlabel
= f.label :category_id, "Catégorie"
%span.necessary
Obligatoire
.sell__about__right__wrap-box.parent
%select.select-box1#parent
%option{value: 0} ---
#Afficher toutes les valeurs de la catégorie parent
- @parents.each do |parent|
%option{value: "#{parent.id}"} #{parent.name}
.child
# #La vue définie dans js est insérée à la place de l'enfant
%select.select-box2#child
.grand_child
.select-box3
# id:grand_La vue définie dans js est insérée à la place de l'enfant
#De plus, pour enregistrer correctement la valeur de la catégorie de petit-enfant sélectionnée, écrivez comme suit.
= f.collection_select(:category_id, [], :id, :name, {prompt: "---"}, {id: "grand_child"})
En complément, veuillez consulter le site suivant car je me suis référé à la description suivante
f.collection_select(:category_id, [], :id, :name, {prompt: "---"}, {id: "grand_child"})
#Description de référence
#collection_select(Nom de l'objet,Nom de la méthode,Tableau d'éléments,Attribut d'élément de valeur,Élément de texte[,Options ou attributs HTML ou attributs d'événement])
Article de référence: https://railsdoc.com/page/collection_select
Le processus n'est pas si compliqué, j'ai donc vérifié chacun d'eux et cela a fonctionné!
Si vous obtenez une erreur ou si vous n'obtenez pas correctement la valeur, vérifiez ** binding.pry **, ** console.log (); **, ** debugger **!
Merci beaucoup!