vue

How to Get the Current Year in Vue.js

To get the current year in Vue.js, create a new Date object with the Date() constructor, then use the getFullYear() method to get the year of the Date. getFullYear() will return a number that represents the current year.

For example:

App.vue
<template> <div> {{ new Date().getFullYear() }} <div> &copy; {{ new Date().getFullYear() }} Coding Beauty </div> </div> </template>
The current year is displayed.
The current year is displayed.

We use the Date() constructor to create a new Date object. When Date() is called with no arguments, the Date object is created using the current date and time.

The Date getFullYear() method returns a number that represents the year of the Date. Since the Date object here stores the current date, getFullYear() returns the current year.

Get current year with data property

We can also put the current year in a data variable instead of placing it directly in the template with the {{ }} symbols. This allows us to more easily reuse the value in multiple places in the template markup.

App.vue
<template> <div> {{ currYear }} <div>&copy; {{ currYear }} Coding Beauty</div> </div> </template> <script> export default { data() { return { currYear: new Date().getFullYear(), }; }, }; </script>

Get current year with Composition API

Of course, this also works when using the Vue 3 Composition API:

App.vue
<script setup> const currYear = new Date().getFullYear(); </script> <template> <div> {{ currYear }} <div>&copy; {{ currYear }} Coding Beauty</div> </div> </template>

Get current month

If you also want to get the current month, the getMonth() method is for you.

getMonth() returns a zero-based index that represents the month of the Date. Zero-based here means that 0 = January, 1 = February, 2 = March, etc.

App.vue
<template> <div>Month number {{ currMonth }} in {{ currYear }}</div> </template> <script> export default { data() { return { currMonth: new Date().getMonth(), currYear: new Date().getFullYear(), }; }, }; </script>
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getmonth
The month number is displayed.

If you want the month name directly (the more likely case), the Date toLocaleString() method will do the job.

App.vue
<template> <div>{{ currMonth }} in {{ currYear }}</div> </template> <script> export default { data() { return { currMonth: new Date().toLocaleString([], { month: 'long', }), currYear: new Date().getFullYear(), }; }, }; </script>
The month name is displayed.

Check out this article for a full guide on how to convert a month number to its equivalent month name in JavaScript.

Get current day of month

Similarly, to get the current day in the month, you’d use the Date getDate() method:

App.vue
<template> <div>{{ currMonth }} {{ currDay }}, {{ currYear }}</div> </template> <script> export default { data() { return { currDay: new Date().getDate(), currMonth: new Date().toLocaleString([], { month: 'long', }), currYear: new Date().getFullYear(), }; }, }; </script>
The current day of the month is displayed.
The current day of the month is displayed.

Get current year, month, day, week…

While you could get each component of the date using different functions, a much more flexible and easy way to do this is by formatting the date in the given format with a format specifier.

We can carry out this formatting with the format() function from the date-fns library.

In the following example, we use date-fns format() to get the multiple individual parts of the date.

App.vue
<template> <div>{{ dateString }}</div> </template> <script> import { format } from 'date-fns'; export default { data() { return { dateString: format( new Date(), "EEEE, 'the' do 'of' LLLL, yyyy" ), }; }, computed() { return {}; }, }; </script>
Different parts of the date are displayed using formatting.
Different parts of the date are displayed using formatting.

The format() function takes a pattern and returns a formatted date string in the format specified by the pattern. You can find a list of the patterns format() accepts here.

For our example, we use the following patterns:

  • EEEE: to get the full name of the day of the week.
  • do: to get the ordinal day of the month, i.e., 1st, 2nd, 3rd, etc.
  • LLLL: to get the full name of the month of the year.
  • yyyy: to get the full year.

We also use single quotes to escape strings (the and of) that are not patterns but should be included in the result of the formatting.

How to Easily Handle the onScroll Event in Vue

To handle the onScroll event on a Vue element, assign a function to the scroll event of the element and use the event object the function receives to perform an action. The action will occur whenever the user scrolls up or down on the page.

For example:

App.vue
<template> <div id="app"> Scroll top: <b>{{ scrollTop }}</b> <br /> <br /> <div id="box" @scroll="handleScroll" > <p v-for="i in 10" :key="i" > Content </p> </div> </div> </template> <script> export default { data() { return { scrollTop: 0, }; }, methods: { handleScroll(event) { this.scrollTop = event.currentTarget.scrollTop; }, }, }; </script> <style scoped> #box { border: 1px solid black; width: 400px; height: 200px; overflow: auto; } </style>
The text is update when the componet's onScroll event fires.
The text is updated when the component’s onScroll event fires.

We use the @ character to set a listener for an event on the component.

Vue
<div id="box" @scroll="handleScroll" > <!-- ... --> </div>

The @ character is a shorter alternative to v-on:

Vue
<div id="box" v-on:scroll="handleScroll" > <!-- ... --> </div>

The function (event handler) passed to the scroll event is invoked whenever the viewport is scrolled. It is called with an event object, which you can use to perform actions and access information related to the scroll event.

The currentTarget property of this event object returns the element that the scroll listener was attached to.

Tip: If you’re not sure of when to use the event object’s currentTarget or target properties, this article might help: Event target vs currentTarget in JavaScript: The Important Difference.

We use the element’s scrollTop property to get how far the element’s scrollbar is from its topmost position. Then we update the state variable with the new value, and this reflects on the page.

Handle onScroll event on window object

We can also handle the onScroll event on the global window object, to perform an action when the viewport is scrolled.

The addEventListener() method lets us do this:

JavaScript
<template> <div id="app"> Scroll top: <b>{{ scrollTop }}</b> <br /> <br /> <div id="label">Scroll top: {{ scrollTop }}</div> <div> <p v-for="i in 30" :key="i" > Content </p> </div> </div> </template> <script> export default { data() { return { scrollTop: 0, }; }, methods: { handleScroll() { this.scrollTop = window.scrollY; }, }, mounted() { window.addEventListener('scroll', this.handleScroll); }, beforeUnmount() { window.removeEventListener('scroll', this.handleScroll); }, }; </script> <style scoped> #label { position: fixed; padding: 10px 0; top: 0; background-color: white; border-bottom: 1px solid #c0c0c0; width: 100%; } </style>
The text is updated when the window’s onScroll event fires.
The text is updated when the window’s onScroll event fires.

The addEventListener() method takes up to two arguments:

  1. type: a string representing the event type to listen for, e.g., 'click', 'keydown', 'scroll', etc.
  2. listener: the function called when the event fires.

It also has some optional parameters, which you can learn more about here.

We call addEventListener() in the mounted hook to register the listener once the component renders as the page loads. mounted is only called for a component when it has been added to the DOM, so the listener will not be registered multiple times.

We also called the removeEventListener() method to unregister the event listener and prevent a memory leak. We place the call in the beforeUnmount hook so that it happens just before the component is removed from the DOM.

How to Capitalize the First Letter of a String in Vue.js

To capitalize the first letter of a string in Vue:

  1. Get the string’s first letter with [0].
  2. Uppercase this letter with .toUpperCase().
  3. Get the rest of the string with .slice(1).
  4. Add the results together.

For example:

App.vue

<template>
  <div id="app">
    <b>{{ name1 }}</b>
    <br />
    Capitalized: <b>{{ capitalized(name1) }}</b>
    <br /><br />
    <b>{{ name2 }}</b
>
    <br />
    Capitalized:
    <b>{{ capitalized(name2) }}</b>
  </div>
</template>

<script>
export default {
  data() {
    return { name1: 'coding beauty', name2: 'javascript' };
  },
  methods: {
    capitalized(name) {
      const capitalizedFirst = name[0].toUpperCase();
      const rest = name.slice(1);

      return capitalizedFirst + rest;
    },
  },
};
</script>
The strings and their capitalized forms.
The strings and their capitalized forms.

We create a reusable Vue instance method (capitalized) that takes a string and capitalizes its first letter.

We use bracket indexing ([ ]) to get the 0 property of the string – the character at index 0. String (and array) indexing is zero-based in JavaScript, so the string’s first character is at index 0, the second is at index 1, and so on, until the last character at index str.length-1.

After getting the string’s first character, we uppercase it with the toUpperCase() method.

We use the slice() method to get the rest of the string. slice() returns the portion of a string between a specified start and an optional end index. If the end index is omitted, the substring will range from the start index to the end of the string.

Hence, slice(1) returns a substring ranging from the second character to the end.

After getting the remaining part of the string, all that’s left is simply concatenating it with the capitalized first letter.

If it’s necessary for the resulting string to have only its first letter capitalized, you can call the toLowerCase() method on the result of slice(), to lowercase the rest of the string before concatenation.

const capitalizedFirst = name[0].toUpperCase();

// 👇 toLowerCase()
const rest = name.slice(1).toLowerCase();

return capitalizedFirst + rest;

Use Computed Property

If you’re trying to capitalize a string data property of the Vue instance (like in our example), you can use a computed property in place of a method.

<template>
  <div id="app">
    <b>{{ name1 }}</b>
    <br />
    Capitalized: <b>{{ capitalizedName1 }}</b> <br /><br />
    <b>{{ name2 }}</b
    ><br />
    Capitalized:
    <b>{{ capitalizedName2 }}</b>
  </div>
</template>

<script>
export default {
  data() {
    return { name1: 'coding beauty', name2: 'javascript' };
  },
  methods: {
    capitalized(name) {
      const capitalizedFirst = name[0].toUpperCase();
      const rest = name.slice(1);

      return capitalizedFirst + rest;
    },
  },

  // 👇 Computed properties
  computed: {
    capitalizedName1() {
      return this.capitalized(this.name1);
    },
    capitalizedName2() {
      return this.capitalized(this.name2);
    },
  },
};
</script>

Using a computed property for this is useful when the data is likely to change in the app’s lifetime, e.g., in a two-way binding with an input field. When the data property changes, the depending computed property will be recalculated and updated automatically.

How to Check if a Checkbox is Checked in Vue.js

To check if a checkbox is checked in Vue:

  1. Create a boolean state variable to store the value of the checkbox.
  2. Use v-model to set up a two-way binding between the checkbox’s value and the state variable.
  3. If the checkbox is checked, the state variable will be true. Otherwise, it will be false.

For example:

App.vue

<template>
  <div id="app">
    <input
      type="checkbox"
      v-model="agreement"
      name="agreement"
    />

    <label for="agreement">
      I agree to the terms and conditions
    </label>

    <br /><br />

    <button :disabled="!agreement">Continue</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      agreement: false,
    };
  },
};
</script>
The button is disabled when the checkbox is checked, and enabled when it is unchecked.
The button is disabled when the checkbox is checked, and enabled when it is unchecked.

The checked property of the checkbox object indicates whether or not the checkbox is checked.

Every time the checkbox is checked or unchecked, the agreement state variable will be automatically updated to true or false respectively.

We set the button‘s disabled prop to the negation of agreement to disable and enable it when agreement is true and false respectively.

Check if checkbox is checked with ref

In most cases, v-model will be sufficient for checking if a checkbox if a checked in Vue. However, we can also use the ref attribute to get the input value. We can set this attribute on any DOM element and use the $refs property of the Vue instance to access the object that represents the element.

For example:

<template>
  <div id="app">
    <!-- 👇 Set "ref" prop to create new ref -->
    <input
      type="checkbox"
      name="js"
      ref="theCheckbox"
    />

    <label for="js"> JavaScript </label>
    <br />
    <button @click="handleClick">Done</button>
    <p v-if="message">{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return { message: '' };
  },
  methods: {
    handleClick() {
      // 👇 Access ref with "$refs" property
      if (this.$refs.theCheckbox.checked) {
        this.message = 'You know JS';
      } else {
        this.message = "You don't know JS";
      }
    },
  },
};
</script>
The checked state of the checkbox determines the message displayed when the button is clicked.
The checked state of the checkbox determines the message displayed when the button is clicked.

We set an onClick listener on the button. In this listener, we access the checkbox object using the ref, and use its checked property to determine the message that should be shown to the user when the button is clicked.

How to Change the Style of an Element on Click in Vue

To change the style of an element on click in Vue:

  1. Create a boolean state variable to conditionally set the style on the element depending on the value of this variable.
  2. Set a click event handler on the element that toggles the value of the state variable.

For example:

App.vue

<template>
  <div id="app">
    <p>Click the button to change its color.</p>

    <button
      role="link"
      @click="handleClick"
      class="btn"
      :style="{
        backgroundColor: active ? 'white' : 'blue',
        color: active ? 'black' : 'white',
      }"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      active: false,
    };
  },
  methods: {
    handleClick() {
      this.active = !this.active;
    },
  },
};
</script>

<style>
.btn {
  border: 1px solid gray;
  padding: 8px 16px;
  border-radius: 5px;
  font-family: 'Segoe UI';
  font-weight: bold;
}
</style>
Clicking the element changes its stye.
Clicking the element changes its style.

The active state variable determines the style that will be applied to the element. When it is false (the default), a certain style is applied.

We set a click event handler on the element, so that the handler will get called when it is clicked. The first time this handler is called, the active variable gets toggled to true, which changes the style of the element.

Note

To prevent the style from changing every time the element is clicked, we can set the state variable to true, instead of toggling it:

handleClick() {
  this.active = true

  // this.active = !this.active
},

We used ternary operators to conditionally set the backgroundColor and color style on the element.

The ternary operator works like an if/else statement. It returns the value before the ? if it is truthy. Otherwise, it returns the value to the left of the :.

const treshold = 10;

const num = 11;

const result = num > treshold ? 'Greater' : 'Lesser';

console.log(result) // Greater

So if the active variable is true, the backgroundColor and color are set to white and black respectively. Otherwise, they’re set to blue and white respectively.

Change element style on click with classes

To change the style of an element on click in Vue, we can also create classes containing the alternate styles and conditionally set them to the class prop of the element, depending on the value of the boolean state variable.

For example:

App.vue

<template>
  <div id="app">
    <p>Click the button to change its color.</p>

    <button
      role="link"
      @click="handleClick"
      class="btn"
      :class="active ? 'active' : 'non-active'"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      active: false,
    };
  },
  methods: {
    handleClick() {
      this.active = !this.active;
    },
  },
};
</script>

<style>
.btn {
  border: 1px solid gray;
  padding: 8px 16px;
  border-radius: 5px;
  font-family: 'Segoe UI';
  font-weight: bold;
}

.active {
  background-color: white;
  color: black;
}

.non-active {
  background-color: blue;
  color: white;
}
</style>

We create two classes (active and non-active) with different styles, then we use the ternary operator to add the active class if the active variable is true, and add the non-active class if otherwise.

The advantage of using classes is that we get to cleanly separate the styles from the template markup. Also, we only need to use one ternary operator.

Change element style on click with event.currentTarget.classList

There are other ways to change the style of an element in Vue without using a state variable.

With classes defined, we can use the currentTarget.classList property of the Event object passed to the click event handler to change the style of the element.

For example:

App.vue

<template>
  <div id="app">
    <p>Click the button to change its color.</p>

    <button
      role="link"
      @click="handleClick"
      class="btn non-active"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {

  methods: {
    handleClick(event) {
      // 👇 Change style
      event.currentTarget.classList.remove('non-active');
      event.currentTarget.classList.add('active');
    },
  },
};
</script>

<style>
.btn {
  border: 1px solid gray;
  padding: 8px 16px;
  font-family: Arial;
  font-size: 1.1em;
  box-shadow: 0 2px 5px #c0c0c0;
}

.active {
  background-color: white;
  color: black;
}

.non-active {
  background-color: rebeccapurple;
  color: white;
}
</style>
Clicking the element changes its style.
Clicking the element changes its style.

We don’t use a state variable this time, so we add the non-active class to the element, to customize its default appearance.

The click event listener receives an Event object used to access information and perform actions related to the click event.

The currentTarget property of this object returns the element that was clicked and had the event listener attached.

We call the classList.remove() method on the element to remove the non-active class, then we call the classList.add() method on it to add the active class.

Notice that the style of the element didn’t change anymore after being clicked once. If you want to toggle the style whenever it is clicked, you can use the toggle() class of the element to alternate the classes on the element.

App.vue

<template>
  <div id="app">
    <p>Click the button to change its color.</p>

    <button
      role="link"
      @click="handleClick"
      class="btn non-active"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick(event) {

      // 👇 Alternate classes
      event.currentTarget.classList.toggle('non-active');
      event.currentTarget.classList.toggle('active');
    },
  },
};
</script>

<style>
.btn {
  border: 1px solid gray;
  padding: 8px 16px;
  font-family: Arial;
  font-size: 1.1em;
  box-shadow: 0 2px 5px #c0c0c0;
}

.active {
  background-color: white;
  color: black;
}

.non-active {
  background-color: rebeccapurple;
  color: white;
}
</style>
Clicking the element toggles its color.
Clicking the element toggles its color.

The classList.toggle() method removes a class from an element if it is present. Otherwise, it adds the class to the element.

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 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 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');

How to Create a Spinner With Bootstrap Vue

A spinner is used to indicate an ongoing process to the user. They are suitable for operations that don’t take very long to complete, and they help to enhance the responsiveness of an application. Read on to learn more about the Vue Bootstrap spinner component and the various customization options it provides.

The Boostrap Vue Spinner Component (b-spinner)

Boostrap Vue provides the b-spinner component for creating spinners. It starts spinning as soon as it has been rendered on the page.

<template>
  <div
    id="app"
    class="text-center"
  >
    <b-spinner></b-spinner>
  </div>
</template>
The Bootstrap Vue Spinner component (b-spinner)

Border spinner

We can use the type prop to display a particular type of spinner. By default the type is set to border, which makes the spinner transparent and gives it a thick circle border.

<template>
  <div
    id="app"
    class="text-center"
  >
    <b-spinner type="border"></b-spinner>
  </div>
</template>
A border spinner in Bootstrap Vue

Grow spinner

Alternatively, we can set type to grow to make the spinner repeatedly grow into view and fade out.

<template>
  <div
    id="app"
    class="text-center"
  >
    <b-spinner type="grow"></b-spinner>
  </div>
</template>
A grow spinner in Bootstrap Vue

Spinner colors

b-spinner comes with a variant prop that lets us customize the color of the spinner. There are a bunch of values it can take, including primary, secondary, danger, warning, success, and info.

Here we create multiple border spinners with many different colors:

<template>
  <div
    id="app"
    class="text-center d-flex justify-content-between"
  >
    <b-spinner
      v-for="variant in variants"
      :key="variant"
      :variant="variant"
    ></b-spinner>
  </div>
</template>

<script>
export default {
  data() {
    return {
      variants: [
        'primary',
        'secondary',
        'danger',
        'warning',
        'success',
        'info',
      ],
    };
  },
};
</script>
Border spinner components with different color variants.

We can also customize the color of grow spinners with the variant prop:

<template>
  <div
    id="app"
    class="text-center d-flex justify-content-between"
  >
    <b-spinner
      v-for="variant in variants"
      :key="variant"
      :variant="variant"
      type="grow"
    ></b-spinner>
  </div>
</template>

<script>
export default {
  data() {
    return {
      variants: [
        'primary',
        'secondary',
        'danger',
        'warning',
        'success',
        'info',
      ],
    };
  },
};
</script>
Grow spinner components with different color variants.

For more color customization options we can set the color CSS property using inline styles.

<template>
  <div
    id="app"
    class="text-center m-3 d-flex justify-content-between"
  >
    <b-spinner style="color: orange"></b-spinner>
    <b-spinner style="color: blue"></b-spinner>
    <b-spinner style="color: #800080"></b-spinner>
    <b-spinner style="color: green"></b-spinner>
    <b-spinner style="color: red"></b-spinner>
    <b-spinner style="color: #424242"></b-spinner>
  </div>
</template>
Customizing spinner colors with inline CSS.

Spinner size

Setting the small prop to true on the b-spinner creates a spinner of a smaller size.

<template>
  <div
    id="app"
    class="text-center"
  >
    <b-spinner small></b-spinner>
    <b-spinner
      type="grow"
      small
    ></b-spinner>
  </div>
</template>
Using the small prop of the Bootstrap Vue spinner component

For more size customization options, we can add some inline styles to customize the width and height CSS properties.

<template>
  <div
    id="app"
    class="text-center"
  >
    <b-spinner
      style="width: 50px; height: 50px"
    ></b-spinner>
    <b-spinner
      type="grow"
      style="width: 50px; height: 50px"
    ></b-spinner>
  </div>
</template>
Customizing the size of the spinner with inline styles.

Spinner margin

We can add any of the Bootstrap Vue margin utility classes to a b-spinner to adjust its spacing. Here we use the ms-4 class from Bootstrap to add a left margin to the second spinner:

<template>
  <div
    id="app"
    class="text-center"
  >
    <b-spinner></b-spinner>
    <b-spinner
      type="grow"
      class="ms-4"
    ></b-spinner>
  </div>
</template>
Adjusting spinner margin.

Spinner in button

One good use for a spinner is within a button, to indicate that an action is currently taking place.

<template>
  <div
    id="app"
    class="text-center"
  >
    <b-button variant="primary">
      <b-spinner small></b-spinner>
      Loading...
    </b-button>
  </div>
</template>
Using the Boostrap Vue spinner component in a button.

Here’s a more practical example of using spinners within buttons. When the button is clicked to save, it changes its text and shows the spinner to indicate the ongoing save operation (simulated with a timeout). Then it hides the spinner and changes the text again after the save.

<template>
  <div
    id="app"
    class="text-center m-3"
  >
    <b-button
      variant="primary"
      @click="save"
    >
      <b-spinner
        small
        v-if="status === 'saving'"
      ></b-spinner>
      {{ buttonText }}
    </b-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      status: 'unsaved',
    };
  },
  computed: {
    buttonText() {
      if (this.status === 'unsaved') return 'Save';
      else if (this.status === 'saving') return 'Saving';
      else return 'Saved';
    },
  },
  methods: {
    save() {
      this.status = 'saving';
      setTimeout(() => {
        this.status = 'saved';
      }, 2000);
    },
  },
};
</script>

We use the status data property to track the current save state, and we create a buttonText computed property to determine what the button label should be from status.

Using a spinner in a button.

Conclusion

A spinner is useful for indicating app operations in the process of being completed. In this article, we learned how to use the spinner component from Bootstrap Vue (b-spinner) to easily create and customize spinners.