DEV Community

Andrew Elans
Andrew Elans

Posted on • Edited on

Array.reduce() to fill <select>

I have a list of colors sitting in my database and a <select> HTML element where I want to use these colors as <option>s.

Colors

I get the values from the database and store them in a variable.

const colors = [
    {val: "1", name: "Black"},
    {val: "2", name: "Red"},
    {val: "3", name: "Yellow"},
    {val: "4", name: "Green"},
    {val: "5", name: "Blue"},
    {val: "6", name: "White"}
]
Enter fullscreen mode Exit fullscreen mode

Generate options with Array.reduce()

With return in the reducer callback

const colorOptions = colors.reduce(
    (options, color) => {
        options.push(`<option value="${color.val}">${color.name}</option>`)
        return options
    }, []
)
Enter fullscreen mode Exit fullscreen mode

Without the return word in the reducer callback

We use Grouping ( ) and Comma (,) operators for one-liner implementation.
Identation is added for better human readability.

const colorOptions = colors.reduce(
    (options, color) => (
        options.push(`<option value="${color.val}">${color.name}</option>`),
        options
    ), []
)
Enter fullscreen mode Exit fullscreen mode

Resulting colorOptions

[
    '<option value="1">Black</option>', 
    '<option value="2">Red</option>', 
    '<option value="3">Yellow</option>', 
    '<option value="4">Green</option>', 
    '<option value="5">Blue</option>', 
    '<option value="6">White</option>'
]
Enter fullscreen mode Exit fullscreen mode

Sort before reducing

You can also sort on val or name before Array.reduce().

const colors = [
    {val: "1", name: "Black"},
    {val: "2", name: "Red"},
    {val: "3", name: "Yellow"},
    {val: "4", name: "Green"},
    {val: "5", name: "Blue"},
    {val: "6", name: "White"}
].sort(
    (a, b) => a.name.localeCompare(b.name)
)

// colors => [
//     '<option value="1">Black</option>', 
//     '<option value="5">Blue</option>', 
//     '<option value="4">Green</option>', 
//     '<option value="2">Red</option>', 
//     '<option value="6">White</option>', 
//     '<option value="3">Yellow</option>'
// ]
Enter fullscreen mode Exit fullscreen mode

Use DocumentFragment to fill in <select>

We have a <select> on a page which is currently empty.

<select id="colors-select"></select>
Enter fullscreen mode Exit fullscreen mode

We can use the DocumentFragment interface to load <select> with options as nodes.

Create DocumentFragment

const fragment = document.createRange().createContextualFragment(
    colorOptions.join('')  // convert colors array to string
)
Enter fullscreen mode Exit fullscreen mode

Fill in <select>

document.getElementById('colors-select').appendChild(fragment)
Enter fullscreen mode Exit fullscreen mode

Result

<select id="colors-select">
    <option value="1">Black</option>
    <option value="5">Blue</option>
    <option value="4">Green</option>
    <option value="2">Red</option>
    <option value="6">White</option>
    <option value="3">Yellow</option>
</select>
Enter fullscreen mode Exit fullscreen mode

Full code snippet

const colors = [
    {val: "1", name: "Black"},
    {val: "2", name: "Red"},
    {val: "3", name: "Yellow"},
    {val: "4", name: "Green"},
    {val: "5", name: "Blue"},
    {val: "6", name: "White"}
].sort(
    (a, b) => a.name.localeCompare(b.name)
)

const colorOptions = colors.reduce(
    (options, color) => (
        options.push(`<option value="${color.val}">${color.name}</option>`),
        options
    ), []
).join('')

const fragment = document.createRange().createContextualFragment(colorOptions)

document.getElementById('colors-select').appendChild(fragment)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)