[JAVA] Afficher et publier les données de structure à plusieurs niveaux par ascendance !! ~ Ajax ~

introduction

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);
      });
    })
  });
})

Façon de penser

・ 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!

routage

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

manette

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

Traitement JS

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);
      });
    })
  });
//=============================================
})

Enfin, HTML

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

À la fin

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!

Recommended Posts

Afficher et publier les données de structure à plusieurs niveaux par ascendance !! ~ Ajax ~
[Rails] Affichage des données de structure à plusieurs niveaux à l'aide de la boîte de sélection