I have this array of JSON and I want to loop through them and use it to fill up my option
element.
Sample Array:
var myOptionData = [
{fooValue:"1", fooText:"option A"},
{fooValue:"2", fooText:"option B"},
{fooValue:"3", fooText:"option C"}
]
I did use this method:
var fields="";
fields = "</select >";
fields = "<option value='0'></option>";
$.each(myOptionData , function (key, value) {
fields = "<option value=" value.fooValue ">" value.fooText "</option>";
});
fields = "</select >";
//But I want to make it more flexible, so that I can reuse it in making another <option>
from another array of JSON, like this scenario:
var myNewOptionData = [
{myValue:"5", myText:"option E"},
{myValue:"6", myText:"option F"},
{myValue:"7", myText:"option G"},
{myValue:"8", myText:"option H"}
]
//Now I cannot use the method above
CodePudding user response:
Simply turn the whole operation into a function:
function mkSelect(data){
return "<select><option value='0'></option>"
data.map(o=>{
let [val,txt]=Object.values(o);
return "<option value=" val ">" txt "</option>"}).join("")
"</select >";
}
const myOptionData = [
{fooValue:"1", fooText:"option A"},
{fooValue:"2", fooText:"option B"},
{fooValue:"3", fooText:"option C"}
],
myNewOptionData = [
{myValue:"5", myText:"option E"},
{myValue:"6", myText:"option F"},
{myValue:"7", myText:"option G"},
{myValue:"8", myText:"option H"}
];
document.querySelector("#frm").innerHTML=mkSelect(myOptionData) "<br>"
mkSelect(myNewOptionData);
<form id="frm"></form>
The function should be improved, as it momentarily relies on the sequence of the properties of object o
. Maybe the property names could be checked for containing "Value" and "Text"?
Here is a slight variation of my snippet, checking for parts of the property names. Now the order of the given option properties is immaterial and a selected option can also be defined by providing a property that contains "select" in its name:
function mkSelect(data){
const arr=data.map(o=>Object.fromEntries(Object.entries(o).map(([k,v])=>
[k.replace(/.*value.*/i,"val") // generate an object with standardised key names:
.replace(/.*text.*/i,"txt") // ===> val, txt and sel
.replace(/.*select.*/i,"sel"),
v])));
return "<select><option value='0'></option>" // build the actual select element:
arr.map(o=>`<option value="${o.val}"${o.sel?` selected="${o.sel}"`:""}>${o.txt}</option>`).join("") "</select>"
}
const myOptionData = [
{fooValue:"1", fooText:"option A"},
{fooValue:"2", fooText:"option B", thisIsSelected: true},
{fooValue:"3", fooText:"option C"},
{thisTextIsGreatToo:"option D", andValueThis:"4"}
],
myNewOptionData = [
{myValue:"5", myText:"option E"},
{myValue:"6", myText:"option F"},
{myValue:"7", myText:"option G"},
{selectThis: 1, myLastText:"option H", myLastValue:"8"}
];
document.querySelector("#frm").innerHTML=mkSelect(myOptionData) "<br>" mkSelect(myNewOptionData)
<form id="frm"></form>
CodePudding user response:
If you use jQuery hability to create elements, you can also use the methods to set the value (.val()
) and text (.text()
). That is nicer than string concatenations that are error prone.
Then having a single function to reuse the $.each()
using the Object.keys()
of the data like this.
var myOptionData = [
{ fooValue: "1", fooText: "option A" },
{ fooValue: "2", fooText: "option B" },
{ fooValue: "3", fooText: "option C" }
];
var myNewOptionData = [
{ myValue: "5", myText: "option E" },
{ myValue: "6", myText: "option F" },
{ myValue: "7", myText: "option G" },
{ myValue: "8", myText: "option H" }
];
function fillOptions(data, target){
$.each(data, function(index,item){
const itemKeys = Object.keys(item)
const $option = $("<option>").val(item[itemKeys[0]]).text(item[itemKeys[1]])
target.append($option)
})
}
// First create a select element
const $selectElement = $("<select>")
// Then use the function to fill it with options
fillOptions(myOptionData, $selectElement)
fillOptions(myNewOptionData, $selectElement)
// And finally append it somewhere...
$("#result").append($selectElement)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="result"></div>
CodePudding user response:
Generally when making a function you should expect to receive parameters with defined keys. There's nothing wrong with requiring objects within lists to have fooValue & fooText. However if you want to make it property-independent:
function createSelect(options, valueName, textName) {
const select = `<select><option value='0'></option>
${options.map(option => `<option value="${option[valueName]}">${option[textName]}</option>`)}
</select>`;
return select;
}
console.log(
createSelect([{randomValue: 1, randomName: 'Go select!'}], 'randomValue', 'randomName')
);
Note how jQuery isn't necessary in this case. Map is a function that transforms every item on your list (without modifying it)
Also if you want to 'just specify the keys once and then reuse' you can create partially applied functions:
const createSelect = (valueName, textName) => (options)=> {
return `<select><option value='0'></option>
${options.map(option => `<option value="${option[valueName]}">${option[textName]}</option>`)}
</select>`;
}
const fooList = [{fooValue: 1, fooName: 'Foo select!'}];
const fooSelect = createSelect('fooValue', 'fooName');
console.log(
fooSelect(fooList)
);
const barList = [{barValue: 2, barName: 'Bar select!'}];
const barSelect = createSelect('barValue', 'barName');
console.log(
barSelect(barList)
);