Array.reduce() to fill <select>
Tags: javascript, array, reduce
Published: 2024-04-26 18:32:48

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.
```javascript
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"}
]
```

## Generate options with Array.reduce()

### With `return` in the reducer callback
```javascript
const colorOptions = colors.reduce(
    (options, color) => {
        options.push(`<option value="${color.val}">${color.name}</option>`)
        return options
    }, []
)
```

### Without the `return` word in the reducer callback
We use [Grouping ( )](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Grouping) and [Comma (,)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_operator) operators for one-liner implementation. 
Identation is added for better human readability. 
```javascript
const colorOptions = colors.reduce(
    (options, color) => (
        options.push(`<option value="${color.val}">${color.name}</option>`),
        options
    ), []
)
```
### Resulting `colorOptions`
```javascript
[
    '<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>'
]
```

## Sort before reducing
You can also sort on `val` or `name` before `Array.reduce()`.

```javascript
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>'
// ]
```

## Use DocumentFragment to fill in `<select>`

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

```html
<select id="colors-select"></select>
```
We can use the [DocumentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) interface to load `<select>` with options as nodes.

### Create DocumentFragment

```javascript
const fragment = document.createRange().createContextualFragment(
    colorOptions.join('')  // convert colors array to string
)
```
### Fill in `<select>`

```javascript
document.getElementById('colors-select').appendChild(fragment)
```

### Result

```html
<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>
```

## Full code snippet
```javascript
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)
```