Using Vuetify Core Functionality - JessicaOPRD/docs GitHub Wiki

Mixins

Vuetify offers many compositional mixins that may be helpful to developers who already use the Vuetify library.

Why to use

🟢 Well-designed and get a lot of use

🟢 Standardized approach for many needed behaviors

🟢 Custom components built on them will be consistent with Vuetify library

🟢 Can import and use with ES5+ or Typescript

🟢 Good training wheels for learning re-usable Vue patterns

🟢 Handle many accessibility/Section 508 needs

Why not to use

🔴 Officially a private API that could change, so you will need to keep up with changes (or create own repo or copy into your project)

🔴 If unfamiliar with TypeScript, need to learn to read it or refer to compiled ES5 (which is not on GitHub?)

🟡 Vuetify source uses pattern that may be different to many Vue developers (render instead of <template>), but mixins can be used regardless of pattern in many cases

🔴 If using ES5 import, may add to your build size – I need to explore this more

Read more about Vue's render function and related features in the Vue docs.

Remember helpful base components if it makes more sense to use them

Remember also that Vuetify encapsulates helpful re-usable functionality in base components that can be wrapped and re-used to create more advanced components. These components are typically not used on their own, but are good building blocks. Using them circumvents accessing the internal private API directly. Some examples are:

Summary of helpful mixins

Mixin Factory? Dependencies Description
Groupable ✔️ Extends Registrable ⚪ Use on components that can be grouped such a VChip and VBtn ⚪ Manages isActive property and active classes for component (the child) ⚪ Registers component (the child) to a parent namespace
Registrable ⚪ Uses provide/inject Vue feature to register/unregister children to parent namespace ⚪ Simplifies parent-child communication that otherwise needs to happen through $parent, scoped slots, or possibly store
Selectable Extends VInput ⚪ Uses model Vue feature to describe model property and event (inputValue and change) ⚪ Use for elements that have a raw HTML value property that means something other than selected/unselected in group contexts (VCheckbox, VSwitch, VRadio) ⚪ Manages true/false value, color, creation of internal HTML checkbox, etc ⚪ Does not seem to work with Groupable, use Toggleable instead or see VRadio.
Toggleable ✔️ ⚪ Uses model Vue feature to describe model property and event (value and input by default) ⚪ Manages value Boolean update and emit ⚪ Also uses isActive to determine state from prop value ⚪ Used by VChip, VBtn, VListItem

Examples

You can extend existing components (see VCheckbox), however there is a learning curve to the rendering methods if you are accustomed to Vue or Angular templates. Mostly these make good examples for developing similar components from base mixins.

Component Dependencies Description
VInput Validatable ⚪ Creates and manages its own internalVaue based on an internal model event ('input' by default) ⚪ Creates and manages its own computedId (which I think is Vue's _uid per component instance) ⚪ Renders template
VItem Groupable mixin ⚪ Maintains internal isActive property managed by own toggle method ⚪ Maintains active class for item ⚪ Renders template
VItemGroup Groupable mixin (for register/unregister of child items) ⚪ Tracks and manages child items via registrable registration ⚪ Assesses value of child value and internalValue ⚪ Manages own group internalValue ⚪ Renders template

Basic extending

import VCheckbox from 'vuetify/es5/components/VCheckbox/VCheckbox'

export default VCheckbox.extend({
  name: 'op-jumbo-checkbox'
})

Registering child with a grouping parent

There are a few problematic or verbose ways to do this in Vue. The worst is probably to access the parent directly from the child:

mounted() {
  // Attempt to register this with a grouping parent automagically
  if (
    this.$parent &&
    this.$parent.$vnode.componentOptions.tag === 'op-photo-chip-group' &&
    isFunction(this.$parent.register)
  ) {
    this.$parent.register(this)
  }
},

This works but is fragile, and requires a direct parent-child relationship (the child cannot be further nested in other elements).

Another way is do manual registration by passing a registration function via scoped slots. There may be cases where this makes sense, but it does require awkward passing.

mounted() {
  // Allow manual registration signal
  this.$emit('register', this)
},

In the parent template:

<v-input :error-messages="errors">
  <slot :register="register"></slot>
</v-input>
register(item) {
  // Append to internal items array
}

In use:

<op-large-chip-group #default="{ register }">
  <op-large-chip @register="register($event)"></op-large-chip-group>
</op-large-chip-group>

Another way similar to the method above is to access the parent's API via $refs to invoke the register method.

The least messy way is to make use of Vue's provide/inject feature. Vuetify's Registrable mixin wraps this behavior. A namespace is provided by the parent:

provide() {
  return {
    photoChipGroup: this
  }
},

Which the child uses:

<script>
import { factory as GroupableFactory } from 'vuetify/es5/mixins/groupable'

export default {
  name: 'op-photo-chip',

  mixins: [GroupableFactory('photoChipGroup')],

  // Rest of component
}
</script>

Some naming conventions to use in your own components

Vuetify uses these internally, and it can be helpful to use similar conventions in custom components. I just love seeing how other developers name things. From the C# learning module: "A software developer once famously said 'The hardest part of software development is naming things.'"

Name of property or method Description
internalValue What I had come to call localValue. This value is maintained inside the component as local state and emitted externally when appropriate. In VInput is an alias for lazyValue, which is set from value during setup.
inputValue An alternative model value property name for selectable components where value has another meaning (such as "dog", "Silver Falls", etc). Compare to raw HTML value for checkboxes. This model indicates whether the component has been selected.
isActive Whether or not the component is active. Used in Toggleable components.
computedId Refers to unique internal ID for the component. May wrap the Vue _uid. This may also be the convention used to describe any computed value. I've often used translatedId or similar, but this makes good sense.
isFocused The same I had come to use to determine if an input is in focus.
⚠️ **GitHub.com Fallback** ⚠️