0

I have dynamically created dropdowns and populating them with data from a json array.

Data:

data = [{hello: 'abc', asd: '123', fgh: '345' }, 
{hello: 'sdf', asd: '456', fgh: 'df' }, 
{hello: 'ty', asd: '789', fgh: '345675' },
{hello: 'qwe', asd: '123', fgh: '987' }]

array of keys (for the data I need in the dropdown): arr = ['asd', 'fgh']

Creation of dropdown:

arr.forEach(c => {
   $('div').append(`
     <div class='float-left'>
     <p>${c}</p>
     <select id='${c}'></select>
    </div>`);
});

To populate the dropdowns:

arr.forEach(o => {
   data.forEach(strs => {
      if (strs[o] != null) {
         $(`#${o}`).append(`<option value='${strs[o]}'>${strs[o]}</option>`);
      }
   });
});

I am able to populate the dropdowns. How do I populate the dropdowns with NO DUPLICATES?

nb_nb_nb
  • 1,243
  • 11
  • 36

3 Answers3

1

You can create an array of each of the values of the object indexes specified by arr and de-duplicate that before using it to add options. Note I've combined your two forEach loops; doing so requires adding an id to the top-level div. If you don't want to do that you will need to split them apart again.

data = [{hello: 'abc', asd: '123', fgh: '345' }, 
{hello: 'sdf', asd: '456', fgh: 'df' }, 
{hello: 'ty', asd: '789', fgh: '345675' },
{hello: 'qwe', asd: '123', fgh: '987' }]

arr = ['asd', 'fgh']

arr.forEach(o => {
  $('div#top').append(`
     <div class='float-left'>
     <p>${o}</p>
     <select id='${o}'></select>
    </div>`);
  let vals = data.map(strs => strs[o]);
  vals.filter((v, i) => v !== null && vals.indexOf(v) === i)
      .forEach(v => $(`#${o}`).append(`<option value='${v}'>${v}</option>`));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='top'></div>
Nick
  • 138,499
  • 22
  • 57
  • 95
1

To handle the duplicate <select> elements you need to not append to the generic 'div' selector. Instead I use a named class .container.

To handle duplicate <option>s I would use the array method .some()

data = [{hello: 'abc', asd: '123', fgh: '345' }, 
{hello: 'sdf', asd: '456', fgh: 'df' }, 
{hello: 'ty', asd: '789', fgh: '345675' },
{hello: 'qwe', asd: '123', fgh: '987' }]

arr = ['asd', 'fgh']

arr.forEach(c => {
   $('.container').append(`
     <div class='float-left'>
     <p>${c}</p>
     <select id='${c}'></select>
    </div>`);
});

arr.forEach(o => {
   data.forEach(strs => {
      if (strs[o] != null) {
      
      const alreadyHasThis = $(`#${o} option`).toArray().some(option => option.value === strs[o]);
                  
      if(!alreadyHasThis){
          $(`#${o}`).append(`<option value='${strs[o]}'>${strs[o]}</option>`);
      }
     
      }
   });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container"></div>
WillD
  • 5,170
  • 6
  • 27
  • 56
1

You can first use a temporary array with your selected data, and use [... new Set(data)] to remove duplicates. Then use this array to build your control.

data = [{hello: 'abc', asd: '123', fgh: '345' }, 
{hello: 'sdf', asd: '456', fgh: 'df' }, 
{hello: 'ty', asd: '789', fgh: '345675' },
{hello: 'qwe', asd: '123', fgh: '987' }]

arr = ['asd', 'fgh']

var selects = arr.reduce((r, e) => (r[e] = [... new Set(data.map(d => d[e]))], r), {});

console.log(selects)

var html = ""
for (sel of arr) {
  html += `<div class='float-left'>${sel} <select id='${sel}'>`;
  for (data of selects[sel]) 
    html += `<option value='${data}'>${data}</option>`;
  html += `</select></div>`;
}
document.querySelector("div").insertAdjacentHTML("beforeend", html);
<div></div>

References: How do I convert array of Objects into one Object in JavaScript? https://medium.com/dailyjs/how-to-remove-array-duplicates-in-es6-5daa8789641c

ariel
  • 15,620
  • 12
  • 61
  • 73