DOM events and callbacks
The DOM in a web page generates a multitude of events (e.g. click, keydown, load, etc.) for web apps to respond to. The developer can write JavaScript functions (i.e. “callbacks”) and attach them to DOM events such that the callback runs every time that event fires.
Simple Event Callback
Here’s a simple example:
- Create a button somewhere on your page with
idofbtn1. Make sure it is a standalone button, and not a part of aform. - Add the following JavaScript code to the page. It must run after the button is loaded into the page.
const btn1 = document.getElementById("btn1"); // there must be a button on the page with this id
let counter = 0; // a counter to count clicks
btn1.addEventListener("click", function(event) { // the callback gets the DOM `event` as parameter
const target = event.target; // the DOM element that is the "target" of the event (button that was clicked)
counter++; // increment the counter
const message = `You clicked ${target.id} ${counter} time${counter>1 ? 's' : ''}`;
target.innerText = message; // update DOM
});
- Test it. It should work.
- Now wrap the button in a
formtag, like this:
<form>
<button id="btn1">Click Me!</button>
</form>
- Test it again. This time you should see something strange. The button text does change for a brief moment, but then goes back to the original (“Click Me!”) soon after.
- The reason is that since this button is a part of a
form, right after executing your callback, it performs the button’s default action, which is to submit the form. And since the form is getting submitted, the whole page refreshes. - To fix this, call
event.preventDefault()on the event before returning.
btn1.addEventListener("click", function(event) {
event.preventDefault(); // don't perform the default action of this event
// ... code to respond to the event ...
});
Form Submit Example
In modern JavaScript apps, it is very common to convert a traditional form from submitting normally (and refreshing the whole page) to intercepting the submission, performing client-side validations, and then sending form inputs to server using AJAX and handling the response, all without refreshing the page.
<!-- input -->
<form id="test-form">
<input name="firstName" type="text" placeholder="First Name" required>
<input name="lastName" type="text" placeholder="Last Name" required>
<input name="dob" type="date" placeholder="Date of Birth">
<select name="employment" required>
<option value="">Employment Status</option>
<option>Salaried</option>
<option>Self-Employed</option>
<option>Retired</option>
<option>Unemployed</option>
</select>
<div>
<button>Submit</button>
<button type="reset">Reset</button>
</div>
</form>
<!-- output -->
<fieldset>
<legend>Submissions</legend>
<ol id="submission-list">
<!-- submissions will appear here -->
</ol>
</fieldset>
const submissions = document.getElementById("submission-list");
document.getElementById("test-form").addEventListener("submit", function(e) {
e.preventDefault(); // prevent submission (default action)
const form = e.target;
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
// client-side validation
if(data.firstName.length < 3 || data.lastName.length < 3) {
alert("First Name and Last Name must be at least 3 characters long");
return; // Validation failed. Abort.
}
const li = document.createElement("LI");
li.innerText = JSON.stringify(data);
submissions.append(li);
});
Note that:
- We are attaching to the
submitevent of theformand notclickevent of thebutton. - We call
preventDefaultto prevent the full page refresh. - We construct a
FormDataobject, which extracts all the input values from the form. - We perform client-side validation on the submitted
data, and abort if validation fails.