Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 25, 2021 08:45 pm GMT

Create wrapper components for Vuetify components

Vuetify is one of the most popular high-level UI component frameworks for Vue.js. It's based on Google Material Design and provides a wide range of high-quality pre-made components so that you can start building functional, accessible, and aesthetically pleasing web apps right away.

Although the built-in styling of Vuetify is great, your project might require different styling or you just want to customize Vuetify components to your liking.

Vue wrapper components to the rescue!

Wrapper components

A wrapper component is a custom component that "wraps" (hence the name) a native element or another component in order to add some custom functionality, styles, or anything else really.

Wrapper components are a great way to keep our codebase DRY by encapsulating functionality and/or styling that would otherwise have to be repeated.

Some of the advantages of wrapper components include:

  • Coherence between different parts of the application.
  • Simplified development by avoiding copy/paste.
  • Reduced bundle size.
  • Decouple the application from third-party components so that it's easier to switch from one component implementation to another.

Usecase

In this case, we are going to build a wrapper component for the Vuetify v-text-field component as an example, putting a label on top of the input and setting some default styles as well.

In the picture below:

  • On the left, there's the default Vuetify text field.
  • On the right, we see the custom text field that we are going to create using a wrapper component.Alt Text

Now that we know how our final result looks like, let's get to the code.

Our wrapper component

<template>  <div>    <label>{{ label }}</label>    <v-text-field v-bind="{ ...$attrs, ...commonAttrs }" v-on="$listeners">      <template v-for="(_, scopedSlotName) in $scopedSlots" #[scopedSlotName]="slotData">        <slot :name="scopedSlotName" v-bind="slotData" />      </template>      <template v-for="(_, slotName) in $slots" #[slotName]>        <slot :name="slotName" />      </template>    </v-text-field>  </div></template><script>export default {  inheritAttrs: false,  props: {    label: {      type: String,      default: ''    }  },  computed: {    commonAttrs() {      return {        label: '',        persistentHint: true,        outlined: true,        dense: true,        hideDetails: false,        class: {          'mt-1': this.$props.label        }      }    }  }}</script>

Breakdown of the most important parts.

  • Disable attribute inheritance
inheritAttrs: false

Setting inheritAttrs to false enables us to forward all attributes to v-text-field using $attrs.

  • Bind all parent-scope attribute bindings to the Vuetify component.
v-bind="{ ...$attrs, ...commonAttrs }"

In this case, we are also merging $attrs with our own attributes.

  • Forward all event listeners on the component to the Vuetify component.
v-on="$listeners"

All event listeners such as e.g @click, @input etc will propagate to the Vuetify component.

  • Pass down slots to the Vuetify component.
<template v-for="(_, scopedSlotName) in $scopedSlots" #[scopedSlotName]="slotData">  <slot :name="scopedSlotName" v-bind="slotData" /></template><template v-for="(_, slotName) in $slots" #[slotName]>  <slot :name="slotName" /></template>

Vuetify components provide slots for customization, we want them passed on from the wrapper component to the Vuetify component as well.

That's all there is to it!
You can now use the "component wrapper" technique to extend Vuetify components and also to build apps that are modular and more organized overall.

You can view the code used, in this CodeSandbox example.


Original Link: https://dev.to/kouts/create-wrapper-components-for-vuetify-components-2aah

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To