[JAVA] [Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Erstellungsformular"

Ziel

ezgif.com-video-to-gif.gif

Entwicklungsumgebung

・ Ruby: 2.5.7 Schienen: 5.2.4 ・ Vagrant: 2.2.7 -VirtualBox: 6.1 ・ Betriebssystem: macOS Catalina

Annahme

Folgendes wurde implementiert.

Schlanke EinführungEinführung von Bootstrap 3Einführung von Font Awesome

Implementierung

1. Erstellen Sie eine Methode in 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

[Erläuterung]

(1) Bereiten Sie ein Array vor, um ein Auswahlfeld für die übergeordnete Kategorie zu erstellen und die Anfangswerte zu speichern.

category_parent_array = ['---']

(2) Der Wert der Abstammung ist "Null", dh alle übergeordneten Kategorien werden extrahiert und der Kategoriename und die ID werden in dem in (1) erstellten Array gespeichert.

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

** * Wichtige Punkte ** [parent.name, parent.id] ➡︎ Bei Anzeige der übergeordneten Kategorie im Auswahlfeld in der Ansicht Das erste Argument (parent.name) wird zum Wert, der im Browser angezeigt wird. Das zweite Argument (parent.id) ist der Wert, der als Parameter gesendet werden soll.

③ Gibt das in erstellte Array als Rückgabewert zurück.

return category_parent_array

2. Erstellen Sie eine Methode in "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

[Erläuterung]

① Erhalten Sie 4 Argumente vom Controller.

(book, parent_id, children_id, grandchildren_id)

book: Daten des zu erstellenden Buches parent_id: ID der übergeordneten Kategorie children_id: ID der untergeordneten Kategorie Enkelkinder_ID: ID der Enkelkategorie

(2) Wenn die ID der übergeordneten Kategorie als Argument empfangen wird und nicht der Anfangswert ist, wird der Prozess ausgeführt.

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

(3) Extrahieren Sie den Datensatz, der der als Argument empfangenen übergeordneten Kategorie-ID entspricht, aus dem Kategoriemodell und weisen Sie ihn der Variablen zu.

category = Category.find(parent_id)

④ Erstellen Sie einen Datensatz in BookCategory (Zwischentabelle). ** ** **

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

3. Bearbeiten Sie den Controller

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

[Erläuterung]

(1) Übergeben Sie vier Argumente an die Methode maltilevel_category_create und führen Sie sie aus.

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

** ◎ Empfangen Sie die von der Ajax-Kommunikation gesendeten Parameter. ** ** **

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

(2) Weisen Sie der Instanzvariablen das empfangene Array als Rückgabewert der Methode "category_parent_array_create" zu.

@category_parent_array = Category.category_parent_array_create

③ Extrahieren Sie die untergeordneten Kategorien, die der ausgewählten übergeordneten Kategorie zugeordnet sind.

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

④ Extrahieren Sie die Enkelkategorie, die der ausgewählten Kinderkategorie zugeordnet ist.

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

4. Erstellen / bearbeiten Sie die Datei "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

[Erläuterung]

① Iterieren Sie die mit der Aktion get_category_children extrahierten Datensätze, um ein Array zu erstellen.

json.array! @category_children do |children|

(2) Speichern Sie jede ID und jeden Namen in dem von erstellten Array.

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

** ◎ Rückgabewert bei Auswahl der übergeordneten Kategorie (Unternehmen) **

[
  {
    "id": 2, 
    "name": "Finanzen"
  },
  {
    "id": 6, 
    "name": "Wirtschaft"
  },
  {
    "id": 9, 
    "name": "Management"
  },
  {
    "id": 13, 
    "name": "Marketing"
  },
]

** ◎ Wenn die untergeordnete Kategorie (Finanzen) ausgewählt ist **

[
  {
    "id": 3, 
    "name": "Lager"
  },
  {
    "id": 4, 
    "name": "Austausch-"
  },
  {
    "id": 5, 
    "name": "MwSt"
  },
]

5. Routing hinzufügen

routes.rb


#Nachtrag
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. Ansicht bearbeiten

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

[Erläuterung]

(1) Zeigen Sie die Daten in der vom Controller definierten Instanzvariablen im Auswahlfeld an und setzen Sie die Eigenschaft (Parametername) auf "parent_id".

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

7. Erstellen / bearbeiten Sie eine JavaScript-Datei

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('Das Genre konnte nicht verstanden werden');
        });
    } 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('Das Genre konnte nicht verstanden werden');
        });
    } else {
      $('#grandchildren-wrapper').remove();
    }
  });
});

[Erläuterung]

(1) Stellen Sie die Optionen des Auswahlfelds ein.

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

** ◎ Legen Sie den Wert fest, der als Parameter gesendet werden soll. ** ** **

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

** * Wichtige Punkte ** Es entspricht dem Parameter, der von von 3. Edit controller empfangen wird.

** ◎ Legen Sie den Wert fest, der im Auswahlfeld angezeigt werden soll. ** ** **

${category.name}

(2) Erstellen Sie ein Auswahlfeld für das untergeordnete Genre.

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

** ◎ Legen Sie den Parameternamen des in erstellten Parameters fest. ** ** **

name='[children_id]

** ◎ Erstellen Sie ein Auswahlfeld für untergeordnete Kategorien basierend auf den in festgelegten Optionen. ** ** **

${insertHTML}

** ◎ Zeigen Sie das Auswahlfeld der untergeordneten Kategorie an. ** ** **

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

③ Erstellen Sie ein Auswahlfeld für das Enkelkind-Genre. (Da es fast dasselbe ist wie "②", wird die Erklärung weggelassen)

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

④ Erstellen Sie ein Ereignis, das ausgelöst wird, wenn die übergeordnete Kategorie ausgewählt wird.

$('#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('Das Genre konnte nicht verstanden werden');
      });
  } else {
    $('#children-wrapper').remove();
    $('#grandchildren-wrapper').remove();
  }
});

** ◎ Wird ausgelöst, wenn die übergeordnete Kategorie ausgewählt ist. ** ** **

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

** ◎ Holen Sie sich die ID der ausgewählten übergeordneten Kategorie und weisen Sie sie der Variablen zu. ** ** **

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

** ◎ Wenn die übergeordnete Kategorie nicht der Standardwert ist Legen Sie die ID der übergeordneten Kategorie fest, die Sie zuvor im Parameter (parent_id) erhalten haben. Führen Sie die Aktion "get_category_children" asynchron aus. ** ** **

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

** ◎ Wenn die Ajax-Kommunikation erfolgreich ist, erstellen Sie ein Auswahlfeld für die untergeordnete Kategorie. Wenn die übergeordnete Kategorie geändert wird, während die Auswahlfelder unter der untergeordneten Kategorie bereits angezeigt werden, Löschen Sie die Auswahlfelder unter der untergeordneten Kategorie und erstellen Sie die Auswahlfelder für die untergeordneten Kategorien neu. ** ** **

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

** ◎ Wenn die asynchrone Kommunikation fehlschlägt, wird eine Warnung angezeigt. ** ** **

.fail(function() {
  alert('Das Genre konnte nicht verstanden werden');
});

** ◎ Wenn die übergeordnete Kategorie der Anfangswert ist, löschen Sie die untergeordnete Kategorie und darunter. ** ** **

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

④ Erstellen Sie ein Ereignis, das ausgelöst wird, wenn eine untergeordnete Kategorie ausgewählt wird. (Fast das gleiche wie "③")

$('.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('Das Genre konnte nicht verstanden werden');
      });
  } else {
    $('#grandchildren-wrapper').remove();
  }
});

** ◎ Einige Kategorien haben keine Enkelkategorien, daher werden Bedingungen angegeben. (Fügen Sie nach Bedarf Bedingungen zu untergeordneten Kategorien hinzu.) **

if (grandchildren.length != 0)

Hinweis

Wenn Sie "Turbolinks" nicht deaktivieren, funktioniert das Auswahlfeld nicht asynchron. Deaktivieren Sie es daher unbedingt.

So deaktivieren Sie Turbolinks

Folge

Implementierung einer mehrschichtigen Kategoriefunktion (Formular bearbeiten)

Recommended Posts

[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Erstellungsformular"
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Edit Form Edition"
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Vorbereitung"
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der "Seed Edition" der Vorfahren
[Rails] Implementierung der Kategoriefunktion
Implementierung der Funktionsfunktion [Rails] gem ancestry category
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Ich habe versucht, ein Fenster mit Bootstrap 3 zu erstellen"
[Rails] Implementierung der Suchfunktion mit Gem's Ransack
[Rails] Implementierung der Bildvergrößerungsfunktion mit Lightbox2
Implementierung eines Kategorieauswahlformulars mit JS bei der Erstellung von Frima-Apps
Implementierung der Kategorie-Pulldown-Funktion
[Rails] Implementierung der Tutorial-Funktion
[Rails] Implementierung einer ähnlichen Funktion
[Rails] Implementierung der CSV-Importfunktion
[Rails] Asynchrone Implementierung der Like-Funktion
[Rails] Implementierung der Bildvorschau
[Rails] Über die Implementierung der Like-Funktion
[Rails] Implementierung der Benutzerrückzugsfunktion
[Rails] Implementierung der CSV-Exportfunktion
[Rails] Implementierung von Viele-zu-Viele-Kategoriefunktionen
[Rails] Implementierung einer neuen Registrierungsfunktion im Assistentenformat mit devise
[Rails] Implementierung der Couponfunktion (mit automatischer Löschfunktion mittels Stapelverarbeitung)
[Rails] Implementierung der Tag-Funktion mit Acts-as-Taggable-On und der Funktion zur Vervollständigung der Tag-Eingabe mit Tag-It
Implementierung der Benutzerauthentifizierungsfunktion mit devise (2)
Implementierung der Benutzerauthentifizierungsfunktion mit devise (1)
Rails [Für Anfänger] Implementierung der Kommentarfunktion
Implementierung der Benutzerauthentifizierungsfunktion mit devise (3)
[Ruby on Rails] Implementierung einer ähnlichen Funktion
[Schienen] Kategoriefunktion
[Rails] Ich werde die Prozedur zum Implementieren der Follow-Funktion mit form_with erklären.
Implementieren Sie die Produktkategoriefunktion mit Abstammung ① (Vorbereitung)
Implementierung der Suchfunktion Lernnotiz (Portfolioerstellung)
[Rails] Implementierung des PV-Nummernrankings mit Impressionist
[Rails] Implementierung einer Bild-Diashow mit Bootstrap 3
Implementierung der Suchfunktion
Implementierung der Pagenationsfunktion
[Rails] Implementierung der Drag & Drop-Funktion (mit Wirkung)
Implementierung der Ruby on Rails-Anmeldefunktion (Devise Edition)
Implementierung der Ajax-Entfernung in Rails
Implementierung der Fuzzy-Suchfunktion für Schienen
[Rails] Implementierung der automatischen Adresseneingabe mit jpostal und jp_prefecture
Implementierung der sequentiellen Suchfunktion
Implementierung einer ähnlichen Funktion (Ajax)
Implementierung der Bildvorschau
Implementierung der Rails-Sortierfunktion (angezeigt in der Reihenfolge der Anzahl der Gleichen)
Implementieren Sie die Kategoriefunktion mithilfe von Vorfahren