Tari Ibaba

Tari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

How to Fix the “Cannot read property ‘addEventListener’ of null” Error in JavaScript

The “cannot read property ‘addEventListener’ of null” error occurs in JavaScript when you try to call the addEventListener() method on an element that cannot be found in the DOM. This happens for two main reasons:

  1. Accessing the addEventListener() method on an element absent from the DOM.
  2. Inserting the script tag referencing the JavaScript file at a point above the declaration of the DOM element in the HTML.

We’ll learn how to handle the error for these two scenarios in this article.

The "cannot read property 'addEventListener' of null" error occurring in JavaScript.

Cause 1: Accessing addEventListener() on an element not present in the DOM

index.js

const btn = document.getElementById('does-not-exist');

console.log(btn); // null

// ❌ Cannot read property 'addEventListener' of null
btn.addEventListener('click', () => {
  alert('You clicked the button');
});

When a method like getElementById() or querySelector() method is used to search for an element that doesn’t exist in the DOM, it returns null. And attempting to call the addEventListener() method on a null value will cause the error.

Solve: Ensure correct selector

To fix the “cannot read property ‘addEventListener’ of null” error, make sure the selector used the access the element is properly defined. Ensure that there are no mistakes in the ID or class name, and the correct symbols are used.

Solve: Check for null

To fix the “cannot read property ‘addEventListener’ of null” error, check that the element is not null before calling the addEventListener() method on it.

We can do this with an if statement:

const btn = document.getElementById('does-not-exist');

console.log(btn); // null

// âś… Check if element exists before calling addEventListener()
if (btn) {
  // Not called
  btn.addEventListener('click', () => {
    alert('You clicked the button');
  });
}

When a value is placed in between the brackets of an if statement, it is coerced to a Boolean before being evaluated, i.e., truthy values become true, and falsy values become false. null is a falsy value, so it is coerced to false and the code in the if statement block is never run.

Note: In JavaScript, there are six falsy values: undefined, null, NaN, 0, '' (empty string) and false. Every other value is truthy.

We can also use the optional chaining operator (?.) to check if the element is null.

const btn = document.getElementById('does-not-exist');

console.log(btn); // null

// âś… Check if element exists before calling addEventListener()

// Not called
btn?.addEventListener('click', () => {
  alert('You clicked the button');
});

The optional chaining operator (?.) is null-safe way of accessing a property or calling a method of an object. If the object is nullish (null or undefined), the operator prevents the member access and returns undefined instead of throwing an error.

Cause 2: Inserting the script tag above the DOM element

Another common cause of this error is placing the <script> tag referencing the JavaScript file at a point above where the target element is declared.

For example, in this HTML markup:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>
    <!-- ❌ Script is run before button is declared -->
    <script src="index.js"></script>
  </head>
  <body>
    <button id="btn">Sign up</button>
  </body>
</html>

the script tag is placed in the head tag, above where the button element is declared, so the index.js file will not be able to access the button element.

index.js

const btn = document.getElementById('btn');

console.log(btn); // null

// ❌ TypeError: Cannot read properties of null
btn.addEventListener('click', () => {
  alert('You clicked the button');
});

Solve: Move script tag to bottom of body

To fix the error in this case, move the script tag to the bottom of the body, after all the HTML elements have been declared.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>
  </head>
  <body>
    <button id="btn">Sign up</button>

    <!-- âś… Script is run after button is declared -->
    <script src="index.js"></script>
  </body>
</html>

Now the index.js script file will have access to the button element and all the other HTML elements, because they would have already been declared when the script is run.

index.js

const btn = document.getElementById('btn');

console.log(btn); // HTMLButtonElement object

// âś… Works as expected
btn.addEventListener('click', () => {
  alert('You clicked the button');
});

Solve: Access element in DOMContentLoaded event listener

Another way to fix the “cannot read property ‘addEventListener’ of null” error in JavaScript is to add a DOMContentLoaded event listener to the document, and access the element in this listener. With this approach it won’t matter where we place the script in the HTML.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>

    <!-- Script placed above element accessed -->
    <script src="index.js"></script>
  </head>
  <body>
    <button id="btn">Sign up</button>
  </body>
</html>

The DOMContentLoaded event is fired when the browser has fully loaded the HTML, and the DOM tree has been built, but external resources like images and stylesheets may not have loaded. So regardless of where we place the script, the code in the listener is only called after all the declared HTML elements have been added to the DOM.

index.js

document.addEventListener('DOMContentLoaded', () => {
  const btn = document.getElementById('btn');

  console.log(btn); // HTMLButtonElement object

  // âś… Works as expected
  btn.addEventListener('click', () => {
    alert('You clicked the button');
  });
});

Conclusion

We can fix the “cannot read property addEventListener’ of null” error in JavaScript by ensuring that the correct selector is defined, adding a null check to the element before calling addEventListener(), moving the script tag to the bottom of the body, or accessing the element in a DOMContentLoaded event listener added to the document.

How to Open a Link in a New Tab in Vue

To open a link in a new tab in Vue, create an anchor (<a>) element and set its target attribute to _blank, e.g., <a href="https://codingbeautydev.com" target="_blank"></a>. The _blank value specifies that the link should be opened in a new tab.

App.vue

<template>
  <div id="app">
    <a
      href="https://codingbeautydev.com"
      target="_blank"
      rel="noreferrer"
    >
      Coding Beauty
    </a>

    <br /><br />

    <a
      href="https://codingbeautydev.com/blog"
      target="_blank"
      rel="noreferrer"
    >
      Coding Beauty Blog
    </a>
  </div>
</template>

The target property of the anchor element specifies where to open the linked document. By default target has a value of _self, which makes the linked page open in the same frame or tab where it was clicked. To make the page open in a new tab, we set target to _blank.

We also set the rel prop to noreferrer for security purposes. It prevents the opened page from gaining any information about the page that it was opened from.

The link is opened in a new tab.
The link is opened in a new tab.

Sometimes we’ll prefer a button instead of a link to open the new tab when clicked.

To open a link in a new tab on button click, create a button element and set an click event listener that calls the window.open() method.

App.vue

<template>
  <div id="app">
    <p>
      Click this button to visit Coding Beauty in a new tab
    </p>

    <button
      role="link"
      @click="openInNewTab('https://codingbeautydev.com')"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {
  methods: {
    openInNewTab(url) {
      window.open(url, '_blank', 'noreferrer');
    },
  },
};
</script>
The link is opened when the button is clicked.
The link is opened when the button is clicked.

We use the open() method of the window object to programmatically open a link in a new tab. This method has three optional parameters:

  1. url: The URL of the page to open in a new tab.
  2. target: like the target attribute of the <a> element, this parameter’s value specifies where to open the linked document, i.e., the browsing context. It accepts all the values the target attribute of the <a> element accepts.
  3. windowFeatures: A comma-separated list of feature options for the window. noreferrer is one of these options.

Passing _blank to the target parameter makes the link get opened in a new tab.

When the button is clicked, the event listener is called, which in turn calls window.open(), which opens the specified link in a new tab.

How to Remove Special Characters From a String in JavaScript

To remove all special characters from a string, call the replace() method on the string, passing a whitelisting regex and an empty string as arguments, i.e., str.replace(/^a-zA-Z0-9 ]/g, ''). The replace() method will return a new string that doesn’t contain any special characters.

For example:

const str = 'milk and @#$%&!bread';

const noSpecialChars = str.replace(/[^a-zA-Z0-9 ]/g, '');

console.log(noSpecialChars); // milk and bread

The String replace() method searches a string for a value (substring or regular expression), and returns a new string with the value replaced by a substring. It doesn’t modify the original string.

The square brackets in the regular expression ([]) indicates a character class. Only characters that are enclosed in it will be matched.

But after placing the caret (^) as the first character in the square bracket, only characters that are not enclosed in the square bracket will be matched.

After the caret, we specify:

  • ranges for lowercase (a-z) and uppercase (A-Z) letters.
  • a range for digits from 0-9.
  • a space character (' ').

So the regex matches any character is not a lowercase or uppercase letter, digit or space, and the replace() method returns a new string with all of these characters removed from the original string.

The g (global) flag specifies that every occurrence of the pattern should be matched.

If we don’t pass a global flag, only the first special character in the string will be matched and removed.

const str = 'milk and @#$%&!bread';

// 👇 No 'g' flag in regex
const noSpecialChars = str.replace(/[^a-zA-Z0-9 ]/, '');

// 👇 Only first special character removed
console.log(noSpecialChars); // milk and #$%&!bread

Shorten regular expression with \w character.

We can shorten this regular expression a bit with the \w character.

const str = 'milk and @#$%&!bread';

const noSpecialChars = str.replace(/[^\w ]/g, '');

console.log(noSpecialChars); // milk and bread

The \w character matches uppercase and lowercase Latin letters, digits, and underscores.

Since \w matches underscores, it can’t be used on its own to remove this special character from a string.

const str = '_milk_ _and _@#$%&!_bread_';

const noSpecialChars = str.replace(/[^\w ]/g, '');

console.log(noSpecialChars); // _milk_ _and_ _bread_

We’ll need a different regex to remove the underscores:

const str = '_milk_ _and _@#$%&!_bread_';

const noSpecialChars = str.replace(/([^\w ]|_)/g, '');

console.log(noSpecialChars); // milk and bread

The pipe symbol (|) allows either of two patterns to be matched in a string, similar to a character class. To use the pipe symbol we need to wrap the two patterns in parentheses (( and )), which is what we did.

How to Get the Value of a Form Input on Submit in React

To get the value of form input on submit in React:

  1. Create a state variable to store the value of the input.
  2. Set an onChange event handler on the input to update the state variable when the input’s value changes.
  3. Set an onSubmit event handler on the form element.
  4. Access the value of the input field in the onSubmit event handler.

For example:

App.js

import { useState } from 'react';

export default function App() {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [message, setMessage] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault();

    setMessage(`Hello ${firstName} ${lastName}!`);
    setFirstName('');
    setLastName('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        id="firstName"
        name="firstName"
        value={firstName}
        placeholder="First Name"
        onChange={(event) =>
          setFirstName(event.target.value)
        }
      />

      <br />
      <br />

      <input
        type="text"
        id="lastName"
        name="lastName"
        value={lastName}
        placeholder="Last Name"
        onChange={(event) => {
          setLastName(event.target.value);
        }}
      />

      <br />
      <br />

      <button type="submit">Submit</button>

      <br />
      <br />

      <h2>{message}</h2>
    </form>
  );
}
The input values are used to display a message on form submit.

With the useState() hook we create a state variable to store the current value of each input field. We also created another state variable (message) that will be updated with the values of the input fields after the user submits the form.

We set an inline onChange event handler on each input field to make the handler get called whenever the input field changes. In each handler, we use the target property of the Event object the handler receives to access the input element object. The value property of this object contains the input value, so we pass it to the state update function to update the value of that particular input.

The button element in the form has a type of submit, so every time the user clicks it, the submit event is triggered. We set an onSubmit event handler on the form to listen to this event. In this handler, we call preventDefault() on the Event object, to prevent the page from refreshing when the form is submitted.

To get the input values in this event handler after the form is submitted, we simply access the firstName and lastName state variables.

Get input value on form submit with event.target

We can also get the value of a form input on submit using the target property of the Event object. This is useful in cases where we don’t track the input value with a state variable, i.e., an uncontrolled input.

App.js

import { useState } from 'react';

export default function App() {
  const [message, setMessage] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault();

    const firstName = event.target.firstName.value;
    const lastName = event.target.lastName.value;
    setMessage(`Hello ${firstName} ${lastName}!`);

    event.target.reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        id="firstName"
        name="firstName"
        placeholder="First Name"
      />

      <br />
      <br />

      <input
        type="text"
        id="lastName"
        name="lastName"
        placeholder="Last Name"
      />

      <br />
      <br />

      <button type="submit">Submit</button>

      <br />
      <br />

      <h2>{message}</h2>
    </form>
  );
}

In an onSubmit event handler, the target property of the Event object returns the form element object (of type HTMLFormElement).

Because we set the name prop on the input element, the form element object will contain a property with the same name that returns the input element object, i.e., after setting name to firstName on an input element, we can access the element object for this input with the firstName property on the form element object.

After getting the value of each input and displaying the message, we call the reset() method on the form element object to restore the default values of the form’s input elements. This is how we clear the text in the input fields in this example since they’re not controlled by state variables.

Get input value on form submit with ref

We can also use a component ref to get the value of an uncontrolled form input on submit in React.

App.js

import { useState, useRef } from 'react';

export default function App() {
  const [message, setMessage] = useState('');
  const firstNameRef = useRef(undefined);
  const lastNameRef = useRef(undefined);

  const handleSubmit = (event) => {
    event.preventDefault();

    const firstName = firstNameRef.current.value;
    const lastName = lastNameRef.current.value;

    setMessage(`Hello ${firstName} ${lastName}!`);

    event.target.reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        id="firstName"
        name="firstName"
        placeholder="First Name"
        ref={firstNameRef}
      />

      <br />
      <br />

      <input
        type="text"
        id="lastName"
        name="lastName"
        placeholder="Last Name"
        ref={lastNameRef}
      />

      <br />
      <br />

      <button type="submit">Submit</button>

      <br />
      <br />

      <h2>{message}</h2>
    </form>
  );
}

The data in a controlled input is handled by React state, but for an uncontrolled input, it is handled by the DOM itself. This is why the input in this example above doesn’t have a value prop or onChange event handler set. Instead, we access the input field’s value with a React ref. The DOM updates this value when the text in the input is changed.

For each input, we create a ref object with the useRef() hook and set it to the ref prop of the input. Doing this sets the current property of the ref object to the DOM object that represents the input element.

useRef() returns a mutable ref object that doesn’t change value when a component is updated. Also, modifying the value of this object’s current property doesn’t cause a re-render. This is in contrast to the setState update function returned from useState().

Although the React documentation recommends using controlled components, uncontrolled components offer some advantages. You might prefer them if the form is very simple and doesn’t need instant validation, and values only need to be accessed when the form is submitted.

How to Subtract 6 Months From a Date in JavaScript

To subtract 6 months from a date:

  1. Call the getMonth() method on the date to get the months.
  2. Subtract 6 from the return value of getMonth().
  3. Pass the result of the subtraction to the setMonth() method.

For example:

function subtract6Months(date) {
  date.setMonth(date.getMonth() - 6);

  return date;
}

// November 14, 2022
const date = new Date('2022-11-14T00:00:00.000Z');

const newDate = subtract6Months(date);

// May 14, 2022
console.log(newDate); // 2022-05-14T00:00:00.000Z

Our subtract6Months() function takes a Date object and the number of months to subtract as arguments. It returns the same Date object with 6 months subtracted.

The Date getMonth() returns a zero-based number that represents the month of a particular date.

The Date setMonth() method sets the months of a date to a specified zero-based number.

Note: â€śZero-based” here means that 0 is January, 1 is February, 2 is March, etc.

If the months subtracted would decrease the year of the date, setMonths() will automatically update the date information to reflect this.

// January 10, 2022
const date = new Date('2022-01-10T00:00:00.000Z');

date.setMonth(date.getMonth() - 6);

// July 10, 2021
console.log(date); // 2021-07-10T00:00:00.000Z

In this example, we subtract 6 months from a date in January 2022. This makes the year automatically get rolled back to 2021 by setMonth().

Avoid side-effects

The setMonth() mutates the Date object it is called on. This introduces a side effect into our subtract6Months() function. To avoid modifying the passed Date and create a pure function, make a copy of the Date and call setMonth() on this copy, instead of the original.

function subtract6Months(date) {
  // 👇 Make copy with "Date" constructor
  const dateCopy = new Date(date);

  dateCopy.setMonth(dateCopy.getMonth() - 6);

  return dateCopy;
}

// August 13, 2022
const date = new Date('2022-08-13T00:00:00.000Z');

const newDate = subtract6Months(date);

// February 13, 2022
console.log(newDate); // 2022-02-13T00:00:00.000Z

// 👇 Original not modified
console.log(date); // 2022-08-13T00:00:00.000Z

Tip: Functions that don’t modify external state (i.e., pure functions) tend to be more predictable and easier to reason about, as they always give the same output for a particular input. This makes it a good practice to limit the number of side effects in your code.

2. date-fns subMonths() function

Alternatively, we can use the subMonths() function from the date-fns NPM package to quickly subtract 6 months from a date. It works like our pure subtractMonths() function. subMonths() takes a Date object and the number of months to subtract as arguments. It returns a new Date object with the months subtracted.

import { subMonths } from 'date-fns';

// July 26, 2022
const date = new Date('2022-07-26T00:00:00.000Z');

const newDate = subMonths(date, 6);

// January 26, 2022
console.log(newDate); // 2022-01-26T00:00:00.000Z

// Original not modified
console.log(date); // 2022-07-26T00:00:00.000Z

Note that the subMonths() function returns a new Date object without modifying the one passed to it.

How to Subtract Months From a Date in JavaScript

1. Date getMonth() and setMonth() methods

To subtract months from a date in JavaScript:

  1. Call the getMonth() method on the Date to get the months.
  2. Subtract the months.
  3. Pass the result of the subtraction to the setMonth() method.

For example:

function subtractMonths(date, months) {
  date.setMonth(date.getMonth() - months);
  return date;
}

// August 13, 2022
const date = new Date('2022-08-13T00:00:00.000Z');

const newDate = subtractMonths(date, 3);

// May 13, 2022
console.log(newDate); // 2022-05-13T00:00:00.000Z

Our subtractMonths() function takes a Date object and the number of months to subtract as arguments. It returns the same Date object with the months subtracted.

The Date getMonth() method returns a zero-based number that represents the month of a particular date.

The Date setMonth() method sets the months of a date to a specified zero-based number.

Note: “Zero-based” here means that 0 is January, 1 is February, 2 is March, etc.

If the months subtracted would decrease the year of the date, setMonth() will automatically update the date information to reflect this.

// January 10, 2022
const date = new Date('2022-01-10T00:00:00.000Z');

date.setMonth(date.getMonth() - 2);

// November 10, 2021: year decreased by 1
console.log(date); // 2021-11-10T00:00:00.000Z

In this example, we subtracted 2 months from a date in January 2022. This makes setMonth() automatically roll the year back to 2021.

Avoid side-effects

The setMonth() method mutates the Date object it is called on. This introduces a side effect into our subtractMonths() function. To avoid modifying the passed Date and create a pure function, make a copy of the Date and call setMonth() on this copy, instead of the original.

function subtractMonths(date, months) {
  // 👇 Make copy with "Date" constructor
  const dateCopy = new Date(date);

  dateCopy.setMonth(dateCopy.getMonth() - months);

  return dateCopy;
}

// August 13, 2022
const date = new Date('2022-08-13T00:00:00.000Z');

const newDate = subtractMonths(date, 3);

// May 13, 2022
console.log(newDate); // 2022-05-13T00:00:00.000Z

// 👇 Original not modified
console.log(date); // 2022-08-13T00:00:00.000Z

Tip: Functions that don’t modify external state (i.e., pure functions) tend to be more predictable and easier to reason about, as they always give the same output for a particular input. This makes it a good practice to limit the number of side effects in your code.

2. date-fns subMonths() function

Alternatively, we can use the subMonths() function from the date-fns NPM package to quickly subtract months from a date. It works like our pure subtractMonths() function.

import { subMonths } from 'date-fns';

// June 27, 2022
const date = new Date('2022-06-27T00:00:00.000Z');

const newDate = subMonths(date, 4);

// February 27, 2022
console.log(newDate); // 2022-02-27T00:00:00.000Z

// 👇 Original not modified
console.log(date); // 2022-06-27T00:00:00.000Z

How to Add a Class Conditionally in Vue

To add a class conditionally to an element in Vue, set the class prop to a JavaScript object where for each property, the key is the class name, and the value is the boolean condition that must be true for the class to be set on the element.

<p
  v-bind:class="{
    'class-1': class1,
    'class-2': class2,
  }"
>
  Coding
</p>

Here’s a complete example:

App.vue

<template>
  <div id="app">
    <input
      type="checkbox"
      name="class-1"
      v-model="class1"
    />
    <label for="class-1">Class 1</label>

    <br />

    <input
      type="checkbox"
      name="class-2"
      v-model="class2"
    />
    <label for="class-2">Class 2</label>

    <!-- 👇 Add classes conditionally -->
    <p
      v-bind:class="{
        'class-1': class1,
        'class-2': class2,
      }"
    >
      Coding
    </p>
    <p
      v-bind:class="{
        'class-1': class1,
        'class-2': class2,
      }"
    >
      Beauty
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      class1: false,
      class2: false,
    };
  },
};
</script>

<style>
.class-1 {
  font-size: 2em;
  font-weight: bold;
}

.class-2 {
  color: blue;
  text-transform: uppercase;
}
</style>
Setting a class conditionally in Vue.
The classes are only applied when their respective checkboxes are checked.

The class-1 class will only present on the element if the class1 variable is true, and the class-2 class will only be present if the class2 variable is true. The values of these variables are determined by the current checked state of their respective checkboxes since we use v-model to set up a two-way binding between the variables and the checkboxes.

Use :class shorthand

We can use :class as a shorthand for v-bind:class.

<p
  :class="{
    'class-1': class1,
    'class-2': class2,
  }"
>
  Coding
</p>
<p
  :class="{
    'class-1': class1,
    'class-2': class2,
  }"
>
  Beauty
</p>

Pass object as computed property

The JavaScript object passed doesn’t have to be inline. It can be stored as a computed property in the Vue component instance.

<template>
  <div id="app">
    ...
    <!-- 👇 Add classes conditionally -->
    <p :class="classObject">Coding</p>
    <p :class="classObject">Beauty</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      class1: false,
      class2: false,
    };
  },
  computed: {
    // 👇 Computed object property
    classObject() {
      return {
        'class-1': this.class1,
        'class-2': this.class2,
      };
    },
  },
};
</script>
...

Add both static and dynamic classes

We can set the class prop on the same element twice, once to add static classes, and once to add the dynamic classes that will be present based on certain conditions.

For example:

<template>
  <div id="app">
    <input
      type="checkbox"
      name="class-1"
      v-model="class1"
    />
    <label for="class-1">Class 1</label>

    <br />

    <input
      type="checkbox"
      name="class-2"
      v-model="class2"
    />
    <label for="class-2">Class 2</label>

    <!-- 👇 Add classes conditionally and statically -->
    <p
      class="static-1 static-2"
      :class="{ 'class-1': class1, 'class-2': class2 }"
    >
      Coding
    </p>
    <p
      class="static-1 static-2"
      :class="{ 'class-1': class1, 'class-2': class2 }"
    >
      Beauty
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      class1: false,
      class2: false,
    };
  },
};
</script>

<style>
.class-1 {
  font-size: 2em;
  font-weight: bold;
}

.class-2 {
  color: blue;
  text-transform: uppercase;
}

/* 👇 Classes to add statically */
.static-1 {
  font-family: 'Segoe UI';
}

.static-2 {
  font-style: italic;
}
</style>
Adding a class conditionally in Vue.
The texts are styled with static classes before being conditionally styled with dynamic classes.

The static-1 and static-2 classes are always applied to the texts, making them italic and changing the font.

How to Convert XML to JSON in JavaScript

We can use the xml-js library from NPM to easily convert XML to JSON in JavaScript, i.e.:

import { xml2json } from 'xml-js';

// ...

const json = xml2json(xml);

For example:

index.js

import { xml2json } from 'xml-js';

const xml = `<name>Garage</name>
<cars>
    <color>red</color>
    <maxSpeed>120</maxSpeed>
    <age>2</age>
</cars>
<cars>
    <color>blue</color>
    <maxSpeed>100</maxSpeed>
    <age>3</age>
</cars>
<cars>
    <color>green</color>
    <maxSpeed>130</maxSpeed>
    <age>2</age>
</cars>`;

const json = xmltojson(xml, );

console.log(json);

This code will have the following output:

{"declaration":{"attributes":{"version":"1.0","encoding":"UTF-8"}},"elements":[{"type":"element","name":"languages","elements":[{"type":"element","name":"language","elements":[{"type":"text","text":"\n      English\n   "}]},{"type":"element","name":"language","elements":[{"type":"text","text":"\n      French\n   "}]},{"type":"element","name":"language","elements":[{"type":"text","text":"\n      Spanish\n   "}]}]}]}

What are XML and JSON?

Let’s go through these terms in case you’re not familiar with them

XML (eXtensible Markup Language) is a markup language similar to HTML that was designed to store and transport data. Unlike HTML, XML doesn’t have any predefined tags. Instead, we define our own tags according to our requirements.

JSON (JavaScript Object Notation) is a text format used to store and transport data based on JavaScript object syntax and is commonly used to build RESTful APIs.

Install xml-js

Before using xml-js, we need to install it in our project. We can do this with the NPM CLI.

npm i xml-js

Or with the Yarn CLI:

yarn add xml-js

After installation, we’ll be able to import it into a JavaScript module, like this:

import { xml2json } from 'xml-js';

We use import destructuring to access the xml2json() method directly from the library.

For a CommonJS module, we’ll import it like this instead:

const { xml2json } = require('xml-js');

The xml2json() function

The xml2json() function has two parameters. The first is the XML string to convert to JSON, and the second is an optional object.

const json = xml2json(xml, { spaces: 2, compact: true });

Customize conversion of XML to JSON

We use this object to specify various options for customizing the conversion process.

In our example, we don’t pass an object, so the default options are used. We can pass an object with a spaces option to properly format and indent the resulting JSON.

import { xml2json } from 'xml-js';

const xml = `<?xml version="1.0" encoding="UTF-8"?>
<languages>
   <language>
      English
   </language>
   <language>
      French
   </language>
   <language>
      Spanish
   </language>
</languages>`;

// 👇 Set "spaces" option
const json = xml2json(xml, { spaces: 2 });

console.log(json);

Here’s the new output:

{
  "declaration": {
    "attributes": {
      "version": "1.0",
      "encoding": "UTF-8"
    }
  },
  "elements": [
    {
      "type": "element",
      "name": "languages",
      "elements": [
        {
          "type": "element",
          "name": "language",
          "elements": [
            {
              "type": "text",
              "text": "\n      English\n   "
            }
          ]
        },
        {
          "type": "element",
          "name": "language",
          "elements": [
            {
              "type": "text",
              "text": "\n      French\n   "
            }
          ]
        },
        {
          "type": "element",
          "name": "language",
          "elements": [
            {
              "type": "text",
              "text": "\n      Spanish\n   "
            }
          ]
        }
      ]
    }
  ]
}

The compact property to determine whether the resulting JSON should be detailed or compact. It is false by default.

import { xml2json } from 'xml-js';

const xml = `<?xml version="1.0" encoding="UTF-8"?>
<languages>
   <language>
      English
   </language>
   <language>
      French
   </language>
   <language>
      Spanish
   </language>
</languages>`;

// 👇 Set "compact" option
const json = xml2json(xml, { spaces: 2, compact: true });

console.log(json);

Now the resulting JSON will have a significantly smaller size than before:

{
  "_declaration": {
    "_attributes": {
      "version": "1.0",
      "encoding": "UTF-8"
    }
  },
  "languages": {
    "language": [
      {
        "_text": "\n      English\n   "
      },
      {
        "_text": "\n      French\n   "
      },
      {
        "_text": "\n      Spanish\n   "
      }
    ]
  }
}

How to Detect a Browser or Tab Close Event in JavaScript

To detect a browser or tab close event in JavaScript:

  1. Add a beforeunload event listener to the global window object.
  2. In this listener, call the preventDefault() method on the Event object passed to it.
  3. Set the returnValue property of this Event object to an empty string ('').

JavaScript

window.addEventListener('beforeunload', (event) => {
  event.preventDefault();
  event.returnValue = '';
});

We’ll need to detect the event of a browser or tab close to alert the user of any unsaved changes on the webpage.

We use the addEventListener() method to attach an event handler to any DOM objects such as HTML elements, the HTML document, or the window object.

The beforeunload event is fired right before the window, document, and its resources are about to be unloaded. At this point, the document is still visible, and the event is still cancelable.

We have to call preventDefault() on the Event object the handler receives to show the confirmation dialog in the browser. The preventDefault() method prevents the default action of an event. For the beforeunload event, preventDefault() stops the unloading of the resources, the window, and the document.

This JavaScript code will cause a confirmation dialog to be displayed when the user tries to close the browser or tab. Here’s some sample HTML to use the JavaScript in.

HTML

<a href="codingbeautydev.com">Coding Beauty</a>
<br />
Try to close the tab or browser
A confirmation dialog is shown when the user tries to close the tab.
A confirmation dialog is shown when the user tries to close the tab.
A confirmation dialog is shown when the user tries to close the browser.
A confirmation dialog is shown when the user tries to close the browser.

Note that the beforeunload event is triggered not only when the browser or tab is closed, but also when a link is clicked, a form is submitted, the backward/forward button is pressed, or the page is refreshed.

A confirmation dialog is shown when a link is clicked on the page.
A confirmation dialog is shown when a link is clicked on the page.
A confirmation dialog is shown when the user tries to refresh the page.
A confirmation dialog is shown when the user tries to refresh the page.

How to Get an Input Value On Change in React

To get the value of an input on change in React, set an onChange event handler on the input, then use the target.value property of the Event object passed to the handler to get the input value.

For example:

App.js

import { useState } from 'react';

export default function App() {
  const [message, setMessage] = useState('');

  const handleChange = (event) => {
    // 👇 Get input value from "event"
    setMessage(event.target.value);
  };

  return (
    <div>
      <input
        type="text"
        id="message"
        name="message"
        onChange={handleChange}
      />

      <h2>Message: {message}</h2>
    </div>
  );
}
Getting an input value on change in React.
The message is updated when the input value changes.

Here we create a state variable (message) to track the input value. By setting an onChange event handler, the handler function will get called whenever the text in the input field changes.

The handler function will be called with an Event object containing data and allowing actions related to the event. The target property of this object lets us access the object representing the input element.

This input element object has a value property which returns the text currently in the input field. So we call the setMessage() function with this property as an argument to update the message variable with the input value, and this reflects on the page after the DOM is updated.