How to append custom option values using jQuery?

Viewed 117

Can anyone help me with this? Note: Project is a dynamic Webflow website, so the entries get generated as described below, I can only change class names

Let's say I have multiple items I want to append to a select field

<div class="item-category">Kitchen</div>
<div class="actual-item">Spoon</div>
<div class="item-category">Living room</div>
<div class="actual-item">Sofa</div>
<div class="item-category">Kitchen</div>
<div class="actual-item">Plate</div>

I'm able to append items using actual-item class

$('.actual-item').each(function(){
var s=$(this).text();
$('.item-select-field').append('<option value="'+s+'">'+s+'</option>');
})

But I want to have option value equal to corresponding item-category (so I could filter items out later). Is there any way to do this? I've thought of changing the item-category class to actual-item and then using only even elements as option-value but I don't know to do this.

4 Answers

As your HTML will always be category followed by item, you can find the items then use .prev() to get the previous div which contains the category:

var category = $(this).prev().text()

As the requirement is "so I could filter items out later" - you don't want to set the value= to category otherwise you get multiple options with the same value, so you don't know which one was selected

<option value="Kitchen">Spoon</option>
<option value="Kitchen">Plate</option>

instead, you can add a data- attribute to the <option>

<option data-category="Kitchen">Spoon</option>
<option data-category="Kitchen">Plate</option>

then you can use this to filter the options later, eg:

$(".item-select-field :not([data-category='Kitchen'])").hide()

Giving:

$('.actual-item').each(function() {
  var val = $(this).text();
  var cat = $(this).prev().text();
  $('.item-select-field').append('<option value="' + val + '" data-category="' + cat + '">' + cat + ":" + val + '</option>');
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item-category">Kitchen</div>
<div class="actual-item">Spoon</div>
<div class="item-category">Living room</div>
<div class="actual-item">Sofa</div>
<div class="item-category">Kitchen</div>
<div class="actual-item">Plate</div>

<select class='item-select-field'>
</select>


You could equally get each category and use .next() to get the item for that category, which ever makes the most sense to you.

$('.item-category').each(function() {
  var cat = $(this).text();
  var val = $(this).next().text();
  $('.item-select-field').append('<option value="' + val + '" data-category="' + cat + '">' + cat + ":" + val + '</option>');
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item-category">Kitchen</div>
<div class="actual-item">Spoon</div>
<div class="item-category">Living room</div>
<div class="actual-item">Sofa</div>
<div class="item-category">Kitchen</div>
<div class="actual-item">Plate</div>

<select class='item-select-field'>
</select>

This answer is based off here.

Use this format: new Option("option text", "value");

$('.actual-item').each(function(){
    var s = $(this).text();
    var o = new Option(s, s);
    
    $(".item-select").append(o);
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item-category">Kitchen</div>
<div class="actual-item">Spoon</div>
<div class="item-category">Living room</div>
<div class="actual-item">Sofa</div>
<div class="item-category">Kitchen</div>
<div class="actual-item">Plate</div>

<select class="item-select">
</select> 

If I understand your question correctly I believe this is the effect you're trying to achieve.

I've gathered all of the items and their parent categories and used the optgroup element to group them inside of the select.

I've also modified your HTML slightly so the relationship between category and item is more obvious inside the markup.

$('.actual-item').each(function(){
  const option = $(this).text();
  const optgroup = $(this).parent().find('.category-title').text();
  
  if ($(`[label="${optgroup}"]`).length) {
    $(`[label="${optgroup}"]`).append(`<option value="${option}">${option}</option>`);
  } else {
    $('.item-select-field').append(`
      <optgroup label="${optgroup}">
        <option value="${option}">${option}</option>
      </optgroup
    `);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="item-category">
  <span class="category-title">Kitchen</span>
  <div class="actual-item">Spoon</div>
  <div class="actual-item">Knife</div>
  <div class="actual-item">Fork</div>
</div>

<div class="item-category">
  <span class="category-title">Living room</span>
  <div class="actual-item">Sofa</div>
</div>

<div class="item-category">
  <span class="category-title">Kitchen</span>
  <div class="actual-item">Plate</div>
</div>

<label for="item-select">Choose an item:</label>
<select id="item-select" class="item-select-field"></select>

hard way

const zip = (...arr) => {
   const zipped = [];
   arr.forEach((element, ind) => {
      element.forEach((el, index) => {
         if(!zipped[index]){
            zipped[index] = [];
         };
         if(!zipped[index][ind]){
            zipped[index][ind] = [];
         }
         zipped[index][ind] = el || '';
      })
   });
   return zipped;
};

const combined = zip($('.actual-item').toArray(), $('.item-category').toArray())

$(combined).each(function(){
  console.log({'value': $(this[0]).text(), 'category': $(this[1]).text()})
})
{value: "Spoon", category: "Kitchen"}
{value: "Sofa", category: "Living room"}
{value: "Plate", category: "Kitchen"}

PS thanks to this info

Related