[JAVA] [Rails] Implémentation de la fonction de catégorie multicouche à l'aide de l'ascendance "Formulaire de création"

Cible

ezgif.com-video-to-gif.gif

Environnement de développement

・ Rubis: 2.5.7 Rails: 5.2.4 ・ Vagrant: 2.2.7 -VirtualBox: 6.1 ・ Système d'exploitation: macOS Catalina

supposition

Ce qui suit a été mis en œuvre.

Présentation minceIntroduction de Bootstrap 3Introduction de Font Awesome

la mise en oeuvre

1. Créez une méthode dans category.rb

category.rb


def self.category_parent_array_create
  category_parent_array = ['---']
  Category.where(ancestry: nil).each do |parent|
    category_parent_array << [parent.name, parent.id]
  end
  return category_parent_array
end

[Explication]

(1) Préparez un tableau pour créer une boîte de sélection pour la catégorie parente et stocker les valeurs initiales.

category_parent_array = ['---']

(2) La valeur de l'ascendance est «nil», c'est-à-dire que toutes les catégories parentes sont extraites et que le nom et l'ID de la catégorie sont stockés dans le tableau créé dans (1).

Category.where(ancestry: nil).each do |parent|
  category_parent_array << [parent.name, parent.id]
end

** * Les points importants ** [parent.name, parent.id] ➡︎ Lors de l'affichage de la catégorie parente dans la zone de sélection de la vue Le premier argument (parent.name) devient la valeur affichée sur le navigateur, Le deuxième argument (parent.id) est la valeur à envoyer en tant que paramètre.

③ Renvoie le tableau créé dans comme valeur de retour.

return category_parent_array

2. Créez une méthode dans book_category.rb

book_category.rb


  def self.maltilevel_category_create(book, parent_id, children_id, grandchildren_id)
    if parent_id.present? && parent_id != '---'
      category = Category.find(parent_id)
      BookCategory.create(book_id: book.id, category_id: category.id)
    end

    if children_id.present? && children_id != '---'
      category = Category.find(children_id)
      BookCategory.create(book_id: book.id, category_id: category.id)
    end

    if grandchildren_id.present? && grandchildren_id != '---'
      category = Category.find(grandchildren_id)
      BookCategory.create(book_id: book.id, category_id: category.id)
    end
  end

[Explication]

① Recevez 4 arguments du contrôleur.

(book, parent_id, children_id, grandchildren_id)

book: Données du livre à créer parent_id: ID de la catégorie parent children_id: ID de la catégorie enfant petitchildren_id: ID de la catégorie de petit-enfant

(2) Si l'ID de la catégorie parente est reçu comme argument et qu'il ne s'agit pas de la valeur initiale, le processus est exécuté.

if parent_id.present? && parent_id != '---'

(3) Extrayez l'enregistrement correspondant à l'ID de catégorie parent reçu en tant qu'argument du modèle de catégorie et affectez-le à la variable.

category = Category.find(parent_id)

④ Créez un enregistrement dans BookCategory (table intermédiaire). ** **

BookCategory.create(book_id: book.id, category_id: category.id)

3. Modifiez le contrôleur

books_controller.rb


def create
  @book = Book.new(book_params)
  @book.user_id = current_user.id
  if @book.save
    BookCategory.maltilevel_category_create(
      @book,
      params[:parent_id],
      params[:children_id],
      params[:grandchildren_id]
    )
    redirect_to books_path
  else
    @books = Book.all
    @category_parent_array = Category.category_parent_array_create
    render 'index'
  end
end

def index
  @book = Book.new
  @books = Book.all
  @category_parent_array = Category.category_parent_array_create
end

def get_category_children
  @category_children = Category.find(params[:parent_id]).children
end

def get_category_grandchildren
  @category_grandchildren = Category.find(params[:children_id]).children
end

[Explication]

(1) Passez quatre arguments à la méthode maltilevel_category_create et exécutez-la.

BookCategory.maltilevel_category_create(
  @book,
  params[:parent_id],
  params[:children_id],
  params[:grandchildren_id]
)

** ◎ Recevez les paramètres envoyés par la communication Ajax. ** **

params[:parent_id],
params[:children_id],
params[:grandchildren_id]

(2) Assignez le tableau reçu comme valeur de retour de la méthode category_parent_array_create à la variable d'instance.

@category_parent_array = Category.category_parent_array_create

③ Extrayez les catégories enfants associées à la catégorie parent sélectionnée.

def get_category_children
  @category_children = Category.find(params[:parent_id]).children
end

④ Extrayez la catégorie petit-enfant associée à la catégorie enfant sélectionnée.

def get_category_grandchildren
  @category_grandchildren = Category.find(params[:children_id]).children
end

4. Créez / modifiez le fichier json.jbuilder

Terminal


$ touch app/views/books/get_category_children.json.jbuilder

ruby:books/get_category_children.json.jbuilder


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

Terminal


$ touch app/views/books/get_category_grandchildren.json.jbuilder

ruby:books/get_category_grandchildren.json.jbuilder


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

[Explication]

① Itérez les enregistrements extraits par l'action get_category_children pour créer un tableau.

json.array! @category_children do |children|

(2) Stockez chaque ID et nom dans le tableau créé par .

json.id children.id
json.name children.name

** ◎ Valeur renvoyée lorsque la catégorie parente (entreprise) est sélectionnée **

[
  {
    "id": 2, 
    "name": "La finance"
  },
  {
    "id": 6, 
    "name": "Économie"
  },
  {
    "id": 9, 
    "name": "la gestion"
  },
  {
    "id": 13, 
    "name": "commercialisation"
  },
]

** ◎ Lorsque la catégorie enfant (finance) est sélectionnée **

[
  {
    "id": 3, 
    "name": "Stock"
  },
  {
    "id": 4, 
    "name": "échange"
  },
  {
    "id": 5, 
    "name": "impôt"
  },
]

5. Ajouter un routage

routes.rb


#Postscript
get 'get_category/children', to: 'books#get_category_children', defaults: { format: 'json' }
get 'get_category/grandchildren', to: 'books#get_category_grandchildren', defaults: { format: 'json' }

6. Modifier la vue

slim:books/index.html.slim


.category-form
  = label_tag 'Genre'
  = select_tag 'parent_id', options_for_select(@category_parent_array), id: 'parent-category', class: 'form-control'
  i.fas.fa-chevron-down
br

[Explication]

(1) Affichez les données dans la variable d'instance définie par le contrôleur dans la boîte de sélection et définissez la propriété (nom du paramètre) sur parent_id.

= select_tag 'parent_id', options_for_select(@category_parent_array), id: 'parent-category', class: 'form-control'

7. Créer / modifier un fichier JavaScript

Terminal


$ touch app/assets/javascripts/category_form.js

category_form.js


$(function() {
  function appendOption(category) {
    let html = `<option value='${category.id}' data-category='${category.id}'>${category.name}</option>`;
    return html;
  }

  function appendChidrenBox(insertHTML) {
    let childrenSelectHtml = '';
    childrenSelectHtml = `
      <div id='children-wrapper'>
        <select id='children-category' class='form-control' name='[children_id]'>
          <option value='---' data-category='---'>---</option>
          ${insertHTML}
        </select>
        <i class='fas fa-chevron-down'></i>
      </div>
    `;
    $('.category-form').append(childrenSelectHtml);
  }

  function appendGrandchidrenBox(insertHTML) {
    let grandchildrenSelectHtml = '';
    grandchildrenSelectHtml = `
      <div id='grandchildren-wrapper'>
        <select id='grandchildren-category' class='form-control' name='[grandchildren_id]'>
          <option value='---' data-category='---'>---</option>
          ${insertHTML}
        </select>
        <i class='fas fa-chevron-down'></i>
      </div>
    `;
    $('.category-form').append(grandchildrenSelectHtml);
  }

  $('#parent-category').on('change', function() {
    let parentId = document.getElementById('parent-category').value;
    if (parentId != '---') {
      $.ajax({
        url: '/get_category/children',
        type: 'GET',
        data: {
          parent_id: parentId,
        },
        dataType: 'json',
      })
        .done(function(children) {
          $('#children-wrapper').remove();
          $('#grandchildren-wrapper').remove();
          let insertHTML = '';
          children.forEach(function(children) {
            insertHTML += appendOption(children);
          });
          appendChidrenBox(insertHTML);
        })
        .fail(function() {
          alert('Échec de l'obtention du genre');
        });
    } else {
      $('#children-wrapper').remove();
      $('#grandchildren-wrapper').remove();
    }
  });

  $('.category-form').on('change', '#children-category', function() {
    let childrenId = $('#children-category option:selected').data('category');
    if (childrenId != '---') {
      $.ajax({
        url: '/get_category/grandchildren',
        type: 'GET',
        data: {
          children_id: childrenId,
        },
        dataType: 'json',
      })
        .done(function(grandchildren) {
          if (grandchildren.length != 0) {
            $('#grandchildren-wrapper').remove();
            let insertHTML = '';
            grandchildren.forEach(function(grandchildren) {
              insertHTML += appendOption(grandchildren);
            });
            appendGrandchidrenBox(insertHTML);
          }
        })
        .fail(function() {
          alert('Échec de l'obtention du genre');
        });
    } else {
      $('#grandchildren-wrapper').remove();
    }
  });
});

[Explication]

(1) Définissez les options de la boîte de sélection.

$(function() {
  function appendOption(category) {
    let html = `<option value='${category.id}' data-category='${category.id}'>${category.name}</option>`;
    return html;
  }

** ◎ Définissez la valeur à envoyer en tant que paramètre. ** **

<option value='${category.id}' data-category='${category.id}'>

** * Les points importants ** Il correspond au paramètre reçu par «①» de «3. Edit controller».

** ◎ Définissez la valeur à afficher dans la boîte de sélection. ** **

${category.name}

② Créez une boîte de sélection pour le genre enfant.

function appendChidrenBox(insertHTML) {
  let childrenSelectHtml = '';
  childrenSelectHtml = `
    <div id='children-wrapper'>
      <select id='children-category' class='form-control' name='[children_id]'>
        <option value='---' data-category='---'>---</option>
        ${insertHTML}
      </select>
      <i class='fas fa-chevron-down'></i>
    </div>
  `;
  $('.category-form').append(childrenSelectHtml);
}

** ◎ Définissez le nom du paramètre du paramètre créé dans. ** **

name='[children_id]

** ◎ Créez une boîte de sélection de catégorie enfant basée sur les options définies dans . ** **

${insertHTML}

** ◎ Affichez la boîte de sélection de la catégorie enfant. ** **

$('.category-form').append(childrenSelectHtml);

③ Créez une boîte de sélection pour le genre de petit-enfant. (Comme c'est presque la même chose que «②», l'explication est omise)

function appendGrandchidrenBox(insertHTML) {
  let grandchildrenSelectHtml = '';
  grandchildrenSelectHtml = `
    <div id='grandchildren-wrapper'>
      <select id='grandchildren-category' class='form-control' name='[grandchildren_id]'>
        <option value='---' data-category='---'>---</option>
        ${insertHTML}
      </select>
      <i class='fas fa-chevron-down'></i>
    </div>
  `;
  $('.category-form').append(grandchildrenSelectHtml);
}

④ Créez un événement qui se déclenche lorsque la catégorie parent est sélectionnée.

$('#parent-category').on('change', function() {
  let parentId = document.getElementById('parent-category').value;
  if (parentId != '---') {
    $.ajax({
      url: '/get_category/children',
      type: 'GET',
      data: {
        parent_id: parentId,
      },
      dataType: 'json',
    })
      .done(function(children) {
        $('#children-wrapper').remove();
        $('#grandchildren-wrapper').remove();
        let insertHTML = '';
        children.forEach(function(children) {
          insertHTML += appendOption(children);
        });
        appendChidrenBox(insertHTML);
      })
      .fail(function() {
        alert('Échec de l'obtention du genre');
      });
  } else {
    $('#children-wrapper').remove();
    $('#grandchildren-wrapper').remove();
  }
});

** ◎ Se déclenche lorsque la catégorie parente est sélectionnée. ** **

$('#parent-category').on('change', function() {});

** ◎ Obtenez l'ID de la catégorie parent sélectionnée et attribuez-le à la variable. ** **

let parentId = document.getElementById('parent-category').value;

** ◎ Si la catégorie parente n'est pas la valeur par défaut Définissez l'ID de la catégorie parent obtenue précédemment dans le paramètre (parent_id), Exécutez l'action get_category_children de manière asynchrone. ** **

if (parentId != '---') {
  $.ajax({
    url: '/get_category/children',
    type: 'GET',
    data: {
      parent_id: parentId,
    },
    dataType: 'json',
  })

** ◎ Si la communication Ajax réussit, créez une boîte de sélection pour la catégorie enfant. De plus, si la catégorie parente est modifiée alors que les cases de sélection sous la catégorie enfant sont déjà affichées, Supprimez les cases de sélection sous la catégorie enfant et recréez les cases de sélection pour les catégories enfants. ** **

.done(function(children) {
  $('#children-wrapper').remove();
  $('#grandchildren-wrapper').remove();
  let insertHTML = '';
  children.forEach(function(children) {
    insertHTML += appendOption(children);
  });
  appendChidrenBox(insertHTML);
})

** ◎ Si la communication asynchrone échoue, une alerte s'affiche. ** **

.fail(function() {
  alert('Échec de l'obtention du genre');
});

** ◎ Si la catégorie parente est la valeur initiale, supprimez la catégorie enfant et ci-dessous. ** **

} else {
  $('#children-wrapper').remove();
  $('#grandchildren-wrapper').remove();
}

④ Créez un événement qui se déclenche lorsqu'une catégorie enfant est sélectionnée. (Presque le même que )

$('.category-form').on('change', '#children-category', function() {
  let childrenId = $('#children-category option:selected').data('category');
  if (childrenId != '---') {
    $.ajax({
      url: '/get_category/grandchildren',
      type: 'GET',
      data: {
        children_id: childrenId,
      },
      dataType: 'json',
    })
      .done(function(grandchildren) {
        if (grandchildren.length != 0) {
          $('#grandchildren-wrapper').remove();
          let insertHTML = '';
          grandchildren.forEach(function(grandchildren) {
            insertHTML += appendOption(grandchildren);
          });
          appendGrandchidrenBox(insertHTML);
        }
      })
      .fail(function() {
        alert('Échec de l'obtention du genre');
      });
  } else {
    $('#grandchildren-wrapper').remove();
  }
});

** ◎ Certaines catégories n'ont pas de catégories de petits-enfants, des conditions sont donc données. (Ajoutez des conditions aux catégories enfants si nécessaire) **

if (grandchildren.length != 0)

Mise en garde

Si vous ne désactivez pas turbolinks, la boîte de sélection ne fonctionnera pas de manière asynchrone, alors assurez-vous de la désactiver.

Comment désactiver les turbolinks

Suite

Implémentation de la fonction de catégorie multicouche (formulaire d'édition)

Recommended Posts

[Rails] Implémentation de la fonction de catégorie multicouche à l'aide de l'ascendance "Formulaire de création"
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "Edit Form Edition"
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "Préparation"
[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
[Rails] Implémentation de la fonction de catégorie d'ascendance gemme
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "J'ai essayé de créer une fenêtre avec Bootstrap 3"
[Rails] Implémentation de la fonction de recherche en utilisant le ransack de gem
[Rails] Implémentation de la fonction d'agrandissement d'image à l'aide de lightbox2
Mise en œuvre du formulaire de sélection de catégorie en utilisant JS dans la création d'applications frima
Mise en œuvre de la fonction déroulante de catégorie
[Rails] Implémentation de la fonction tutoriel
[Rails] Implémentation d'une fonction similaire
[Rails] Implémentation de la fonction d'importation CSV
[Rails] Implémentation asynchrone de la fonction similaire
[Rails] Implémentation de la fonction de prévisualisation d'image
[Rails] À propos de la mise en œuvre de la fonction similaire
[Rails] Implémentation de la fonction de retrait utilisateur
[Rails] Implémentation de la fonction d'exportation CSV
[Rails] Implémentation de fonctions de catégorie plusieurs à plusieurs
[Rails] Implémentation d'une nouvelle fonction d'enregistrement au format assistant à l'aide de devise
[Rails] Implémentation de la fonction coupon (avec fonction de suppression automatique par traitement par lots)
[Rails] Implémentation de la fonction de balise à l'aide de la fonction agit-as-taggable-on et de la fonction de complétion d'entrée de balise à l'aide de tag-it
Implémentation de la fonction d'authentification des utilisateurs à l'aide de devise (2)
Implémentation de la fonction d'authentification des utilisateurs à l'aide de devise (1)
Rails [Pour les débutants] Implémentation de la fonction de commentaire
Implémentation de la fonction d'authentification des utilisateurs à l'aide de devise (3)
[Ruby on rails] Implémentation d'une fonction similaire
[Rails] Fonction de catégorie
[Rails] Je vais expliquer la procédure d'implémentation de la fonction follow en utilisant form_with.
Mettre en œuvre la fonction de catégorie de produit en utilisant l'ascendance ① (Préparation)
Mise en place de la fonction de recherche Mémo d'apprentissage (création de portfolio)
[Rails] Mise en œuvre du classement des nombres PV à l'aide de l'impressionniste
[Rails] Implémentation du diaporama d'images à l'aide de Bootstrap 3
Implémentation de la fonction de recherche
Mise en œuvre de la fonction de pagénation
[Rails] Implémentation de la fonction glisser-déposer (avec effet)
Implémentation de la fonction de connexion Ruby on Rails (édition de devise)
Implémentation de la suppression d'ajax dans Rails
Implémentation de la fonction de recherche floue Rails
[Rails] Implémentation de la saisie d'adresse automatique avec jpostal et jp_prefecture
Implémentation de la fonction de recherche séquentielle
Implémentation d'une fonction similaire (Ajax)
Implémentation de la fonction de prévisualisation d'image
Mise en place de la fonction de tri des rails (affichés par ordre de nombre de like)
Implémenter la fonction de catégorie en utilisant l'ancêtre