1

I use Vuetify but disabled the import of all icons since treeshaking wasn't working properly in Nuxt, instead I followed the advice and import them manually as stated in this thread: vuetifyjs: Adding only used icons to build

However, this means that a lot of components that require icons, e.g v-checkbox, v-select or v-combobox (which uses v-checkbox in their dropdown menus) need their icons added manually. Just using v-checkbox allows for :on-icon & :off-icon props to be used but I can't figure out how I'd reach them when the checkboxes are used by other components. I've been attempting to change the behaviour in both v-select and v-combobox.

This is as far as I got but clearly this doesn't add the checked icon, just the blank one.

<v-combobox outlined multiple chips v-model="select" :items="items">
    <template v-slot:item="{ item }">
       <v-icon>{{mdiCheckboxBlankOutline}}</v-icon>{{ item }}
   /template>
</v-combobox>

import { mdiCheckboxBlankOutline, mdiCheckboxMarked } from "@mdi/js";

Data(){
select: ["Stockholm"],
      items: [
        "Stockholm",
        "London",
      ],

}

My question is therefore, how can replicate the default checkbox behaviour for the combobox menu using imported icons? This thread seems to talk about it but never ends up showing a code example: https://github.com/vuetifyjs/vuetify/issues/10904 (Meaning it should look like this) enter image description here

Thorvald
  • 546
  • 6
  • 18

1 Answers1

2

You can use the item slot, where you are provided with the item, on and attrs object, to replicate the default behaviour.

You bind the on (events) and attrs (properties) objects to the custom list item, to send click events from your list item to combobox component.

Next you set the appropriate icon depending on the selected values. See the code below and the code sandbox.

<template>
  <v-app>
    <v-combobox
      label="Label"
      outlined
      multiple
      chips
      v-model="select"
      :items="items"
    >
      <template v-slot:item="{ item, on, attrs }">
        <v-list-item v-on="on" v-bind="attrs">
          <v-list-item-icon>
            <v-icon>
              {{ select.includes(item) ? checkIcon : uncheckIcon }}
            </v-icon>
          </v-list-item-icon>
          <v-list-item-content>
            <v-list-item-title v-text="item" class="text-left"></v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </template>
    </v-combobox>
  </v-app>
</template>

<script>
import { mdiCheckboxBlankOutline, mdiCheckboxMarked } from "@mdi/js";
export default {
  name: "HelloWorld",
  data() {
    return {
      items: ["One", "Two", "Three"],
      select: [],
      uncheckIcon: mdiCheckboxBlankOutline,
      checkIcon: mdiCheckboxMarked,
    };
  },
};
</script> 

CodeSandbox: https://codesandbox.io/s/recursing-banach-cb7ys?file=/src/components/HelloWorld.vue

Igor Moraru
  • 7,089
  • 1
  • 12
  • 24
  • That worked perfectly, any chance you could elaborate what binding attrs actually does? Essentially v-bind="attrs" sets up data binding to exactly what? – Thorvald Jun 01 '21 at 17:55
  • v-bind="attrs" basically sets the default styles for the selected list item (background, color), so you don't have to set them manually. – Igor Moraru Jun 01 '21 at 18:00