liveBook · Manning

Custom event

As explained in Secrets of the JavaScript Ninja, Second Edition

A programmer-defined event that represents an application-specific occurrence and can be triggered and handled like a built-in event.

Suppose shared code detects that an operation has started, but several parts of a page might need to react. Calling a global function forces the shared code and every page to agree on that function. A custom event offers a looser arrangement: announce what happened, then let interested code register its own handlers. section 13.3.2

The browser’s event-handling pattern works for application-specific occurrences too:

  • Create a CustomEvent with a name such as 'ajax-start'. Put optional information in its detail property. section 13.3.2
  • Call dispatchEvent on the chosen target. Other code registers handlers for that name with addEventListener. section 13.3.2
  • Keep the triggering code independent of its listeners: it need not know whether there are any, or what each one does. section 13.3.2

A loading indicator without a direct UI call

An operation dispatches 'ajax-start' on document with a URL in detail, then dispatches 'ajax-complete' after a timer. Separate listeners show and hide an indicator. The timer stands in for an operation; it is not an AJAX request. section 13.3.2

Listing 13.10. Using custom events
<style>
  #whirlyThing { display: none; }
</style>
<button type="button" id="clickMe">Start</button>                   #A
<img id="whirlyThing" src="whirly-thing.gif" />                     #B

<script>
  function triggerEvent(target, eventType, eventDetail){
    const event = new CustomEvent(eventType, {                      #C
      detail: eventDetail                                           #D
    });
    target.dispatchEvent(event);                                    #E
  }
  
  function performAjaxOperation() {                                 #F
    triggerEvent(document, 'ajax-start', { url: 'my-url'});         #F
    setTimeout(() => {                                              #F
      triggerEvent(document, 'ajax-complete');                      #F
    },5000);
  }

  const button = document.getElementById('clickMe'); 
  button.addEventListener('click', () => {  
    performAjaxOperation();                                                 #G
  });
    
  document.addEventListener('ajax-start', e => {                            #H
    document.getElementById('whirlyThing').style.display = 'inline-block';
    assert(e.detail.url === 'my-url', 'We can pass in event data');         #I
  });
  
  document.addEventListener('ajax-complete', e => {                         #J
      document.getElementById('whirlyThing').style.display = 'none';  
  });
</script>

The helper constructs a CustomEvent, supplies optional detail, and dispatches it on a target. section 13.3.2

button.addEventListener('click', () => {
  performAjaxOperation();
});

document.addEventListener('ajax-start', e => {
  document.getElementById('whirlyThing').style.display = 'inline-block';
  assert(e.detail.url === 'my-url', 'We can pass in event data');
});

document.addEventListener('ajax-complete', e => {
    document.getElementById('whirlyThing').style.display = 'none';
});

The listeners react independently; the start handler reads the URL through the event’s detail property. section 13.3.2

A compatibility caution: an application-defined CustomEvent is not the same thing as a browser-provided, browser-specific event. Being able to bind a listener does not prove that a browser will fire such an event. section 14.3.3

How Secrets of the JavaScript Ninja, Second Edition covers it

How deep it goes
Works through creating, dispatching, and handling a CustomEvent with optional detail, using an operation-status example.
Examples
Uses 'ajax-start' and 'ajax-complete' notifications to show and hide a loading indicator, with a timer standing in for an operation.
What it assumes
Assumes familiarity with JavaScript functions and DOM event listeners, then introduces the custom-event pattern through a worked example.
What you can do after
Build it from scratch with CustomEvent, dispatchEvent, and addEventListener to notify independent parts of a page.
How it connects
Connects custom events to DOM event handlers, addEventListener, event targets, and loose coupling.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Secrets of the JavaScript Ninja, Second Edition. The section links point to the parts of the book it draws on.