Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending Vuetify Component

Tags:

vue.js

vuejs2

What is the best way to extend vue (vuetify) component v-select.

For example, I want to create <v-city></v-city> component that extends v-select with minimal props, async items loaded and one of items selected.

I've started with template

<template>
    <v-select
        :items="items"
        v-model="item"
        required
        return-object
        autocomplete
        item-text="name"
        item-value="id"
    ></v-select>
</template>

and script

<script>
    export default {
        name: 'v-city',
        data()
        {
            return {
                item: null,
                items: [],
                disabled: true
            };
        },
        created()
        {
            this.$http({
                method: 'GET',
                url: '/api.cities'
            })
                .then(response => this.items = response.data)
                .catch(console.warn);
        },
        methods: {},
        watch: {
            item(nv)
            {
                this.$emit('update', nv.id);
            }
        }
    };
</script>

And usage: <v-city @update="local.city = arguments[0]"></v-city>

What I want to archive is: <v-city v-model="local.city" label="Select city"></v-city>

like image 271
Đorđe Zeljić Avatar asked Jan 17 '18 22:01

Đorđe Zeljić


2 Answers

The best way to "extend" any component is to wrap it.

<template>
  <v-select v-bind="$attrs" v-on="$listeners">
    <!-- pass through scoped slots -->
    <template v-for="(_, name) in $scopedSlots" v-slot:[scopedSlotName]="data">
      <slot :name="name" v-bind="data" />
    </template>

    <!-- pass through normal slots -->
    <template v-for="(_, name) in $slots" v-slot:[name]>
      <slot :name="name" />
    </template>
  </v-select>
</template>

Prop defaults can just be added inline:

<v-select open-on-clear v-bind="$attrs" v-on="$listeners">

Some components (for example v-checkbox) also use a non-default prop and event for the model, so you may also need to set that for v-model to work properly:

<script>
  export default {
    model: {
      // These are the default values
      prop: 'value',
      event: 'input'
    }
  }
</script>
like image 169
Kael Watts-Deuchar Avatar answered Oct 16 '22 20:10

Kael Watts-Deuchar


To answer on my own question: use v-bind="this.$attrs" to get all "parent" attributes applied on child component. Also use this.$listeners.input to change value. Probably not ideal and only solution, but it works.

like image 21
Đorđe Zeljić Avatar answered Oct 16 '22 18:10

Đorđe Zeljić