Uncategorised

How to Subtract Days From a Date in JavaScript

1. Date setDate() and getDate() methods

To subtract days from a Date in JavaScript:

  1. Call the getDate() method on the Date to get the days.
  2. Subtract the days.
  3. Pass the result of the subtraction to the setDate() method.

For example:

function subtractDays(date, days) {
  date.setDate(date.getDate() - days);

  return date;
}

// May 15, 2022
const date = new Date('2022-05-15T00:00:00.000Z');

const newDate = subtractDays(date, 5);

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

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

The Date getDate() method returns a number between 1 and 31 that represents the day of the month of the particular Date.

The Date setDate() method changes the day of the month of the Date object to the number passed as an argument.

If the days you specify would change the month or year of the Date, setDate() automatically updates the Date information to reflect this.

// April 25, 2022
const date = new Date('2022-04-25T00:00:00.000Z');

date.setDate(40);

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

console.log(date.getDate()); // 10

April has only 30 days, so passing 40 to setDate() here increments the month by one and sets the day of the month to 10.

Avoiding Side Effects

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

function subtractDays(date, days) {
  // πŸ‘‡ Make copy with "Date" constructor
  const dateCopy = new Date(date);

  dateCopy.setDate(dateCopy.getDate() - days);

  return dateCopy;
}

const date = new Date('2022-05-15T00:00:00.000Z');

const newDate = subtractDays(date, 5);

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

// πŸ‘‡ Original not modified
console.log(date); // 2022-05-15T00: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 subDays() function

Alternatively, we can use the subDays() function from the date-fns NPM package to quickly subtract days from a Date. It works like our pure subtractDays() function.

import { subDays } from 'date-fns';

const date = new Date('2022-05-15T00:00:00.000Z');

const newDate = subDays(date, 5);

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

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

How to Get the Value of an Input When the Enter Key is Pressed in React

To get the value of an input when the Enter key is pressed 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 field value changes.
  3. Set an onKeyDown event handler on the input.
  4. Use the state variable to access the input value in the event handler, after checking that the key pressed is Enter.

For example:

App.js

import { useState } from 'react';

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

  const [updated, setUpdated] = useState('');

  const handleChange = (event) => {
    setMessage(event.target.value);
  };

  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      // πŸ‘‡ Get input value
      setUpdated(message);
    }
  };

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

      <h2>Message: {message}</h2>

      <h2>Updated: {updated}</h2>
    </div>
  );
}
Getting an input value when the Enter key is pressed.

With the useState() hook we create a state variable (message) to store the current value of the input field. We also create another state variable (updated) that will be updated with the input field value when the Enter key is pressed.

We set an onChange event handler on the input field to make this handler get called whenever the input value changes. In the handler we use the target property of the event object to access the object that represents the input element. The value property of this object contains the input value, so we pass it to setMessage() to update message, and this reflects on the page.

After setting up the controlled input, we can now use message outside the handleChange handler to access the current value of the input field.

We use the event.key property to get the key pressed in the onKeyDown event handler. After ensuring that this key is Enter, we use setUpdated(message) to update the updated variable with the current input field value.

Get input value on Enter with event.target

We can also get the value of the input when the Enter key is pressed using the target.value property of the Event object. This is useful in cases where we are not tracking the input value with a state variable, i.e., an uncontrolled input.

import { useState } from 'react';

export default function App() {
  const [updated, setUpdated] = useState('');

  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      setUpdated(event.target.value);
    }
  };

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

      <h2>Updated: {updated}</h2>
    </div>
  );
}
Getting an input value when the Enter key is pressed.

Get input value on Enter with ref

We can also use a ref to get the value of an uncontrolled input when the Enter key is pressed.

import { useRef, useState } from 'react';

export default function App() {
  const inputRef = useRef(null);

  const [updated, setUpdated] = useState('');

  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      setUpdated(inputRef.current.value);
    }
  };

  return (
    <div>
      <input
        ref={inputRef}
        type="text"
        id="message"
        name="message"
        onKeyDown={handleKeyDown}
      />

      <h2>Updated: {updated}</h2>
    </div>
  );
}

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

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 does not change value when a component is updated. Also, modifying the value of this object’s current property does not 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 Get the Value of an Input When a Button is Clicked in React

Related: How to Get an Input Field’s Value in React

To get the value of an input field on button click in React:

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

For example:

App.js

import { useState } from 'react';

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

  const [updated, setUpdated] = useState(message);

  const handleChange = (event) => {
    setMessage(event.target.value);
  };

  const handleClick = () => {
    // πŸ‘‡ "message" stores input field value
    setUpdated(message);
  };

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

      <h2>Message: {message}</h2>

      <h2>Updated: {updated}</h2>

      <button onClick={handleClick}>Update</button>
    </div>
  );
}
Getting the input value on button click.

With the useState() hook we create a state variable (message) to store the current value of the input field. We also create another state variable (updated) that will be updated with the input field value when the button is clicked.

We set an onChange event handler on the input field to make this handler get called whenever the input value changes. In the handler, we use the event.target property to access the object representing the input element. The value property of this object contains the input value, so we pass it to setMessage() to update message, and this reflects on the page.

After setting up the controlled input, we can now use message outside the handleChange handler to access the current value of the input field.

So in the onClick event handler we set on the button, we use setUpdated(message) to update the updated variable with the current input field value.

Get value of uncontrolled input on button click

To get the value of an uncontrolled input on button click in React:

  1. Create a ref for the input field
  2. Set an onClick event handler on the button.
  3. Use the ref object to access the current input value in the event handler.

For example:

App.js

import { useRef, useState } from 'react';

export default function App() {
  const inputRef = useRef(null);

  const [updated, setUpdated] = useState('');

  const handleClick = () => {
    // πŸ‘‡ "inputRef.current.value" is input value
    setUpdated(inputRef.current.value);
  };

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

      <h2>Updated: {updated}</h2>

      <button onClick={handleClick}>Update</button>
    </div>
  );
}
Updating text with the value of an input field on button click.

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

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 does not change value when a component is updated. Also, modifying the value of this object’s current property does not 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 Fix the “Cannot Find name ‘describe'” Error in TypeScript

To fix the “cannot find name ‘describe'” error, install the type definitions for your testing framework, and then add the definitions to the types array in your tsconfig.json file.

This error happens if you try to use the describe() function in a TypeScript file, but type definitions for the package are missing.

The "cannot find name 'describe'" error happening in a TypeScript file in VS Code.
index.ts
/* Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha`. ts(2582) */ describe('example', () => { it('adds two numbers together', () => { expect(2 + 2).toBe(4); }); }); ο»Ώ

Install the type definitions for the testing framework you’re using by running one of the following commands at the root of your project directory.

Shell
# πŸ‘‡ Jest npm i -D @types/jest jest # πŸ‘‡ Mocha npm i -D @types/mocha mocha # Yarn # πŸ‘‡ Jest yarn add --dev @types/jest jest # πŸ‘‡ Mocha yarn add --dev @types/mocha mocha

Add typings to types array in tsconfig.json

In some cases, this is all you need to fix the error. But if it persists, you might need to add the newly installed typings to the types array of your tsconfig.json file.

So if you’re using Jest, you’ll add a jest string to the types array, and then your tsconfig.json file will look something like this:

tsconfig.json
{ "compilerOptions": { "types": [ // ... other types "jest" ] // ..other settings } }

If you’re using Mocha too, you’ll add a mocha string to the types array.

tsconfig.json
{ "compilerOptions": { "types": [ // ... other types "mocha" ] // ..other settings } }

Include test files

If the error still doesn’t go away after doing this, make sure that TypeScript is not ignoring the directory containing your test files.

If you’ve set the include array in your tsconfig.json file, make sure the patterns specified in this array match the directory where your test files are located.

For example, if your test files are located in a src directory, TypeScript will detect them with a configuration like this:

tsconfig.json
{ "compilerOptions": {}, "include": ["src/**/*"], }

But if they’re located in a tests directory, we’ll need to add an additional glob pattern to make TypeScript detect them:

tsconfig.json
{ "compilerOptions": {}, "include": [ "src/**/*", "tests/**/*" ], }

We can also include glob patterns to match files with a specific ending or extension.

For example, we can include all files ending with .spec.ts and .test.ts with this config:

tsconfig.json
{ "compilerOptions": {}, "include": [ "src/**/*", "**/*.spec.ts", "**/*.test.ts" ], }

If you’ve set the exclude array in your tsconfig.json file, make sure that none of the patterns in the array match the directory containing the test files, as this will prevent TypeScript from detecting them.

For example, in the tsconfig.json file below, files ending with .spec.ts have been excluded, so TypeScript will ignore them and the error will occur when you attempt to use describe() in them.

tsconfig.json
{ "compilerOptions": {}, "include": [ "src/**/*" ], "exclude": [ "**/*.test.ts" ], }

We’ll fix this issue by simply moving the pattern string from exclude to include:

tsconfig.json
{ "compilerOptions": {}, "include": [ "src/**/*", "**/*.test.ts" ], }

Import module in file

Instead of adding the typings to the types array, you can also import them at the top of the file where you are using describe().

So if we’re using Jest, we’ll add an import 'jest' line at the beginning of the file.

index.ts
// πŸ‘‡ import 'jest'; // βœ… No error describe('example', () => { it('adds two numbers together', () => { expect(2 + 2).toBe(4); }); }); ο»Ώ

If we’re also using Mocha, we’ll add an import 'mocha' line:

index.ts
// πŸ‘‡ import 'mocha'; // βœ… No error describe('example', () => { it('adds two numbers together', () => { expect(2 + 2).toBe(4); }); }); ο»Ώ

Restart IDE

If the error persists after doing all of this, restarting your IDE might help.

How to Create the Material Design Text Field With HTML, CSS, and JavaScript

Material Design is a popular UI design system developed by Google. Apps using Material Design typically include responsive animations, attractive color combinations, and depth effects such as lighting and shadows.

In this article, we’ll learn how to recreate the design and animation of the Material Design text field, using only HTML, CSS, and JavaScript. We’ll be cloning the outlined text field variant, but similar steps can be taken to create the filled variant.

Here’s what we’ll have when we’re done:

The completed Material Design text field.

Create basic input and label

We’ll get started by creating the basic structure of the text field with HTML.

HTML

<div class="input-container">
  <input
    type="text"
    id="fname"
    name="fname"
    value=""
    aria-labelledby="label-fname"
  />
  <label class="label" for="fname" id="label-fname">
    <div class="text">First Name</div>
  </label>
</div>

We create an input element to allow typing into the text field, and we use a label element as the label for the text field. The text for this label (First Name) is wrapped in a div (.text) for because of the text animation we’re going to do later.

We use another div (.input-container) to wrap both the input and label elements, so that later we’ll able to place the label on top of the input with absolute positioning.

The basic input and label
The basic input and label.

Style input and label

Let’s add some styles for the input element and its container.

CSS

.input-container {
  position: relative;
}

input {
  height: 48px;
  width: 280px;
  border: 1px solid #c0c0c0;
  border-radius: 4px;
  box-sizing: border-box;
  padding: 16px;
}

We set position: relative for the container so that the label will be positioned relative to it when we set position: absolute for the label, instead of the entire page.

We’ll add styles for the label now.

CSS

.label {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 16px;
  display: flex;
  align-items: center;
}

Apart from the position: absolute we just talked about, we set top: 0 and bottom: 0 to make the label match the height of the input container.

The input has a 16px padding, so we set left: 16px to make the label match this padding and start from the same position as any text the user will type. Lastly, we horizontally center the contents of label in the input container using display: flex and align-items: center.

The input and label have been styled.

Remove pointer events

It looks like a text field now, but if you hover over the label, you’ll see the mouse pointer indicating that this is something that can be clicked. This means that it can block clicks on the input, which would create a bad user experience.

The label blocks clicks on the input.
The label blocks clicks on the input.

Luckily, we can easily fix this by setting pointer-events: none for the label element.

CSS

.label {
  ...
  pointer-events: none;
}
The label no longer blocks clicks on the input.
The label no longer blocks clicks on the input.

Style input font

Let’s change the font family and font size of the input text. We’ll do the same for the label.

CSS

input, .label .text {
  font-family: 'Segoe UI';
  font-size: 16px;
}
The font of the input and label has been changed.
The font of the input and label has been changed.

Style input on focus

Let’s use the :focus CSS selector to change some of the input styles when it receives focus.

CSS

input:focus {
  outline: none;
  border: 2px solid blue;
}

With this, the input border changes color and becomes thicker when the input gains focus.

The input border changes color and becomes thicker on input focus.

Style label on input focus

Let’s also style the input label when it is focused. On gaining focus the label should shrink, move up to meet the top input border, and change color to match the input border.

CSS

input:focus + .label .text {
  font-size: 12px;
  transform: translate(0, -50%);
  background-color: white;
  padding-left: 4px;
  padding-right: 4px;
  color: blue;
}

We set padding-left: 4px and padding-right: 4px to add some visual spacing between the label and the top input border.

Styling the label on input focus.

For a smooth transition, we’ll add a transition property to the label.

CSS

.label .text {
  transition: all 0.15s ease-out;
}
Adding a smooth transition to the label.

Keep label on top when non-empty input loses focus

There’s one more thing we have to do. When you enter text in the input element and remove the input, the label goes back to its original position.

When you enter text in the input element and remove the input, the label goes back to its original position.

It shouldn’t behave in this manner. But now we’re going to fix it with some CSS and JavaScript.

Remember, we’ve already defined a value attribute for the input element. We set it to an empty string.

HTML

<input
  type="text"
  id="fname"
  name="fname"
  value=""
  aria-labelledby="label-fname"
/>

Using the :not pseudo-class, we make the input when focused have the same style as when it is unfocused and non-empty. The only difference will be the color of the input border and label.

CSS

input:focus + .label .text, :not(input[value=""]) + .label .text {
  font-size: 12px;
  transform: translate(0, -150%);
  background-color: white;
  padding-left: 4px;
  padding-right: 4px;
}

input:focus + .label .text {
  color: blue;
}

We’re not done yet. Even though the value DOM property of the input changes according to what is entered, the value HTML attribute stays the same. We need a way to keep it in sync with the value property.

We can do this by adding a listener for the input event, which fires whenever the text in the input field changes. In the listener, we’ll use the setAttribute() method to update the value attribute with the current value of the value property.

JavaScript

const input = document.getElementById('fname');

input.addEventListener('input', () => {
  input.setAttribute('value', input.value);
});
The Material Design text field is complete.

That’s it. We’ve successfully created an outlined Material Design text field.

If you’re using a framework like Vue or React, it should be pretty easy to abstract everything we’ve done into a reusable component.

Here’s the complete source code:

How to Remove a DOM Element OnClick in JavaScript

To remove an element from the DOM onclick in JavaScript:

  1. Select the DOM element with a method like getElementById().
  2. Add a click event listener to the element.
  3. Call the remove() method on the element in the event handler.
const element = document.getElementById('el');

element.remove();

Consider this sample HTML where we create a blue box.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>
    <style>
      #box {
        height: 100px;
        width: 100px;
        background-color: blue;
      }
    </style>
  </head>
  <body>
    Click the box to remove it.

    <div id="box"></div>

    <script src="index.js"></script>
  </body>
</html>

Here’s how we can cause the element to be removed when it is clicked.

index.js

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

box.addEventListener('click', () => {
  box.remove();
});
Clicking the element removes it from the DOM.

We used the addEventListener() method to add a handler for the click event to the #box element. This event handler will be called whenever the user clicks the box.

In the handler function, we called the remove() method on the element to remove it from the DOM.

We could also have used the target property on the event object passed to the handler to remove the element.

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

box.addEventListener('click', (event) => {
  event.target.remove();
});

We can use the event object to access useful information and perform certain actions related to the event. For the click event, the target property lets us access the DOM element that was clicked.

Removing the element with the target property is useful when we want to dynamically remove many elements onclick. For example:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>
    <link rel="stylesheet" href="index.css" />
  </head>
  <body>
    Click on a box to remove it.

    <div class="container">
      <div class="box" id="box-1"></div>
      <div class="box" id="box-2"></div>
      <div class="box" id="box-3"></div>
    </div>

    <script src="index.js"></script>
  </body>
</html>

index.css

.container {
  display: flex;
}

.box {
  height: 100px;
  width: 100px;
  margin: 5px;
}

#box-1 {
  background-color: blue;
}

#box-2 {
  background-color: red;
}

#box-3 {
  background-color: green;
}

index.js

const boxes = document.getElementsByClassName('box');

for (const box of boxes) {
  box.addEventListener('click', (event) => {
    event.target.remove();
  });
}
Clicking on any one of the elements removes it.

We can also remove any one of the elements onclick by adding a single event listener to the parent of all the elements.

index.js

const container = document.querySelector('.container');

container.addEventListener('click', (event) => {
  event.target.remove();
});

This is because the target property returns the innermost element in the DOM that was clicked. This is in contrast to the event.currentTarget property, which returns the element that the event listener was added to.

How to Link an Image in React

Related: How to Use an Image as a Link in React

To link a local image in React, import the image at the top of the file and assign it to the src prop of an img element.

For example:

App.js

// πŸ‘‡ import image from file
import myImage from './my-image.jpg';

export default function App() {
  return (
    <div>
      {/* πŸ‘‡ show image */}
      <img src={myImage} alt="Trees" height="200" />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}
Linking and displaying an image on the webpage.
Linking and displaying an image on the webpage.

This approach works when using a Webpack-based tool like Create React App.

Note that the image file must be within the project directory to be imported successfully. An error will occur if the file is outside the project directory.

Alternatively, we can use the require() function to link an image in React.

The following code example will produce precisely the same result on the page as the first example.

App.js

export default function App() {
  return (
    <div>
      {/* πŸ‘‡ */}
      <img
        src={require('./my-image.jpg')}
        alt="Trees"
        height="200"
      />

      <br />
      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}

The advantage require() has here is that it doesn’t need to be at the top of the page. We can simply assign the result of require() to the src prop without having to store it in a variable.

Another way to link an image in React is to place it in the public folder and reference it with its relative path.

For example, if we placed the my-image.png file in the public folder, we’ll be able to display it in the page like this:

App.js

export default function App() {
  return (
    <div>
      {/* πŸ‘‡ show image */}
      <img src="./my-image.jpg" alt="Trees" height="200" />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}

Using the public folder is advantageous when we have many images that we want to display dynamically.

In the following examples, we dynamically display 100 images placed in a grid subfolder under public, and named with a certain pattern (image-1.jpg, image-2.jpg, …, image-100.png) in a grid.

App.js

export default function App() {
  return (
    <div>
      <div
        style={{
          display: 'grid',
          gridTemplateColumns:
            'repeat(auto-fit, minmax(min-content, 250px))',
          gap: '8px',
        }}
      >
        {[...Array(100)].map((_, i) => {
          return (
            <div>
              {/* πŸ‘‡ linking images dynamically */}
              <img
                key={i}
                src={`./grid/image-${i + 1}.jpg`}
                style={{ width: '100%', height: 'auto' }}
              />
            </div>
          );
        })}
      </div>
    </div>
  );
}

If the image is stored online, then we’ll just have to set the URL of the image to the src prop to link and display it, like we do in plain HTML.

App.js

export default function App() {
  return (
    <div>
      {/* πŸ‘‡ show remote image */}
      <img
        src="http://example.com/trees/my-image.jpg"
        alt="Trees"
        height="200"
      />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}

How to Subtract Years From a Date in JavaScript

1. Date setFullYear() and getFullYear() methods

To subtract years from a Date in JavaScript:

  1. Call the getFullYear() method on the Date to get the year.
  2. Subtract the years.
  3. Pass the result of the subtraction to the setFullYear() method.

For example:

function subtractYears(date, years) {
  date.setFullYear(date.getFullYear() - years);
  return date;
}

// Feb 20, 2022
const date = new Date('2022-02-20T00:00:00.000Z');

const newDate = subtractYears(date, 3);

// Feb 20, 2019
console.log(newDate); // 2019-02-20T00:00:00.000Z

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

The Date getFullYear() method returns a number that represents the year of a particular Date.

The Date setFullYear() method sets the year of a Date to a specified number.

Avoid side effects

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

function subtractYears(date, years) {
  // πŸ‘‡ make copy with "Date" constructor
  const dateCopy = new Date(date);

  dateCopy.setFullYear(date.getFullYear() - years);

  return dateCopy;
}

const date = new Date('2022-02-20T00:00:00.000Z');

const newDate = subtractYears(date, 3);

// Feb 20, 2019
console.log(newDate); // 2019-02-20T00:00:00.000Z

// πŸ‘‡ Original not modified
console.log(date); // 2022-02-20T00: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 subYears() function

Alternatively, we can use the subYears() function from the date-fns NPM package to quickly subtract years from a Date. It works like our pure subtractYears() function.

import { subYears } from 'date-fns';

const date = new Date('2022-02-20T00:00:00.000Z');

const newDate = subYears(date, 3);

// Feb 20, 2019
console.log(newDate); // 2019-02-20T00:00:00.000Z

// πŸ‘‡ Original not modified
console.log(date); // 2022-02-20T00:00:00.000Z

How to Set Focus on an Input in Vue

To set focus on an input in Vue:

  1. Set a ref on the input element.
  2. Access the new ref from the $refs property of the Vue instance.
  3. Call the focus() method on the ref element object.

Set focus on input on button click

For example:

App.js

<template>
  <div id="app">
    <input
      ref="name"
      placeholder="Name"
    />{{ ' ' }}
    <button @click="focusInput">Focus</button>
  </div>
</template>

<script>
export default {
  methods: {
    focusInput() {
      this.$refs.name.focus();
    },
  },
};
</script>
Clicking the button sets focus on the input.
Clicking the button sets focus on the input.

First, we create a new Vue instance ref by setting the input ref prop to a value (name).

<input
  ref="name"
  placeholder="Name"
/>

After doing this, we are able to access the $refs property of the Vue instance to access the object that represents the input element. We then call the focus() method on this object to set focus on the input.

this.$refs.name.focus();

We set the focusInput() method as a handler for the click event of the Focus button. So when the button is clicked, focusInput() is called and the input gains focus.

<button @click="focusInput">Focus</button>

Set focus on custom input component

Custom input components are useful for abstracting logic built around an input element and for reusing an input element styled in a particular way.

For custom components, calling focus() on its ref object will cause an error. For it to work, we’ll need to add a focus() method to the custom component that calls the focus() method of its root input element.

For example:

components/CustomInput.vue

<template>
  <input
    placeholder="Name"
    class="custom-input"
    ref="input"
  />
</template>

<script>
export default {
  methods: {
    // πŸ‘‡ Create custom "focus" method
    focus() {
      this.$refs.input.focus();
    },
  },
};
</script>

<style scoped>
.custom-input {
  font-family: 'Segoe UI';
  font-weight: bold;
  font-size: 16px;
  color: blue;
  height: 30px;
  width: 200px;
}
</style>

App.js

<template>
  <div id="app">
    <custom-input ref="name"></custom-input>
    <br />
    <br />
    <button @click="focusInput">Focus</button>
  </div>
</template>

<script>
import CustomInput from './components/CustomInput.vue';

export default {
  methods: {
    focusInput() {
      // πŸ‘‡ call custom "focus" method
      this.$refs.name.focus();
    },
  },
  components: { CustomInput },
};
</script>

Now we can set focus on the custom input component when the button is clicked.

Clicking the button sets focus on the custom input component.
Clicking the button sets focus on the custom input component.

Set focus on input after page load

To give the input focus immediately after the page loads, we can call the focus() method from the mounted lifecycle hook of the Vue instance with the input ref. The mounted method is called after a component is added to the DOM, which happens when a page is loading.

For example:

App.js

<template>
  <div id="app">
    <input
      ref="name"
      placeholder="Name"
    />
  </div>
</template>

<script>
export default {
  mounted() {
    this.focusInput();
  },
  methods: {
    focusInput() {
      this.$refs.name.focus();
    },
  },
};
</script>
The input gains focus after the page loads.
The input gains focus after the page loads.

Set focus on input after re-render

There are scenarios where we’ll need to wait for the DOM to be updated before calling focus() to give the input element focus.

For example, we might be using a boolean variable to determine whether an input element should be present in the DOM or not.

Because Vue batches state updates, the input element might not be added to the DOM immediately, and we won’t be able to access its ref right away.

We can use the nextTick() instance method to ensure that the DOM has been updated to include the input after modifying the boolean variable before calling focus().

<template>
  <div id="app">
    <!-- πŸ‘‡ conditional rendering with "v-if" directive -->
    <input
      v-if="showInput"
      ref="name"
      placeholder="Name"
    />
    <br /><br />
    <button @click="focusInput">Show and focus</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showInput: false,
    };
  },
  methods: {
    focusInput() {
      // πŸ‘‡ Set boolean variable to show input
      this.showInput = true;

      this.$nextTick(() => {
        // This callback will only be called after the
        // DOM has been updated
        this.$refs.name.focus();
      });
    },
  },
};
</script>
The input gains focus after the DOM is updated to include it.
The input gains focus after the DOM is updated to include it.

Set focus on next input after Enter press

Let’s say we have multiple input elements that need to be filled on the page. We could improve the UX by focusing on the succeeding text input when the user presses the Enter key to signify that they are done with filling in one input.

We do this by assigning a listener to the keypress event on the first input. Because of the enter event modifier, the event listener is only called when a key is pressed and the key is Enter.

We create a ref for the second input, and in the keypress.enter event listener we call the focus() method on the ref object to set focus on the second input.

<template>
  <div id="app">
    <form>
      <input
        placeholder="1st name"
        @keypress.enter="focusName2"
      />
      <br /><br />
      <input
        ref="name2"
        placeholder="2nd name"
      />
    </form>
  </div>
</template>

<script>
export default {
  methods: {
    focusName2() {
      this.$refs.name2.focus();
    },
  },
};
</script>
Pressing Enter sets focus on the next input.
Pressing Enter sets focus on the next input.

How to Remove the Hash From URLs in Vue Router

To remove the hash from URLs in Vue Router in Vue 3, set the history option in createRouter() to the result of createWebHistory().

main.js

const router = VueRouter.createRouter({
  history: VueRouter.createWebHistory(),
  ...
});

If you’re using Vue 2, set the mode option to 'history' in the VueRouter() constructor.

main.js

const router = new VueRouter({
  mode: 'history',
  ...
});

Remove hash from URL in Vue 3 and Vue Router 4

Here’s a sample Vue 3 app, where we make use of Vue Router 4.

main.js

import { createApp } from 'vue';
import { createRouter } from 'vue-router';
import App from './App.vue';
import HomePage from '@/views/HomePage.vue';
import ContactPage from '@/views/ContactPage.vue';
import AboutPage from '@/views/AboutPage.vue';

const app = createApp(App);

const routes = [
  { path: '/', component: HomePage },
  { path: '/about', component: AboutPage },
  { path: '/contact', component: ContactPage },
];

const router = createRouter({
  routes,
});

app.use(router);

app.mount('#app');

App.vue

<template>
  <div id="app">
    <router-link to="/">Home</router-link>{{ ' ' }}
    <router-link to="/about">About</router-link>{{ ' ' }}
    <router-link to="/contact">Contact</router-link>
    <router-view></router-view>
  </div>
</template>

views/HomePage.vue

<template>
  <div><h2>Welcome</h2></div>
</template>

views/AboutPage.vue

<template>
  <div><h2>About us</h2></div>
</template>

views/ContactPage.vue

<template>
  <div><h2>Contact us</h2></div>
</template>

Here’s what the home page of this web app will look like:

The router has a hash character before the path of the route.
There is a hash character before the index route path.

You can see that there is a hash character (#) before the index path (/) in the URL of the page. This happens because Vue Router uses hash history mode to represent the URLs of different routes. In hash mode, a hash character is placed before the route path, and this prevents the page from reloading when a Router link is clicked.

The router has a hash character before the "/about" path.
There is a hash character before the “/about” path.

The createRouter() function from vue-router creates a Router instance to be used by the Vue app. We can pass an object with a bunch of options to the function to customize the behavior of the router.

main.js

import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
import HomePage from '@/views/HomePage.vue';
import ContactPage from '@/views/ContactPage.vue';
import AboutPage from '@/views/AboutPage.vue';

const app = createApp(App);

const routes = [
  { path: '/', component: HomePage },
  { path: '/about', component: AboutPage },
  { path: '/contact', component: ContactPage },
];

// πŸ‘‡
const router = createRouter({
  history: createWebHistory(),
  routes,
});

app.use(router);

app.mount('#app');

Setting the history option to the result of the createWebHistory() function from vue-router switches the router from hash history mode to HTML5 history mode. This removes the hash from the URLs.

There is no hash character before the index route path.
There is no hash character before the index route path.
There is no hash character before the "/about" route path.
There is no hash character before the “/about” route path.

Remove hash from URL in Vue 2 and Vue Router 3

Vue 2 apps use Vue Router 3, so the Router initialization logic will differ.

Your main.js file might look like this at the moment:

main.js

import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
import HomePage from '@/views/HomePage.vue';
import ContactPage from '@/views/ContactPage.vue';
import AboutPage from '@/views/AboutPage.vue';

Vue.config.productionTip = false;
Vue.use(VueRouter);

const routes = [
  { path: '/', component: HomePage },
  { path: '/about', component: AboutPage },
  { path: '/contact', component: ContactPage },
];

const router = new VueRouter({
  routes,
});

new Vue({
  router,
  render: (h) => h(App),
}).$mount('#app');

Here we use a VueRouter() constructor to create a new router instance. Like createRouter(), we can pass a set of options to customize its behavior. To change from hash history mode to HTML5 history mode and remove the hash from the URLs, set the mode option to 'history'.

main.js

import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
import HomePage from '@/views/HomePage.vue';
import ContactPage from '@/views/ContactPage.vue';
import AboutPage from '@/views/AboutPage.vue';

Vue.config.productionTip = false;
Vue.use(VueRouter);

const routes = [
  { path: '/', component: HomePage },
  { path: '/about', component: AboutPage },
  { path: '/contact', component: ContactPage },
];

// πŸ‘‡
const router = new VueRouter({
  mode: 'history',
  routes,
});

new Vue({
  router,
  render: (h) => h(App),
}).$mount('#app');