Creating and Consuming Custom Events
Tags: javascript, tutorial, beginners, codenewbie
Published: 2022-08-10 22:10:20

This week, I've learned something new about the DOM API, and that is how to create and consume custom events. Imagine, instead of listening for a click event, you create your own event to listen for! Sounds cool, right? Allow me to show you more about this neat feature that I didn't even know about, as long as I've been using event listeners.
I've built a project to illustrate one possible use of using custom events. For instance, I want to listen for an order in a kitchen system so the cooks know what's coming up next, then I want to print that order to the screen. I've simulated this in a project on [github](https://github.com/AubreyHBarnes/custom-events-example).

```js
// fetch data from api using netlify functions
const fetchData = async () => {
    //get the data from my super secret netlify function
    const res = await fetch(`/.netlify/functions/token-hider`)
    //if something goes wrong, throw an error
    if (!res.ok) {
        throw new Error(`http response: ${res.status}`)
    }
    // if something goes right, save the json response
    const getMeals = await res.json();
    // pass the fetched data to a new function to process
    processOrder(getMeals)

}
```
We begin our journey with a standard data fetch, I'm using netlify cli to hide my API key, which I bought for $2 a month, but for those of you who do not care to purchase one, the free api can be found [here](https://www.themealdb.com/api.php). The major work behind this program is done after passing the fetched data into a function for processing the data into our own free-range, organic, ethically sourced events.

```js
// This function is called to get a random selection of meals from the array passed in from fetch
const processOrder = (getMeals) => {
    //save an array of randomly selected meals
    const mealsData = getMeals.meals
    // select a random number of meals starting from the beginning of the mealsData array
    // at least one, up to the length of the array given.
    const customerOrder = mealsData.slice(0, Math.floor(Math.random() * mealsData.length) + 1)
// map an array of objects
    const orderDetails = customerOrder.map(item => (
        {
            mealName: item.strMeal,
            mealImg: item.strMealThumb
        }
    ))

// create and initialize event. 

    var orderEvent = new CustomEvent(
        'order',
        { detail: orderDetails }
    );
    // tell the browser api to fire the event
    window.dispatchEvent(orderEvent)
}

const stopMe = setInterval(fetchData, 2000);
```
First, take a random number of entries from the data array, and map an array of objects, saving the meal name and image. For our next trick we create and initialize a custom event, using the syntax 

```js
var orderEvent = new CustomEvent('whatever name you want to call the event', { detail: data-you-want-to-pass }
```
Afterwards, we fire the event using window.dispatchEvent(variable-you-saved-custom-event-to).

My initial thought for this project was to have a random interval of time to fire the event, but I have not yet figured out how to insert a random time interval into the setInterval function, so for now I set it to two seconds. Every two seconds, I'm calling the fetchData function, which calls the processOrder function, which fires the order event. You consume the order event like any other built in event from the browsers' API. The order event was dispatched to the window interface, so we add an event listener to the window interface, and then a callback function to process the data using event.detail (remember setting what we get from detail when initializing the custom event).

```js
window.addEventListener('order', (evt) => {
    let root = document.getElementById('root');
    const section = document.createElement('section');
    let orderNumber = document.createElement('p')

    section.className = 'order-container'
    orderNumber.className = 'order-number'
    orderNumber.innerText = `Order ${Math.floor(Math.random() * 1000)}`
    section.append(orderNumber)

    const displayOrder = evt.detail.map(item => {
        const p = document.createElement('p')
        const img = document.createElement('img')
        const div = document.createElement('div')
        div.className = 'item-in-order'
        img.src = `${item.mealImg}/preview`
        img.alt = item.mealName
        p.innerText = item.mealName
        div.append(p)
        div.append(img)

        return div

    })

    displayOrder.forEach(item => {
        section.append(item)
    })
    root.append(section)
})
```

Slap that data into the DOM and you get something like this

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o24i8tinfsbt6x3d8epf.jpg)

That's all there is to it! I wanted to share this knowledge since I did not know this during an online assessment with essentially a dream company, and wanted to fill in that gap. The best way to learn something is to explain it to someone else, and I hope my explanation was simple and easy to follow, if not, please let me know how I can improve!