CraZyCoDer
CraZyCoDer

Reputation: 429

V-select issue in Vuetify 3

I'm using Vuetify 3.0.0-beta.0 ~ for my project (because it is the only version that supports vue3), and having a bit weird issue

I want to implement the same thing as described there https://codepen.io/reijnemans/pen/vYNadMo?editors=1010 with v-select involved, so I was needed to use Vuetify

copied snippet

          <v-select
            :items="items"
            label="Standard"
          >
            <template v-slot:selection="{ item, index }">
              <img :src="item.image">{{ item.name }}</template>
            </template>
            <template v-slot:item="{ item }">
              <img :src="item.image">{{ item.name }}</template>
          </v-select>

My Component:


<template>
    <div class="resourceSelectors">
    
            <v-col cols="10" lg="4" class="mx-auto">

                  <div class="text-center">
                    <h2 class="indigo--text" style="margin-bottom: 30px">Some Test H2</h2>
                  </div>

                <v-col class="d-flex" cols="12" sm="6">
                    <v-select
                        :items="items"
                        label="Standard">
                        <template v-slot:selection="{ item }">
                        <img :src="item.image">{{ item.name }}
                        </template>

                        <template v-slot:item="{ item }">
                        <img :src="item.image">{{ item.name }}
                        </template>

                    </v-select>
                </v-col>
          </v-col>
  </div>

</template>

<script>

import { mapState } from "vuex";

/* eslint-disable */

export default {

  name: "testComponent",
  data() {
    return {
      // hardware Configuration Validation Rules

      items: [
      { name: 'Foo', image: 'https://www.gravatar.com/avatar/b17065ea1655f1e3283aac8d8fc16019?s=48&d=identicon&r=PG'},
      { name: 'Bar', image: 'https://www.gravatar.com/avatar/b17065ea1655f1e3283aac8d8fc16019?s=48&d=identicon&r=PG'},
      { name: 'Hoo', image: 'https://www.gravatar.com/avatar/b17065ea1655f1e3283aac8d8fc16019?s=48&d=identicon&r=PG'},
      { name: 'Coo', image: 'https://www.gravatar.com/avatar/b17065ea1655f1e3283aac8d8fc16019?s=48&d=identicon&r=PG'}],
}
}}

When I'm trying to run the above component I always get this weird error Failed setting prop "type" on <select>: value text is invalid. TypeError: Cannot set property type of #<HTMLSelectElement> which has only a getter,

Did anyone faced similar issue before?

Upvotes: 3

Views: 5198

Answers (2)

Tenarius
Tenarius

Reputation: 609

In Vuetify 3, you need some workarounds to style the items in v-select, because the item slot resets the entire styling.

You should use the menu-props, with it you can pass props through to the v-menu component. It accepts an object with anything from /api/v-menu. This allows you to close the field on click.

In the item slot, you should use a v-list-item with an @click property to set the model.

I made an example here with a selection of symbols:

<script setup>

    const symbols = [
        'ab-testing',
        'abacus',
        'account',
        'account-alert',
    ]

    const form = { symbol: '', }

</script>
<template>
    <v-select
        v-model="form.symbol"
        :items="symbols"
        label="Symbol"
        :prepend-inner-icon="'mdi-'+form.symbol"
        :menu-props="{
            closeOnClick: true,
            closeOnContentClick: true,
        }"
    >
        <template v-slot:selection="{ item, index }">
            {{ item.value }}
        </template>

        <template v-slot:item="{ item, index }">
            <v-list-item
                :title="item.title"
                :prepend-icon="'mdi-'+item.title"
                @click="form.symbol = item.title"
            >
            </v-list-item>
        </template>
    </v-select>
</template>

I hope it helps you.

Upvotes: 5

Alizadeh118
Alizadeh118

Reputation: 1054

I couldn't find correct solution but I just wanted to share what I did about scoped slot. I think we should use item.raw to access name and image. And the next problem is how to make it clickable to trigger select event that I didn't know yet :(

const { createApp } = Vue
const { createVuetify } = Vuetify
const vuetify = createVuetify()

const app = createApp({
  data() {
    return {
      value: null,
      items: [
        {
            name: 'Foo',
            image: 'https://www.gravatar.com/avatar/b17065ea1655f1e3283aac8d8fc16019?s=48&d=identicon&r=PG'
        },
        {
            name: 'Bar',
            image: 'https://www.gravatar.com/avatar/b17065ea1655f1e3283aac8d8fc16019?s=48&d=identicon&r=PG'
        },
        {
            name: 'Hoo',
            image: 'https://www.gravatar.com/avatar/b17065ea1655f1e3283aac8d8fc16019?s=48&d=identicon&r=PG'
        },
        {
            name: 'Coo',
            image: 'https://www.gravatar.com/avatar/b17065ea1655f1e3283aac8d8fc16019?s=48&d=identicon&r=PG'
        }
      ]
    }
  }
});

app.use(vuetify).mount('#app');
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>

<div id="app">
  <div class="resourceSelectors">
     <v-col cols="10" lg="4" class="mx-auto">
        <div class="text-center">
           <h2 class="indigo--text" style="margin-bottom: 30px">Some Test H2</h2>
        </div>
        <v-col class="d-flex" cols="12" sm="6">
           <v-select
            v-model="value"
            :items="items"
            item-title="name"
            item-value="name"
            label="Standard">
              <template v-slot:item="{item}">
              <v-list-item
                :prepend-avatar="item.raw.image"
                :title="item.raw.name"
              />
            </template>
         </v-select>
        </v-col>
     </v-col>
  </div>
</div>

Upvotes: 3

Related Questions