Click Event & Attributes

I need to switch from ‘Light mode’ to ‘Dark mode’ and vice versa in one single Button and I’m having some issues with my if/else statement, clik event and ‘hasAttribute’ method. I don’t know why this doesn’t work.
How my program works:
I have an attribute insid my HTML tag called ‘data-theme’ to switch from light to dark and dark to light:

<html lang="en" data-theme="light">

Then, in y SCSS file I define my colors for each theme:

html { //Colors here for Light }
html[data-theme="dark"] { //Colors here for Dark }

Finally in my JavaScript file I have this code:

const mainButton = document.querySelector('.primary-cta');
// ~~~ Dark~Light Mode ~~~
mainButton.addEventListener('click', function (event) {
  event.preventDefault();
  if (document.documentElement.hasAttribute('data-theme', 'light')) {
    // Light to Dark
    document.documentElement.setAttribute('data-theme', 'dark');

  } else if (document.documentElement.hasAttribute('data-theme', 'dark')) {
    // Dark to Light
    document.documentElement.setAttribute('data-theme', 'light');
  }
})

It works switching from Light to Dark but if I try, later, to change to Light just doesn’t work. I can’t see where I’m falling .
Full project / CODEPEN: https://codepen.io/ricardorien/pen/OJbxYYa

Thanks in advance!

Be mindful of what exactly is happening when you use .hasAttribute('data-theme', 'light').
If you go over the API here: Element.hasAttribute() - Web APIs | MDN
hasAttribute(name) only accepts one parameter and it returns a boolean based on the first attribute data-theme. Since you’re coding in JS, the javascript compiler won’t care beyond the first single param you passed in; the params after the first one are ignored. On the surface it looks like you’re checking if data-theme='light' exists, but in fact it’s just checking to see if data-theme exists. The first time you run, it changes to dark because it does exist so the first if block runs. But once you click again, data-theme still exists (dark) so it will setAttribute('data-theme', 'dark') and no visible change is made (except for setting data-theme to dark again).

So what you want to do is use another method such as element.getAttribute(name) to get the value of data-theme to check whether it’s in light or dark mode. Element.hasAttribute() - Web APIs | MDN

This is a common problem with coding in Javascript and on Codepen; it won’t raise any errors since it’s loosely type based. You can make a bunch of unknown method calls and it won’t raise any errors until runtime. I recommend coding in Typescript so it will yell at you if you try to pass incorrect number of params for a function.

1 Like

What a grat explenation! So, that’s what happened. Thanks for that method, and for taking your time to solve this problem. Finally I can understand what is happen thanks to you,
Final Code:

mainButton.addEventListener('click', function (event) {
  event.preventDefault();
  if (document.documentElement.getAttribute('data-theme') === 'light') {
    // Light to Dark
    document.documentElement.setAttribute('data-theme', 'dark');

  } else  {
   // Dark to Light
    document.documentElement.setAttribute('data-theme', 'light');
  }
})
1 Like