tutorial

How to Create a Raw String in JavaScript

The static String raw() method is so named as we can use it to get the raw string form of template literals in JavaScript. This means that variable substitutions (e.g., ${num}) are processed but escape sequences like \n and \t are not.

For example:

const message = String.raw`\n is for newline and \t is for tab`;
console.log(message); // \n is for newline and \t is for tab

We can use a raw string to avoid the need to use double backslashes for file paths and improve readability.

For example, instead of:

const filePath = 'C:\\Code\\JavaScript\\tests\\index.js';
console.log(`The file path is ${filePath}`);    // The file path is C:\Code\JavaScript\tests\index.js

We can write:

const filePath = String.raw`C:\Code\JavaScript\tests\index.js`;
console.log(`The file path is ${filePath}`);    // The file path is C:\Code\JavaScript\tests\index.js

We can also use it to write clearer regular expressions that include the backslash character. For example, instead of:

const patternString = 'The (\\w+) is (\\d+)';
const pattern = new RegExp(patternString);

const message = 'The number is 100';
console.log(pattern.exec(message)); // ['The number is 100', 'number', '100']

We can write:

const patternString = String.raw`The (\w+) is (\d+)`;
const pattern = new RegExp(patternString);

const message = 'The number is 100';
console.log(pattern.exec(message)); // ['The number is 100', 'number', '100']

Vuetify Transition: How to Easily Create Transitions

Vuetify provides a wide range of built-in transitions we can apply to various elements to produce smooth animations that improve the user experience. We can use a transition by setting the transition prop on supported components, or wrapping the component in a transition component like v-expand-transition.

Vuetify Expand Transition

To apply the expand transition to an element, we wrap it in a v-expand-transition component. This transition is used in expansion panels and list groups.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-btn
        dark
        color="primary"
        @click="expand = !expand"
      >
        Expand Transition
      </v-btn>
      <v-expand-transition>
        <v-card
          v-show="expand"
          height="100"
          width="100"
          class="blue mx-auto mt-4"
        ></v-card>
      </v-expand-transition>
    </div>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      expand: false,
    };
  },
};
</script>
Creating an expand transition with Vuetify.

Expand X Transition

We can use v-expand-x-transition in place of v-expand-transition to apply the horizontal version of the expand transition.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-btn
        dark
        color="primary"
        @click="expand = !expand"
      >
        Expand X Transition
      </v-btn>
      <v-expand-x-transition>
        <v-card
          v-show="expand"
          height="100"
          width="100"
          class="blue mx-auto mt-4"
        ></v-card>
      </v-expand-x-transition>
    </div>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      expand: false,
    };
  },
};
</script>
Creating expand x transitions.

Vuetify FAB Transition

We can see an FAB transition in action when working with the v-speed-dial component. The target element rotates and scales up into view.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="fab-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Fab Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating an FAB transition with Vuetify.

Fade Transition

A fade transition acts on the opacity of the target element. We can create one by setting transition to fade-transition.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="fade-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Fade Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Create a fade transition.

Vuetify Scale Transition

Scale transitions act on the width and height of the target element. We can create them by setting transition to scale-transition.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scale-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scale Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating scale transitions with Vuetify.

Transition Origin

Components like v-menu have an origin prop that allows us to specify the point from which a transition should start. For example, we can make the scale transition start from the center point of both the x-axis and y-axis:

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu
        transition="scale-transition"
        origin="center center"
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scale Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
            @click="() => {}"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Specifying the origin of a transition.

Vuetify Scroll X Transition

Scroll X transitions work with both the opacity and horizontal position of the target element. It fades in while also moving along the x-axis.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scroll-x-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scroll X Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a scroll x transition with Vuetify.

Scroll X Reverse Transition

A reverse scroll x transition makes the element slide in from the right.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scroll-x-reverse-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scroll X Reverse Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a scroll x reverse transition.

Vuetify Scroll Y Transition

Scroll y transitions work similarly to scroll x transitions, but they act on the vertical position of the element instead.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scroll-y-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scroll Y Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating scroll y transitions with Vuetify.

Scroll Y Reverse Transition

Reverse scroll y transitions make the element slide in from the bottom.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scroll-y-reverse-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scroll Y Reverse Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a scroll y reverse transition.

Vuetify Slide X Transition

A slide x transition makes the element fade in while also sliding in along the x-axis. Unlike a scroll transition, the element slides out in the same direction it slid in from when closed.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="slide-x-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Slide X Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a slide x transition in Vuetify.

Slide X Reverse Transition

Reverse slide x transitions make the element slide in from the right.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="slide-x-reverse-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Slide X Reverse Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a slide x reverse transition.

Vuetify Slide Y Transition

Slide y transitions work like slide x transitions, but they move the element along the y-axis instead.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="slide-y-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Slide Y Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating slide y transitions in Vuetify.

Slide Y Reverse Transition

A reverse slide y transition makes the element slide in from the bottom.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="slide-y-reverse-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Slide Y Reverse Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a slide y reverse transition.

Conclusion

Vuetify comes with a built-in transition system that allows us to easily create smooth animations without writing our own CSS. We can scale, fade or translate a UI element with the various transitions available.

How to Use the JavaScript Nested Ternary Operator

As you might know, ternary operators in JavaScript are a single statement alternative to if...else statements frequently used to make code more concise and easier to understand. For example, we could have a function that returns “yes” or “no” depending on whether a number passed to it is odd or not.

JavaScript
function isOdd(num) { if (num % 2 === 1) return 'yes'; else return 'no'; }

We can refactor the isOdd function to use a one-line conditional statement like this:

JavaScript
function isOdd(num) { return num % 2 === 1 ? 'yes' : 'no'; }

Nested ternary operator in JavaScript

We can nest a ternary operator as an expression inside another ternary operator. We can use this to replace if…else if…else statements and switch statements. For example, we could have a piece of code that sets the English word for the numbers 1, 2, and 3 to a variable. With if...else:

JavaScript
let num = 1; let word; if (num === 1) word = 'one'; else if (num === 2) word = 'two'; else if (num === 3) word = 'three'; else num = 'unknown';

With switch...case:

JavaScript
let num = 1; let word; switch (num) { case 1: word = 'one'; break; case 2: word = 'two'; break; case 3: word = 'three'; break; default: word = 'unknown'; break; }

And now with nested ternary operators:

JavaScript
let num = 1; let word = num === 1 ? 'one' : num === 2 ? 'two' : num === 3 ? 'three' : 'unknown';

The above code example works exactly like the previous two and is less cluttered. Notice we are now able to declare and set the variable in the same statement with this nested ternary approach.

How to Truncate a String in JavaScript

Truncating a string sets a limit on the number of characters to display, usually to save space. We can truncate a string in JavaScript by writing a truncate function that takes the string as the first argument and the maximum number of characters as the second argument.

function truncate(str, length) {
  if (str.length > length) {
    return str.slice(0, length) + '...';
  } else return str;
}

The function truncates the string with the slice method if it has a character count greater than the specified length. Otherwise, it just returns the same string.

truncate('aaaaaa', 3)    // aaa...
truncate('abcde', 4)    // abcd...
truncate('aaaaaa', 8)    // aaaaaa

We can also write this function in one statement with the JavaScript ternary operator:

function truncate(str, length) {
  return str.length > length
    ? str.slice(0, length) + '...'
    : str;
}

This is a String object, so we can the substr method in place of slice to truncate the string:

function truncate(str, length) {
  return str.length > length
    ? str.substr(0, length) + '...'
    : str;
}

And we can use ES6 template strings instead of concatenation:

function truncate(str, length) {
  return str.length > length
    ? `${str.substr(0, length)}...`
    : str;
}

How to Use Vuetify Border Radius Classes

Vuetify comes with helper classes for easily customizing the border radius of an element without creating our own CSS. We’re going to explore these classes in this article.

Pill Class

We can use the rounded-pill class to create a rectangle with rounded corners.

<template>
  <v-app>
    <v-row
      class="text-center ma-2"
      justify="center"
    >
      <v-col cols="3">
        <div class="pa-4 primary white--text rounded-pill">
          .rounded-pill
        </div>
      </v-col>
    </v-row>
  </v-app>
</template>
Using the rounded-pill class.

Circle Class

The rounded-circle class creates a circle out of an element when applied.

<template>
  <v-app>
    <v-row
      class="text-center ma-2"
      justify="center"
    >
      <v-col cols="3">
        <div
          class="pa-7 primary rounded-circle d-inline-block"
        ></div>
        <div>.rounded-circle</div>
      </v-col>
    </v-row>
  </v-app>
</template>
Using the rounded-circle class.

Removing Border Radius

The rounded-0 class removes all border radius from an element. To remove border radius from a specific side, we can use a class of the format rounded-{side}-0, where side can be any of t, r, b, and l. For removing border radius from specific corners, we can use a class of the format rounded-{corner}-0 where corner can be any of tl, tr, br and bl.

<template>
  <v-app>
    <v-row
      justify="center"
      class="flex-grow-0 ma-4"
    >
      <v-col cols="12">
        <div
          class="pa-4 text-center primary white--text rounded-0"
          v-text="`.rounded-0`"
        ></div>
      </v-col>
      <v-col
        v-for="value in [
          't',
          'r',
          'b',
          'l',
          'tl',
          'tr',
          'br',
          'bl',
        ]"
        :key="value"
        sm="3"
      >
        <div
          :class="`pa-4 text-center primary white--text rounded-lg rounded-${value}-0`"
          v-text="`rounded-${value}-0`"
        ></div>
      </v-col>
    </v-row>
  </v-app>
</template>
Remove border radius from elements with Vuetify.

Rounding All Corners

We can use one of the rounded-sm, rounded, rounded-lg, or rounded-xl classes to apply border radius of varying sizes to all corners of an element.

<template>
  <v-app>
    <v-row class="ma-4 white--text">
      <v-col
        v-for="value in ['-sm', '', '-lg', '-xl']"
        :key="value"
        cols="3"
      >
        <div
          :class="`rounded${value}`"
          class="pa-4 text-center primary"
        >
          .rounded{{ value }}
        </div>
      </v-col>
    </v-row>
  </v-app>
</template>
Rounding all corners of an element.

Setting Border Radius By Side

To apply border radius to a specific side, we can use a helper class of the format rounded-{side} or rounded-{side}-{size}, where side can be one of t, r, b, and l, and size can be one of sm, lg, and xl.

<template>
  <v-app>
    <v-row class="ma-4 white--text">
      <v-col
        v-for="value in ['t', 'r', 'b', 'l']"
        :key="value"
        cols="3"
      >
        <div
          :class="`rounded-${value}-xl`"
          class="pa-4 text-center primary"
        >
          .rounded-{{ value }}-xl
        </div>
      </v-col>
    </v-row>
  </v-app>
</template>
Rounding by side with Vuetify border radius helpers.

Border Radius by Corner

To set the border radius of a specific corner, we can use a helper class of the format rounded-{corner} or rounded-{corner}-{size}, where corner can be any of tl, tr, br and bl, and size can be any of sm, lg, and xl.

<template>
  <v-app>
    <v-row class="ma-4 white--text">
      <v-col
        v-for="value in ['tl', 'tr', 'br', 'bl']"
        :key="value"
        cols="3"
      >
        <div
          :class="`rounded-${value}-xl`"
          class="pa-4 text-center primary"
        >
          .rounded-{{ value }}-xl
        </div>
      </v-col>
    </v-row>
  </v-app>
</template>
Rounding by corner with Vuetify border radius helpers.

With these helper classes from Vuetify, we can quickly set border radius of various sizes to specific sizes and corners of elements.

How to Use the Vuetify Footer Component

A footer is an area located at the bottom of a web page, after the main content. We can use it to display copyrights, creation dates, and top-level navigation links. In this article, we’re going to learn how to use the Vuetify footer component to easily create footers for our web pages.

Vuetify provides the v-footer component for creating a footer. It functions as a container in its simplest form.

<template>
  <v-app>
    <v-footer>
      <v-card
        tile
        flat
        width="100%"
        color="indigo"
        dark
        height="100px"
        class="d-flex align-center justify-center"
      >
        &copy; 2022 Coding Beauty
      </v-card>
    </v-footer>
  </v-app>
</template>
Creating a footer with the Vuetify footer component.

As you can see in the results of the previous example, the footer applies some padding to its content by default. We can use the padless prop to remove it:

<template>
  <v-app>
    <v-footer padless>
      <v-card
        tile
        flat
        width="100%"
        color="red accent-2"
        dark
        height="100px"
        class="d-flex align-center justify-center"
      >
        &copy; 2022 Coding Beauty
      </v-card>
    </v-footer>
  </v-app>
</template>
Creating a padless footer.

Setting the fixed prop to true will make the footer remain in the same position even if the user scrolls the page:

<template>
  <v-app>
    <v-container>
      <v-responsive height="800px">
        Lorem ipsum dolor sit amet consectetur adipisicing
        elit. Quisquam possimus aliquid nemo, modi harum rem
        laborum odio dicta, cupiditate accusantium debitis
        earum vero maxime consequatur nihil. Ut dolor esse
        eius. Lorem ipsum dolor sit amet consectetur,
        adipisicing elit. Non cum doloribus consectetur,
        libero rerum unde magnam beatae ullam asperiores,
        harum vero quasi minus animi omnis aliquam sequi,
        saepe nihil et!
      </v-responsive>
    </v-container>
    <v-footer
      fixed
      padless
    >
      <v-card
        tile
        flat
        width="100%"
        color="teal"
        dark
        height="100px"
        class="d-flex align-center justify-center"
      >
        &copy; 2022 Coding Beauty
      </v-card>
    </v-footer>
  </v-app>
</template>
Using the fixed prop of the Vuetify footer component.

We can place links in a footer so that the user can navigate to those locations from any web page.

<template>
  <v-app>
    <v-footer
      color="primary"
      dark
    >
      <v-row
        justify="center"
        class="my-4 text-center"
      >
        <v-col cols="12">
          <v-btn
            href="#"
            v-for="link in links"
            :key="link"
            text
            dark
            >{{ link }}
          </v-btn>
        </v-col>
        <v-col cols="12">&copy; 2022 Coding Beauty</v-col>
      </v-row>
    </v-footer>
  </v-app>
</template>

<script>
export default {
  data: () => {
    return { links: ['Home', 'Blog', 'About'] };
  },
};
</script>
A footer with links.

Here’s a footer with social media links and some text before the copyright:

<template>
  <v-app>
    <v-footer
      color="green"
      dark
    >
      <v-row
        justify="center"
        class="my-4 text-center"
      >
        <v-col cols="12"
          >Lorem ipsum dolor sit amet consectetur
          adipisicing elit.</v-col
        >
        <v-col cols="12">
          <v-btn
            v-for="icon in icons"
            :key="icon"
            text
            dark
          >
            <v-icon>{{ icon }}</v-icon>
          </v-btn>
        </v-col>
        <v-col
          cols="12"
          class="align-center"
          >&copy; 2022 Coding Beauty</v-col
        >
      </v-row>
    </v-footer>
  </v-app>
</template>

<script>
export default {
  data: () => {
    return {
      icons: [
        'mdi-facebook',
        'mdi-twitter',
        'mdi-instagram',
        'mdi-youtube',
      ],
    };
  },
};
</script>
Adding social links in a Vuetify footer component.

Conclusion

Footers can display general information we want to be accessible from any web page of a website. We can use the Vuetify footer component (v-footer) to create them.

How to Use Vuetify Elevation Helpers

Elevation provides important visual cues about the relative distance or depth between two surfaces along the z-axis. Vuetify provides utility classes and props that allow us to easily set the elevation of an element without using creating custom CSS styles.

An elevation helper will customize the shadow elevation of an element when applied. There is a total of 25 elevation levels:

<template>
  <v-app>
    <v-container class="ma-4">
      <v-row justify="center">
        <v-col
          v-for="n in 25"
          :key="n"
          cols="auto"
        >
          <v-card
            :elevation="n - 1"
            height="100"
            width="100"
            color="grey lighten-3"
          >
            <v-row
              class="fill-height"
              align="center"
              justify="center"
              v-text="n - 1"
            ></v-row>
          </v-card>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>
Using Vuetify elevation helpers.

Prop Based Elevation in Vuetify

A lot of Vuetify components have an elevation prop for easily setting the elevation.

In the code example below, we use the v-hover component and the v-card elevation prop to change the shadow elevation when the user hovers over the card with the mouse:

<template>
  <v-app>
    <v-hover>
      <template v-slot:default="{ hover }">
        <v-card
          :elevation="hover ? 24 : 6"
          class="pa-6 ma-4"
        >
          Prop based elevation
        </v-card>
      </template>
    </v-hover>
  </v-app>
</template>
Prop based elevation in Vuetify.

Class Based Elevation in Vuetify

For an element without an elevation prop, we can apply one of the elevation helper classes on it to customize the elevation. The classes are of the format elevation-{value}, where value is the elevation level.

<template>
  <v-app>
    <v-hover>
      <template v-slot:default="{ hover }">
        <div
          class="pa-6 ma-4"
          :class="`elevation-${hover ? 24 : 6}`"
        >
          Class based elevation
        </div>
      </template>
    </v-hover>
  </v-app>
</template>
Class based elevation in Vuetify.

Conclusion

Vuetify provides elevation helpers that let us control the relative depth between two surfaces along the z-axis. We can do this by setting the elevation prop on supported components, or applying one of the elevation utility classes.

Vue Event Handling: A Complete Guide

We listen for events in an application in order to perform certain actions when they occur. For example, we can display content or fetch data when a button is clicked, a key is pressed, a text input value is changed, and so on. In this article, we’re going to learn how to handle events in Vue apps to enable interactivity.

Listening for Events in Vue

To listen for an event, we pass the handler to a v-on directive attached to an element, for example:

<button v-on:click="handler">Click me</button>

We can also use the @ symbol for a shorter syntax:

<button @click="handler">Click me</button>

There are two types of event handlers in Vue: inline handlers and method handlers.

Inline Event Handlers

To create an inline event handler, we pass inline JavaScript that will be executed when the event is triggered. For example:

<template>
  <p>Count: {{ count }}</p>
  <button @click="count++">Add 1</button>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
};
</script>

Method Event Handlers

Method event handlers are what we use when we have more complex logic spanning multiple lines of code. We pass the name of a method defined on a Vue component to use it to handle the event.

For example:

<template>
  Count: {{ count }}
  <br />
  <button @click="increment">Add 1</button>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increment() {
      this.count++;
      if (this.count % 5 === 0) {
        alert(`${this.count} is divisible by 5.`);
      }
    },
  },
};
</script>

Calling Methods in Inline Handlers

We can also call a method in an event handler directly. This is useful for passing arguments.

<template>
  <p>Count: {{ count }}</p>
  <button @click="increment(2)">Add 2</button>
  <button @click="increment(3)">Add 3</button>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increment(amount) {
      this.count += amount;
      if (this.count % 5 === 0) {
        alert(`${this.count} is divisible by 5.`);
      }
    },
  },
};
</script>

Accessing Event Arguments in Event Handlers

When the name of a method is passed directly, the DOM event object associated with the event will be passed to the first parameter of the method:

<template>
  <button
    id="btn-1"
    @click="handleClick"
  >
    Button 1
  </button>
</template>

<script>
export default {
  methods: {
    handleClick(event) {
      const target = event.target;
      alert(`Button with ID ${target.id} clicked`);
    },
  },
};
</script>

We can also use an inline arrow function to access this event object:

<template>
  <button
    id="btn-1"
    @click="(event) => handleClick('Peter', event)"
  >
    Button 1
  </button>
</template>

<script>
export default {
  methods: {
    handleClick(username, event) {
      const target = event.target;
      alert(
        `${username} clicked the button with ID ${target.id}`
      );
    },
  },
};
</script>

Or we could pass the special $event variable when calling the method from the inline handler:

<template>
  <button
    id="btn-1"
    @click="handleClick('Peter', $event)"
  >
    Button 1
  </button>
</template>

<script>
export default {
  methods: {
    handleClick(username, event) {
      const target = event.target;
      alert(
        `${username} clicked the button with ID ${target.id}`
      );
    },
  },
};
</script>

Vue Event Modifiers

Vue provides event modifiers that allow us to separate our data logic from event-related logic. For example, the .prevent event modifier eliminates the need to call event.preventDefault() in the event handler method:

<template>
  <form @submit.prevent="onSubmit">
    <input
      name="email"
      type="email"
      placeholder="Email"
    />
    <button type="submit">Sign up</button>
  </form>
</template>

<script>
export default {
  methods: {
    onSubmit() {
      alert('Signed up successfully.');
    },
  },
};
</script>

Similarly, the .stop event modifier removes the need to call event.stopPropagration() in an event method handler:

<template>
  <button
    id="outer-btn"
    @click="handleOuterButtonClick"
  >
    Outer button
    <button
      id="inner-btn"
      @click.stop="handleInnerButtonClick"
    >
      Inner button
    </button>
  </button>
  <p>{{ message1 }}</p>
  <p>{{ message2 }}</p>
</template>

<script>
export default {
  data() {
    return {
      message1: '',
      message2: '',
    };
  },
  methods: {
    handleOuterButtonClick() {
      this.message2 = 'Outer button clicked';
    },
    handleInnerButtonClick() {
      this.message1 = 'Inner button clicked.';
    },
  },
};
</script>
Handling an event in Vue with the .stop modifier.

Here is a list of the common event modifiers in Vue:

  • .stop
  • .prevent
  • .self
  • .capture
  • .once
  • .passive

Chained Event Modifiers

We can chain event modifiers in Vue:

<a @click.stop.prevent="handleLink1Click"></a>
  
<a @click.once.prevent="handleLink2Click"></a>

Key modifiers

It’s common to check for specific keys when listening for keyboard events. Vue provides key modifiers for this.

For example, we can listen just for the “Enter” key

<input @keyup.enter="handleSubmit" />

We can use any valid key names exposed through KeyboardEvent.key as modifiers by converting them to kebab-case:

<input @keyup.page-down="handlePageDown" />

Key Aliases

Vue provides aliases for the most frequently used keys:

  • .enter
  • .tab
  • .delete (captures both "Delete" and "Backspace" keys)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

System Modifier Keys

Applying system key modifiers to key events will only trigger the event when the corresponding modifier key is pressed.

<!-- Ctrl + Enter -->
<input @keyup.ctrl.enter="clearTextField" />

<!-- Ctrl + Click -->
<div @click.ctrl="handleCtrlClick">Do something</div>

Exact Modifier

The .exact modifier lets us control the exact combination of system modifiers needed to trigger an event:

<!-- this will fire even if Alt or Shift is also pressed -->
<button @click.ctrl="handleClick">Button</button>

<!-- this will only fire when Ctrl and no other keys are pressed -->
<button @click.ctrl.exact="handleCtrlClick">Button</button>

<!-- this will only fire when no system modifiers are pressed -->
<button @click.exact="handleClick">Button</button>

Mouse Button Modifiers

Mouse button event modifiers will only call the event handlers for specific buttons. They are:

  • .left
  • .middle
  • .right
<button @click.left="handleLeftClick">Button</button>

<button @click.middle="handleMiddleClick">Button</button>

<button @click.right="handleRightClick">Button</button>

Conclusion

We can listen for events in Vue by passing inline code or a method handler to the v-on directive for the event. We can apply various modifiers to an event to further customize event trigger conditions.

How to Use Vue Methods: An Easy Guide

A Vue method is a function associated with every Vue instance and created with the methods property. We can use them to perform certain actions when the user interacts with an element, like clicking on a button, or entering data into a text input. Read on to find out more about how to define and use Vue methods.

Creating a Vue Method

To create a method, we assign an object to the method property of the Vue instance. Each key of the object passed corresponds to a method name.

<script>
export default {
  methods: () => ({
    handleClick: () => {
      alert('You clicked the button.');
    },
    handleChange: () => {
      console.log('Text input changed');
    },
  }),
};
</script>

This is JavaScript, so we can use the shorter method definition syntax introduced in ES 2015:

<script>
export default {
  methods: {
    handleClick() {
      alert('You clicked the button.');
    },
    handleInput() {
      console.log('Text input changed');
    },
  },
};
</script>

Calling Methods

To handle an event with a method, we pass it to a v-on directive attached to an element. For example:

<template>
  <div>
    <button v-on:click="handleClick">Click me</button>
    <input v-on:input="handleInput" />
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      alert('You clicked the button.');
    },
    handleInput() {
      console.log('Text input changed');
    },
  },
};
</script>

We can also use the @ symbol for a shorter syntax:

<template>
  <div>
    <button @click="handleClick">Click me</button>
    <input @input="handleInput" />
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      alert('You clicked the button.');
    },
    handleInput() {
      console.log('Text input changed');
    },
  },
};
</script>

Accessing Data from Vue Methods

We can access a data property with this.{propertyName}, where propertyName is the name of one of the properties returned from the data() method. For example:

<template>
  <div>Num: {{ num }}</div>
  <button @click="addOne">Add 1</button>
</template>

<script>
export default {
  data() {
    return {
      num: 0,
    };
  },
  methods: {
    addOne() {
      this.num++;
    },
  },
};
</script>
Accessing data from Vue JS methods.

Passing Parameter Values to Vue Methods

Vue methods can accept arguments like normal JavaScript functions. We can pass arguments by calling the method directly in the template with the parameter values:

<template>
  <div>Number: {{ num }}</div>
  <button @click="add(5)">Add 5</button>
</template>

<script>
export default {
  data() {
    return {
      num: 0,
    };
  },
  methods: {
    add(amount) {
      this.num += amount;
    },
  },
};
</script>
Passing parameter values to Vue JS methods

Conclusion

We can define methods on a Vue instance by passing an object to the methods property. Vue methods are similar to JavaScript functions and allow us to add interactivity to our Vue apps.

How to Use the Vuetify Bottom Sheet Component

A bottom sheet is a customized v-dialog that is anchored to the bottom of the screen, like a v-bottom-navigation. They are primarily used on mobile and can contain supplementary information and actions. In this article, we’re going to learn how to easily create and customize bottom sheets with the Vuetify bottom sheet component.

The Vuetify Bottom Sheet Component (v-bottom-sheet)

Vuetify provides the v-bottom-sheet component for creating a bottom sheet. Like v-dialog, this component comes with an activator slot that we can use to set a button that will open the sheet when clicked.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet v-model="sheet">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sheet: false,
  }),
};
</script>

<style>
html {
  overflow-y: auto !important;
}
</style>
Creating a bottom sheet with Vuetify.

Hide Overlay

v-bottom-sheet comes with a hide-overlay prop that will remove the overlay when set to true.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet
        v-model="sheet"
        hide-overlay
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet.</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sheet: false,
  }),
};
</script>

<style>
html {
  overflow-y: auto !important;
}
</style>
Using the hide-overlay prop of the Vuetify bottom sheet component.

Vuetify Bottom Sheet v-model

We can set up a two-way binding between the value of the v-bottom-sheet and a variable. We can then use this variable to open/close the sheet or to display certain content conditionally.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <div class="mb-4">
        The bottom sheet is {{ sheet ? 'open' : 'closed' }}
      </div>
      <v-bottom-sheet
        v-model="sheet"
        hide-overlay
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sheet: false,
  }),
};
</script>

<style>
html {
  overflow-y: auto !important;
}
</style>
Using v-model on a bottom sheet component.

Persistent Bottom Sheets

By default, an open bottom sheet closes when another element is clicked:

The bottom sheet closes when another element is clicked.

We can prevent this by setting the persistent prop to true on the v-bottom-sheet:

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet
        v-model="sheet"
        persistent
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet.</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sheet: false,
  }),
};
</script>

<style>
html {
  overflow-y: auto !important;
}
</style>
Using the persistent prop of the Vuetify bottom sheet component.

Vuetify Bottom Sheet Inset

The inset prop reduces the maximum width of the v-bottom-sheet to 70% on larger screens. We can also use the width prop to reduce the width manually.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet
        v-model="sheet"
        inset
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet.</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sheet: false,
  }),
};
</script>

<style>
html {
  overflow-y: auto !important;
}
</style>
Using the inset prop of the Vuetify bottom sheet component.

Creating an “Open In” Component

We can combine a functional list and bottom sheet to create an “open in” component.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet v-model="sheet">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="green"
            dark
          >
            Open in
          </v-btn>
        </template>
        <v-list>
          <v-subheader>Open in</v-subheader>
          <v-list-item
            v-for="(app, i) in apps"
            :key="i"
            @click="sheet = false"
          >
            <v-list-item-title>{{ app }}</v-list-item-title>
          </v-list-item>
        </v-list>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sheet: false,
    apps: ['Firefox', 'Chrome', 'Edge', 'Opera'],
  }),
};
</script>

<style>
html {
  overflow-y: auto !important;
}
</style>
Creating an "open in" component with a bottom sheet and a list.

Conclusion

Bottom sheets are anchored to the bottom of the screen and can be used to display supplementary content. Vuetify provides the Vuetify bottom sheet component (v-bottom-sheet) for creating and customizing them.