List of array contents grouped by key

I apologize if my terminology is incorrect - this is definitely not my area of ​​expertise.

I want to make a <select> list from a json file and group the entries in <optgroup> using the key. I was able to successfully list all the entries in the select element, but I don’t know how to loop and nest the elements under their key.

My JSON looks like this:

 [ { "Type" : "Overdrive", "Brand" : "Chase Bliss", "Name" : "Brothers", "Width" : 2.75, "Height" : 4.77, "Image" : "public/images/pedals/chasebliss-brothers.png" } ] 

This is how I show <select> :

 window.RenderPedals = function(pedals){ for(var i in pedals) { var $pedal = $("<option>"+ pedals[i].Brand + " " + pedals[i].Name +"</option>").attr('id', pedals[i].Name.toLowerCase().replace(/\s+/g, "-").replace(/'/g, '')); $pedal.data('width', pedals[i].Width); $pedal.data('height', pedals[i].Height); $pedal.data('height', pedals[i].Height); $pedal.data('image', pedals[i].Image); $pedal.appendTo('.pedal-list'); } } 

I am looking for this markup:

 <select> <optgroup label="Chase Bliss"> <option data-width="..." data-height="..." data-image="...">Chase Bliss Brothers</option> </optgroup> </select> 

Can someone point me in the right direction?

+7
javascript arrays
source share
2 answers

You can get the properties of the current object by destructuring the object, without a for..in loop, create an <optgroup> element with the label attribute set to "Brand" , add <option> to <optgroup> , add <optgroup> to <select> . Check if the <optgroup> element <optgroup> with the label attribute set to Brand ; if true , add <option> to this <optgroup> , add a new <optgroup> element in <select> using html set the new <option> element for html .

 var data = [{ "Type": "Overdrive", "Brand": "Chase Bliss", "Name": "Brothers", "Width": 2.75, "Height": 4.77, "Image": "public/images/pedals/chasebliss-brothers.png" } , { "Type": "Underdrive", "Brand": "Bliss Chase", "Name": "Sisters", "Width": 5.72, "Height": 7.74, "Image": "public/images/pedals/chasebliss-sisters.png" } , { "Type": "Throughdrive", "Brand": "Bliss Chase", "Name": "Cousins", "Width": 2.75, "Height": 4.74, "Image": "public/images/pedals/chasebliss-cousins.png" } ]; window.RenderPedals = function(pedals) { var {Type, Brand, Name, Width, Height, Image} = pedals; var option = $("<option>", { text: `${Brand} ${Name}`, id: Name.toLowerCase() .replace(/(\s+)|(['"])/g, (m, p1, p2) => p1 ? "-" : ""), data: { width: Width, height: Height, image: Image } }); if ($("optgroup").is(`[label="${Brand}"]`)) { $(`optgroup[label="${Brand}"]`).append(option); } else { $("<optgroup>", { label: Brand, html: option }).appendTo(".pedal-list"); } } data.forEach(RenderPedals); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"> </script> <select class="pedal-list"></select> 
0
source share

If you had a data structure that corresponded to HTML, it would be much easier to reason.

given

 [ { "Type" : "Overdrive", "Brand" : "Chase Bliss", "Name" : "Brothers", "Width" : 2.75, "Height" : 4.77, "Image" : "public/images/pedals/chasebliss-brothers.png" } ] 

while you need structure

 <select> <optgroup label="Chase Bliss"> <option data-width="..." data-height="..." data-image="...">Chase Bliss Brothers</option> </optgroup> </select> 

Instead of trying to do this conversion from JSON to HTML, create a new data structure that matches the HTML. If the data structure matches the HTML structure, the logic of its visualization will be much simpler.

Something like the following will work well.

 [ { brandName: "Chase Bliss", items: [ { name: "Brothers" /* width, height, etc */ } ] } ] 

You can write a reduction function to do this conversion:

 let optionGroups = pedals.reduce((optionGroups, pedal) => { let optionGroup = optionGroups.find(group => pedal.Brand === group.brandName) || {} if (!optionGroup.brandName) { optionGroup.brandName = pedal.Brand optionGroup.items = [] optionGroups.push(optionGroup) } optionGroup.items.push(pedal) return optionGroups }, []) 

the rendering function can then simply display the external elements and then the internal elements.

 window.renderPedals = (optionGroups) => { optionGroups.map((group) => { let $optgroup = $("<optgroup>", { label: group.brandName }); group.items.map((pedal) => { let {Type, Brand, Name, Width, Height, Image} = pedal; let $pedal = $("<option>", { text: `${Brand} ${Name}`, id: `${Name.toLowerCase().replace(/\s+/g, "-").replace(/'/g, '')}`, data: { width: Width, height: Height, image: Image }, appendTo: $optgroup }); }) $optgroup.appendTo(".pedal-list"); }) } 

https://jsfiddle.net/f4x9vk0f/2/

0
source share

All Articles