Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 12

Handling User Events

Recommended resources

Hello! Welcome back to our journey into building dynamic web applications.

In our last few lessons, you've mastered the art of "static" DOM manipulation: selecting, creating, modifying, and removing elements on a page. But a web application needs to be interactive; it must respond to the user. This lesson is the bridge that connects user actions to your DOM manipulation code.

Today, we will focus on this learning outcome: Handle user events such as clicks, input changes, and form submissions. You'll learn how to "listen" for things the user doesβ€”like clicking a button or typing in a formβ€”and execute JavaScript code in response. This is the key to making your web pages feel alive and responsive.

1. The Core of Interactivity: addEventListener

The primary way to handle user interaction in modern JavaScript is with the addEventListener() method. You can call this method on any DOM element you've selected.

The basic structure is:
element.addEventListener('eventName', callbackFunction);

It takes two essential arguments:

  1. eventName: A string that specifies the event you're listening for, such as 'click', 'mouseover', or 'submit'.
  2. callbackFunction: The function that will be executed when the event occurs. This function is "called back" by the browser at the right time.

Let's watch a video that demonstrates how to set this up.

Event Listeners in JavaScript | JavaScript Events Tutorial

The video 'Event Listeners in JavaScript' by Dave Gray provides a clear introduction to adding event listeners. Pay close attention to the syntax and the two ways he defines the callback function.

Watch from 03:22 to 08:34. Focus on: The basic syntax: element.addEventListener('click', ...). The difference between passing a named function (doSomething) and an anonymous arrow function as the callback. The introduction of the event object, which is automatically passed to your callback.

Named vs. Anonymous Callbacks

As the video showed, you can provide the callback function in two main ways:

  • Anonymous Function: A function defined directly inside the addEventListener call. This is concise and very common, especially with arrow functions.
    const myButton = document.querySelector('#myButton');
    myButton.addEventListener('click', () => {
      console.log('Button was clicked!');
    });
    
  • Named Function: A separate, named function. This is useful for reusability and, importantly, for removing the event listener later.
    const myButton = document.querySelector('#myButton');
    
    function handleButtonClick() {
      console.log('Button was clicked!');
    }
    
    myButton.addEventListener('click', handleButtonClick);
    

A common mistake is to call the function in the event listener, like handleClick(). Remember to pass the function reference (handleClick) itself, not the result of its execution.

To dive deeper into why using named functions can be beneficial, especially for removing listeners, the following article is an excellent read.

Event Listener

The article 'Event Listener' from Wes Bos's Beginner JavaScript course offers a great textual breakdown of these concepts.

Read the first few sections, up to and including 'Removing an Event Listener'. This will reinforce what you saw in the video and clearly explain: The definition of a callback function. The benefits of using a named function (reusability and unbinding). Why you need a reference to the original function to use removeEventListener.


2. The event Object: Context is Everything

When an event listener's callback function is executed, the browser automatically passes it a single argument: an event object. This object is packed with useful information about the interaction that just occurred.

By far, the most important property you'll use is event.target.

event.target refers to the specific element that triggered the event.

Imagine you have a <div> with three buttons inside. If you put a single click listener on the parent <div>, event.target will tell you which one of the three buttons was actually clicked.

JavaScript Event Listener with `event.target` in Console
This console output demonstrates how `event.target` identifies the specific `div` that was clicked, even though the listener might be on a parent `section`.

Let's return to the Dave Gray video to see a practical example of how event.target differs from the element the listener is attached to, especially when events "bubble" up through the DOM.

Event Listeners in JavaScript | JavaScript Events Tutorial

This clip clarifies the crucial difference between the element an event listener is attached to and the event.target that triggered it.

Watch from 20:24 to 24:01. Notice how using event.target makes the code react to the specific element clicked (the h2), even when the event bubbles up to the parent listeners.


3. Handling Forms and User Input

Clicks are just one type of event. Two other critical types for building applications are input changes and form submissions.

The input Event

This event fires on an <input>, <select>, or <textarea> element every time its value changes. It's perfect for features that need to react in real-time, like search-as-you-type or character counters.

const searchInput = document.querySelector('#search');

searchInput.addEventListener('input', (event) => {
  // event.target is the input element itself
  console.log(`User is typing: ${event.target.value}`);
});

The submit Event and preventDefault()

This is one of the most important concepts for a web developer. By default, when you click a submit button inside an HTML <form>, the browser tries to send the form's data to a server and then reloads the page.

In modern single-page applications, we want to prevent this default behavior. We want to intercept the form data with JavaScript, perhaps validate it, and then send it to an API without a full page refresh.

To do this, we:

  1. Attach a submit event listener to the <form> element itself (not the button).
  2. Call event.preventDefault() as the very first line in our callback function.
HTML Structure for Event Listeners in VS Code and Browser
A typical setup with a form and input, ready to be controlled by a `submit` event listener.

This next video segment demonstrates this crucial pattern.

Event Listeners in JavaScript | JavaScript Events Tutorial

Watch how Dave Gray prevents the default form submission behavior to handle it with JavaScript.

Watch from 34:40 to 39:13. The key takeaway is event.preventDefault(). Notice how the page stops reloading after it's added.

For some practical advice on the difference between click and submit and a common "gotcha" when working with form data, this short article is very helpful.

What I wish I knew about submit and click events.

This dev.to article provides practical insights that many new developers encounter when working with forms.

Read the sections that distinguish between 'click' and 'submit' events and the part about form inputs returning strings. The tip about parseInt() is something you'll use frequently.

Test your understanding!

You have a simple form:

<form id="login-form">
  <input type="text" id="username" placeholder="Username">
  <button type="submit">Log In</button>
</form>
<p id="message"></p>

Write JavaScript code that listens for the form submission. When submitted, it should prevent the page from reloading and display "Welcome, [username]!" in the <p> tag.

Show answer
const loginForm = document.querySelector('#login-form');
const usernameInput = document.querySelector('#username');
const messageP = document.querySelector('#message');

loginForm.addEventListener('submit', (event) => {
  // 1. Prevent the default page reload
  event.preventDefault();

  // 2. Get the value from the input
  const username = usernameInput.value;

  // 3. Update the message paragraph
  messageP.textContent = `Welcome, ${username}!`;

  // Optional: Clear the input field
  usernameInput.value = '';
});

4. A Quick Look at Event Bubbling

When an event happens on an element, it doesn't just stop there. After firing on the target, the event "bubbles" up through its ancestors in the DOM tree, all the way to the document. This means a click on a button will also trigger click event listeners on its parent div, its body, and so on.

This behavior is fundamental to how the web works and is the basis for a powerful pattern called event delegation, which we'll cover in the next lesson. For now, it's just important to know that it happens. You can stop it with event.stopPropagation(), but this should be used with caution as it can break expected behaviors.

Let's see a quick visualization of bubbling.

Event Listeners in JavaScript | JavaScript Events Tutorial

This short clip visually demonstrates event bubbling. When the innermost element is clicked, you'll see the event listeners on its parents fire one by one.

Watch from 13:31 to 15:20. Notice how a single click on the h2 triggers the event handlers on the div and the section as the event bubbles outwards.


Conclusion

Excellent work today! You've unlocked the power to make your web pages truly interactive by responding to user actions. This is a massive step towards your goal of building full-featured web applications.

Key Takeaways:

  • Use element.addEventListener('eventName', callback) to listen for user interactions.
  • The event object provides crucial context. event.target is the element that originated the event.
  • For forms you want to handle with JavaScript, always attach a submit listener to the <form> and call event.preventDefault() immediately.
  • Events "bubble" up the DOM tree from child to parent, a concept we will build on next.

In our next lesson, "Use event delegation to efficiently manage events on multiple or dynamic elements," we will leverage the concept of event bubbling to write cleaner, more efficient code for handling events on lists of items or elements that are added to the page dynamically.