I'm using the Vuetify v-select component : https://vuetifyjs.com/en/components/selects/
I want to make select with image like this :
But i didn't found anything in the documentation
I'm using the Vuetify v-select component : https://vuetifyjs.com/en/components/selects/
I want to make select with image like this :
But i didn't found anything in the documentation
You have to use the item slot https://vuetifyjs.com/en/components/selects/#api
<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>
JS:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
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'}],
}),
})
JSFiddle: https://codepen.io/reijnemans/pen/vYNadMo?editors=1010
You can utilize the slots to fill image content onto select. I have used https://emoji-css.afeld.me/ to get the flags of countries.
Please see the sample Codepen: https://codepen.io/aaha/pen/ZEbRwpy?editors=1011 I couldn't fill the entire list of countries. It will be great if you can fill it and share, I could also use it somewhere. :D
<v-select
v-model="select"
:items="countries"
label="Select"
item-text="name"
>
<template v-slot:item="slotProps">
<i :class="['mr-2', 'em', slotProps.item.flag]"></i>
{{slotProps.item.name}}
</template>
</v-select>
data: {
select: null,
countries: [
{
name: "Andorra",
flag: "em-flag-ad"
},
{
name: "Arab Emirates",
flag: "em-flag-ae"
},
{
name: "Afghanistan",
flag: "em-flag-af"
},
{
name: "Antigua & Barbuda",
flag: "em-flag-ag"
},
{
name: "Albania",
flag: "em-flag-al"
},
{
name: "Anguilla",
flag: "em-flag-ai"
}
],
}
My own implementation of the component using <v-menu>
instead of <v-select>
so UI-wise it looks like the desired mock, not having all the UI of <v-select>
(like the bottom border, arrow, label and so on...)
Intro: I was asked to create a drop-down selector to change between languages. Selecting a different country would result in translating the web app with the corresponding selected language
TL;DR: Working pen: https://codepen.io/narxx/pen/JjRxjrQ (sorry for adding some additional styling, don't know why Vuetify's styling were not loaded and it looked really bad. On my project it looks amazing - I promise! :))
Template:
<v-menu offset-y>
<template v-slot:activator="{ on, attrs }">
<img
style="width: 32px"
class="d-block"
:src="getIcon()"
v-bind="attrs"
v-on="on"
/>
</template>
<v-list>
<v-list-item
v-for="(lang, index) in langs"
:key="index"
class="lang-menu-item"
>
<div class="d-flex align-center" @click="setLang(lang.value)">
<img style="width: 32px"
:src="lang.iconSrc"
class="mr-2 d-block"/>
<span>{{ lang.text }}</span>
</div>
</v-list-item>
</v-list>
</v-menu>
Some explanation on the template above:
Using <v-menu>
component allows us to manually create our own html as activator element, and for this example we want to show a flag of a country as the activator element.
Inside the <v-list>
we will be manually creating the items in the dropdown list by iterating over the list of languages (in langs
- see JS section).
JS:
data () {
return {
selectedLang: this.$i18n.locale,
langs: [
{
value: 'en',
text: 'English',
iconSrc: require('../assets/flags/eng.svg')
},
{
value: 'fr',
text: 'French',
iconSrc: require('../assets/flags/fr.svg')
},
],
}
},
computed: {
getIcon () {
return (item) => {
let image = item || this.selectedLang
let iconSrc = null
Object.keys(this.langs).forEach( (index) => {
if (this.langs[index].value === image) {
iconSrc = this.langs[index].iconSrc
}
})
return iconSrc
}
},
},
methods: {
setLang(lang) {
this.selectedLang = lang
this.$i18n.locale = lang
},
}
Some explanation on the code above
selectedLang
is the reactive variable we will change on selecting new language. Will be defaulted to whatever we currently have in the i18n
locale.
langs
: Given a list of objects containing the name of the language (the text that will be printed on screen in the drop-down list), the value which will be later on applied to the i18n
element to change the locale of the app, and a link to the image that represents the country. Can also be a base64 of svg, or class name for flag fonts or whatever.
getIcon
: Computed that will take a language value (code like en
or fr
..) and iterate through all languages in langs
and return the image that matches the given value to be shown in the dropdown list, and in the activator element.
setLang
: Method to change the language once a click event has been registered from the dropdown list, triggering this method. Of course you will be changing this method to do whatever you want in your project.
CSS (lang sass):
.lang-menu-item
cursor: pointer
&:hover
background-color: var(--v-primaryBG-base)
Just make the list look a bit nicer. The background color is the variable I use in my project for the default background of the entire app.
Vuetify 3.0.0 Update
in Vuetify 3.0.0 there is a breaking change, which cost me a lot of time because it's not documented. In this version the v-list-item is not generated with the former methods. So you have to create it by yourself. I think this will be fixed soon, however until then please use this method:
<v-select :items="mylist" item-title="name" item-value="id">
<template #item="{ item, props }">
<v-list-item v-bind="props">
<template #title>
<span><img :src="item.raw.image" /> {{item.raw.name}}</span>
</template>
</v-list-item>
</template>
</v-select>
data () {
return {
mylist: [
{id:0, image:"pic1.png", name:"Entry1"},
{id:1, image:"pic2.png", name:"Entry2"},
{id:2, image:"pic3.png", name:"Entry3"},
]
}
}