Home > Software design >  Clean way to populate select elements from tabular json data
Clean way to populate select elements from tabular json data

Time:03-22

I have some data in an array of objects, and want to populate select elements with one select element for each field containing all the possible keys for that field. There is one unique key. The best way I could implement was to loop over the array and append each value to its a Set, then loop over each set to create a new option element. This leads to a lot of repititive code with no easy way to add more fields. Any suggestions for better solutions? jQuery will also do if no alternative is present in vanilla.

https://codepen.io/nokeldin/pen/oNpzxmL

var nameSet = new Set();
var eyeSet = new Set();
var stateSet = new Set();
var fruitSet = new Set();

data.forEach(function (e, i, arr) {
    nameSet.add(e.name);
    eyeSet.add(e.eyeColor);
    stateSet.add(e.state);
    fruitSet.add(e.fruit);
});

nameSet.forEach(function (e) {
    var nameEntry = document.createElement("option");
    nameEntry.text = e;
    document.getElementById('names').add(nameEntry);
});
stateSet.forEach(function (e) {
    var stateEntry = document.createElement("option");
    stateEntry.text = e;
    document.getElementById('state-select').add(stateEntry);
});
fruitSet.forEach(function (e) {
    var fruitEntry = document.createElement("option");
    fruitEntry.text = e;
    document.getElementById('fruit-select').add(fruitEntry);
});
eyeSet.forEach(function (e) {
    var eyeEntry = document.createElement("option");
    eyeEntry.text = e;
    document.getElementById('eye-select').add(eyeEntry);
});

CodePudding user response:

I'd go for a more functional approach, using reduce and map methods. The only thing that you have to keep an eye on is when naming the ids of the HTML. They have to match the fields in your JavaScript.

First, it's created an array of keys based on your data's. Then, this array is reduced to construct an object made of Sets whereas within each Set the data is mapped to form an array made of specific keys only. Finally, it's grabbed each entry (Set) of that pre-made object and added each value of it to the corresponding select.

const data = [{eyeColor:"brown",name:"Cindy",state:"texas",fruit:"banana"},{eyeColor:"brown",name:"Carmen",state:"nebraska",fruit:"mango"},{eyeColor:"green",name:"Belinda",state:"alaska",fruit:"banana"},{eyeColor:"brown",name:"Lacy",state:"alaska",fruit:"mango"},{eyeColor:"blue",name:"Mcfarland",state:"nebraska",fruit:"banana"},{eyeColor:"blue",name:"Baird",state:"texas",fruit:"apple"},{eyeColor:"green",name:"Kara",state:"nebraska",fruit:"banana"},{eyeColor:"blue",name:"Hebert",state:"nebraska",fruit:"apple"},{eyeColor:"brown",name:"Opal",state:"nebraska",fruit:"banana"},{eyeColor:"green",name:"Gayle",state:"texas",fruit:"mango"},{eyeColor:"green",name:"Bernadine",state:"nebraska",fruit:"mango"},{eyeColor:"green",name:"Payne",state:"alaska",fruit:"banana"}];
const keys = ["eyeColor", "name", "state", "fruit"];

const obj = keys.reduce((acc, key) => {
  acc[key] = new Set(data.map(info => info[key])); 
  return acc;
 }, {})

Object.entries(obj).forEach(([key,set]) => {
  set.forEach(value => {
    const option = document.createElement("option");
    option.text = value;
    document.getElementById(`${key}-select`).add(option);
  })
})
<select id="state-select" >Cat1</select>
<select id="eyeColor-select" >Cat2</select>
<select id="fruit-select" >Cat3</select>
<select id="name-select" size=5></select>

CodePudding user response:

That was an intersting problem, therefore i made a cleaner solution. I used filter and map functions. It would be better to use the HTML select id's same as in the data named, so a dictionary should be laid aside.

const data = [{ eyeColor: "blue", name: "Katrina", state: "nebraska", fruit: "mango" },{ eyeColor: "green", name: "Meyer", state: "nebraska", fruit: "mango" }, { eyeColor: "brown", name: "Roman", state: "nebraska", fruit: "apple" }, { eyeColor: "green", name: "Forbes", state: "nebraska", fruit: "banana" }, { eyeColor: "green", name: "Melinda", state: "alaska", fruit: "banana" }, { eyeColor: "green", name: "Lucille", state: "alaska", fruit: "mango" }, { eyeColor: "brown", name: "Leanne", state: "nebraska", fruit: "apple" }, { eyeColor: "green", name: "Annabelle", state: "nebraska", fruit: "banana" }, { eyeColor: "blue", name: "Cote", state: "alaska", fruit: "banana" }, { eyeColor: "brown", name: "Boyd", state: "alaska", fruit: "mango" }, { eyeColor: "brown", name: "Witt", state: "texas", fruit: "apple" }, { eyeColor: "green", name: "Salinas", state: "texas", fruit: "mango" }, { eyeColor: "green", name: "Traci", state: "alaska", fruit: "apple" }, { eyeColor: "green", name: "Brandie", state: "alaska", fruit: "mango" }, { eyeColor: "blue", name: "Della", state: "alaska", fruit: "apple" }, { eyeColor: "green", name: "Conrad", state: "texas", fruit: "apple" }, { eyeColor: "blue", name: "Norris", state: "nebraska", fruit: "banana" }, { eyeColor: "green", name: "Reynolds", state: "nebraska", fruit: "mango" }, { eyeColor: "green", name: "Jackie", state: "texas", fruit: "mango" }, { eyeColor: "brown", name: "Adele", state: "texas", fruit: "apple" }, { eyeColor: "blue", name: "Flowers", state: "nebraska", fruit: "mango" }, { eyeColor: "brown", name: "Stanley", state: "nebraska", fruit: "apple" }, { eyeColor: "green", name: "Mccarty", state: "texas", fruit: "apple" }, { eyeColor: "blue", name: "Lopez", state: "nebraska", fruit: "banana" }, { eyeColor: "brown", name: "Pierce", state: "texas", fruit: "apple" }, { eyeColor: "green", name: "Roy", state: "texas", fruit: "banana" }, { eyeColor: "green", name: "Francis", state: "alaska", fruit: "banana" }, { eyeColor: "brown", name: "Buck", state: "alaska", fruit: "banana" }, { eyeColor: "green", name: "Dale", state: "alaska", fruit: "apple" }, { eyeColor: "brown", name: "Keith", state: "nebraska", fruit: "mango" }, { eyeColor: "green", name: "Gwen", state: "texas", fruit: "mango" }, { eyeColor: "blue", name: "Lisa", state: "nebraska", fruit: "mango" }, { eyeColor: "brown", name: "Burt", state: "alaska", fruit: "banana" }, { eyeColor: "brown", name: "Taylor", state: "texas", fruit: "apple" }, { eyeColor: "green", name: "Juliet", state: "nebraska", fruit: "mango" }, { eyeColor: "brown", name: "Trudy", state: "alaska", fruit: "apple" }, { eyeColor: "green", name: "Carney", state: "alaska", fruit: "banana" }, { eyeColor: "brown", name: "Lillie", state: "alaska", fruit: "apple" }, { eyeColor: "brown", name: "Herring", state: "texas", fruit: "banana" }, { eyeColor: "brown", name: "Ginger", state: "alaska", fruit: "mango" }, { eyeColor: "brown", name: "Mcdonald", state: "nebraska", fruit: "mango" }, { eyeColor: "blue", name: "Evangelina", state: "texas", fruit: "apple" }, { eyeColor: "green", name: "Willis", state: "alaska", fruit: "mango" }, { eyeColor: "brown", name: "Tammy", state: "alaska", fruit: "banana" }, { eyeColor: "brown", name: "Cindy", state: "texas", fruit: "banana" }, { eyeColor: "brown", name: "Carmen", state: "nebraska", fruit: "mango" }, { eyeColor: "green", name: "Belinda", state: "alaska", fruit: "banana" }, { eyeColor: "brown", name: "Lacy", state: "alaska", fruit: "mango" }, { eyeColor: "blue", name: "Mcfarland", state: "nebraska", fruit: "banana" }, { eyeColor: "blue", name: "Baird", state: "texas", fruit: "apple" }, { eyeColor: "green", name: "Kara", state: "nebraska", fruit: "banana" }, { eyeColor: "blue", name: "Hebert", state: "nebraska", fruit: "apple" }, { eyeColor: "brown", name: "Opal", state: "nebraska", fruit: "banana" }, { eyeColor: "green", name: "Gayle", state: "texas", fruit: "mango" }, { eyeColor: "green", name: "Bernadine", state: "nebraska", fruit: "mango" }, { eyeColor: "green", name: "Payne", state: "alaska", fruit: "banana" },];

const selects = [
  { dataName: "eyeColor", id: "eye-select" },
  { dataName: "state", id: "state-select" },
  { dataName: "fruit", id: "fruit-select" },
  { dataName: "name", id: "names" },
];

function init() {
  selects.forEach((select) => {
    select["element"] = document.getElementById(select.id);
    select["options"] = new Set(data.map((record) => record[select.dataName]));
  });
  console.table(selects);

  selects
    .filter((select) => select.id === "names")[0]
    .element.addEventListener("change", (event) => {
      const selectedData = data.filter((d) => d.name === event.target.value)[0];
      console.table(selectedData);

      for (let d in selectedData) {
        selects.filter((s) => s.dataName === d)[0].element.value =
          selectedData[d];
      }
    });
}

function render() {
  selects.forEach((select) => {
    select.options.forEach((option) => {
      const optionElement = document.createElement("option");
      optionElement.value = option;
      optionElement.innerText = option;
      select.element.appendChild(optionElement);
    });
  });
}

function clearOptions() {
  selects.forEach((select) => {
    Array.from(select.element.children).forEach((child) => child.remove());
  });
}

init();
render();
<select id="state-select" >Cat1</select>
<select id="eye-select" >Cat2</select>
<select id="fruit-select" >Cat3</select>
<select id="names" size=5></select>

  • Related