I am a student of a certain programming school. Many of you may know this. When creating the "Flea Market Clone Site", we implemented the exhibition category with ajax, so I would like to organize it as well as organize my own mind.
In addition, the category setting uses a gem called "ancestry". For this article, it is assumed that the category has been set.
haml:View(items.new.html.haml)
.form-title
=f.label "category"
.form-title__required
%label required
.form-input-select
= f.select :category, @category_parent_array, {}, {class: 'listing-select-wrapper__box--select', id: 'parent_category'}
.listing-product-detail__category
――This time, only the bottom three lines are important. Others are free.
Controller (items_controller.rb)
def new
@category_parent_array = ["---"]
Category.where(ancestry: nil).each do |parent|
@category_parent_array << parent.name
end
end
def get_category_children
@category_children = Category.find_by(name: "#{params[:parent_name]}", ancestry: nil).children
end
def get_category_grandchildren
@category_grandchildren = Category.find("#{params[:child_id]}").children
end
If you look at the demo, you can see that the categories are displayed in three stages. ・ The first display is new ・ The second display is get_category_children ・ The third display is get_category_grandchildren It has become.
Is the complicated part the new code? You are assigning an array ** that contains only ** "---" to @category_parent_array. In the each statement on the next line, the categories are assigned to the ** array of @category_parent_array set earlier ** one by one. For (ancestry: nil), please check the saved data after setting the category with "ancestry". You can see the meaning.
** The description in the second and third paragraphs is processed by ajax **, so the actions are separated. For params [: parent_name] and params [: child_id], they are the values that fly from JavaScript with ajax. Remember, we'll set it up later.
routes.rb
resources :items do
collection do
get 'get_category_children', defaults: { format: 'json' }
get 'get_category_grandchildren', defaults: { format: 'json' }
end
end
I have set the ** two ajax actions ** that came out on the controller earlier. It is nested in items. To briefly explain the collection, the routing has ** id attached to member **, and the routing does not have ** id attached to collection **. This time, it's a collection ** because you don't have to specify the ** "individual (id)".
The controller basically ** returns the process to the view **, If you set defaults: {format:'json'}, ** returns processing to json file by default **. (You don't have to use respond_to on your controller to sort to a json file.)
ruby:get_category_children.json.jbuilder
json.array! @category_children do |child|
json.id child.id
json.name child.name
end
ruby:get_category_grandchildren.json.jbuilder
json.array! @category_grandchildren do |grandchild|
json.id grandchild.id
json.name grandchild.name
end
Don't get the file location wrong! !! Store in the same location as the view.
If you perform the action processing of the second and third paragraphs with the controller, you will jump to this json file. (You set it earlier in routes.rb.) You are converting the variables set in the controller to the data for ajax here.
By the way, ** json.array! ** is set when receiving array format data from the controller.
The flow of ajax processing is ** View (category selection)-> JavaScript (fire)-> Controller (processing)-> json.jbuilder (data conversion)-> JavaScript (processing)-> View ** Repeat (I recognize).
Well, finally, JavaScript is here.
JS(items.js)
$(function)(){
//Select box choices for child and grandchild categories
function appendOption(category){
//value="${category.name}"For, category depending on how to take the value in the strong parameter.I think it may be id.
var html = `<option value="${category.name}" datacategory="${category.id}">${category.name}</option>`;
return html;
}
//Create a view of a child category
function appendChildrenBox(insertHTML){
var childSelectHtml = '';
childSelectHtml = `<div class='listing-select-wrapper__added' id= 'children_wrapper'>
<div class='listing-select-wrapper__box'>
<select class="listing-select-wrapper__box--select" id="child_category" name="category_id">
<option value="---" data-category="---">---</option>
${insertHTML}
<select>
</div>
</div>`;
$('.listing-product-detail__category').append(childSelectHtml);
}
//Create a view of grandchild categories
function appendGrandchildrenBox(insertHTML){
var grandchildSelectHtml = '';
grandchildSelectHtml = `<div class='listing-select-wrapper__added' id= 'grandchildren_wrapper'>
<div class='listing-select-wrapper__box'>
<select class="listing-select-wrapper__box--select" id="grandchild_category" name="category_id">
<option value="---" data-category="---">---</option>
${insertHTML}
</select>
</div>
</div>`;
$('.listing-product-detail__category').append(grandchildSelectHtml);
}
//Processing when the parent category is selected (display of child categories)
$("#parent_category").on('change', function(){
//Get the value of the selected parent category
var parentCategory = document.getElementById('parent_category').value;
//The selected parent category is"---"False if left (default setting), true if changed
if (parentCategory != "---"){
$.ajax({
url: 'get_category_children',
type: 'GET',
//This is the value to be sent to the controller.
data: { parent_name: parentCategory },
dataType: 'json'
})
.done(function(children){
//First, delete the already displayed child and grandchild categories
$('#children_wrapper').remove();
$('#grandchildren_wrapper').remove();
//Insert the selection of the category select box into the variable called insertHTML. (Variables provided in the very first paragraph)
var insertHTML = '';
children.forEach(function(child){
insertHTML += appendOption(child);
});
//Invoking the view of the child category set in the second paragraph
appendChildrenBox(insertHTML);
})
.fail(function(){
alert('Failed to get the category');
})
}else{
$('#children_wrapper').remove();
$('#grandchildren_wrapper').remove();
}
});
//Processing when a child category is selected (display of grandchild category)
$('.listing-product-detail__category').on('change', '#child_category', function(){
var childId = $('#child_category option:selected').data('category');
if (childId != "---"){
$.ajax({
url: 'get_category_grandchildren',
type: 'GET',
data: { child_id: childId },
dataType: 'json'
})
.done(function(grandchildren){
if(grandchildren.length != 0) {
$('#grandchildren_wrapper').remove();
$('#size_wrapper').remove();
$('#brand_wrapper').remove();
var insertHTML = '';
grandchildren.forEach(function(grandchild){
insertHTML += appendOption(grandchild);
});
appendGrandchildrenBox(insertHTML);
}
})
.fail(function(){
alert('Failed to get the category');
})
}else{
$('#grandchildren_wrapper').remove();
$('#size_wrapper').remove();
$('#brand_wrapper').remove();
}
});
});
Yes. I understand what I mean. I'm Esper. I would like to send you the convenient words ** Do your best **.
This is too long, so ** comment out the code to explain the process **. If it's not easy to understand, I'd like you to check it out.
Thank you for reading the long and sloppy article to the end. LGTM is mandatory for camp students.
https://qiita.com/ATORA1992/items/bd824f5097caeee09678 @ ATORA1992 (It was a very easy-to-understand article. Thank you!)
Recommended Posts