In our starter files, open the index.html page from this lessons folder:
04.Events-And-The-DOM > 13.Preventing-default-behaviour-and the-passive-option
When an event is fired it has some default behaviour which occurs in the browser, and this makes sense because we want the event to do something. A simple example is a checkbox, to see this, over to the starter files:
<!-- index.html (add after last section): -->
<input type="checkbox" id="check">
Then in the events.js
we can listen for the event as we have previously:
// 3. Create a function to run on each click
function handleClick(e) {
}
// 1. Select the checkbox
const checkbox = document.querySelector('#check');
// 2. Listen for a click
checkbox.addEventListener('click', handleClick);
Inside of the function, we can find out if the checkbox is checked or not, using e.target.checked
:
function handleClick(e) {
console.log(e.target.checked);
}
Give this a try in the browser (it will be in the bottom left corner). This will toggle true
or false
when clicked. This toggling action is the default behaviour.
If we did not want this we could prevent the default behaviour and handle what happens ourselves. In an earlier example we made use of a method called stopPropagation
:
function addToFavourites(e) {
e.stopPropagation();
alert(`${e.target.parentNode.children[2].innerText}`);
}
This was available on the event object. And like this, we can make use of another method called preventDefault
in the handleClick
function:
function handleClick(e) {
e.preventDefault();
console.log(e.target.checked);
}
This will stop the default behaviour, which was to toggle the checkbox value, and you will see the console value remain true after clicking.
We are now free to do whatever we want when the user clicks on the checkbox. On the addEventListener
method, we also have an option called passive
:
checkbox.addEventListener('click', handleClick, {passive: true} );
Setting this to true will stop preventDefault
from ever being called. Now the default behaviour to toggle the checkbox value has been reinstated we will see an error in the console when the checkbox is clicked:
Unable to preventDefault inside passive event listener invocation.
You maybe want to do this to stop other developers from doing something in the future when we are relying on the default behaviour. Also, using the passive option can lead to better performance.
An example of this is on mobile devices. Sometimes developers prevent the default scroll behaviour to implement some fancy way of scrolling. If we are not doing something custom like this, it is better to let the browser know by adding the passive option, therefore it does not have figure it out for itself which can take time.
A common example of preventing the default behaviour is with forms.
To see this, add this form
in place of the checkbox
:
<section class="signup">
<h3>Sign up for weekly recipes to your inbox</h3>
<form>
<div>
<label for="name">name: </label>
<input id="name" type="text">
</div>
<div>
<label for="email">email: </label>
<input id="email" type="email">
</div>
<div>
<input id="submit" type="submit">
</div>
</form>
</section>
Remove the event listener code from the previous example then over in the browser, we can test this out. Add a name, email, and then click submit.
When we submit a form, the default behaviour is to send the form to the server, then redirect to a new/success page. We don’t have a redirect page set, so it will redirect to the same page causing the page to refresh.
This refresh loses the form data. If we wanted to validate this data first before it was sent to the server, we would need to prevent this default behaviour.
We can set this up just like with the checkbox.
event.js
// 1. get form and input elements
const form = document.querySelector('form');
const userName = document.querySelector('#name');
const userEmail = document.querySelector('#email');
// 2. Create a function to run on submit
function handleFormSubmit(e) {
console.log(userName.value);
}
// 3. attach event listener to form when submit has been called
form.addEventListener('submit', handleFormSubmit);
Now when we submit, we can see the problem, we briefly get the console log with the user’s name, but then it refreshes and goes away. To stop this, we call preventDefault
:
function handleFormSubmit(e) {
e.preventDefault();
console.log(userName.value);
}
The log should now remain after a submit. Now we have this data such as the name and email, we can validate it and check it is the correct format before sending to the server.
Let's add a simple validation check to see if the user has entered a name, using an if
statement. We have not covered if
statements in detail yet, but they are a way to check if something is true:
function handleFormSubmit(e) {
e.preventDefault();
console.log(userName.value);
// simple validation example
if(userName.value === '') {
alert('Please enter your name');
return;
}
}
This if
statement will only run of the name value is empty. This now gives us the chance to do whatever we want with the data before sending to the server. Remember, since the page is no longer reloading, we also need to handle emptying the form fields ourselves:
function handleFormSubmit(e) {
e.preventDefault();
console.log(userName.value);
if(userName.value === '') {
alert('Please enter your name');
return;
}
// reset input values
userName.value= '';
userEmail.value= '';
// send to server code
// …
}
The form inputs will now clear after the form has submitted.