Custom tag design for TagsElement

Learn how to create a custom tag slot.

To add image to select, we can use option and tag slots:

template
<template>
  <Vueform>
    <TagsElement name="tags" :items="[
      { value: 'judy', name: 'Judy', image: 'https://vueform.com/images/random-user-3.jpg' },
      { value: 'jane', name: 'Jane', image: 'https://vueform.com/images/random-user-4.jpg' },
      { value: 'john', name: 'John', image: 'https://vueform.com/images/random-user-1.jpg' },
      { value: 'joe', name: 'Joe', image: 'https://vueform.com/images/random-user-2.jpg' }
    ]">
      <!-- Option -->
      <template v-slot:option="{ option }">
        <img class="rounded-full w-6 h-6 mr-1.5" :src="option.image">
        {{ option.name }}
      </template>
      <!-- Tag -->
      <template v-slot:tag="{ option, handleTagRemove, disabled }">
        <div :class="[
          'rounded-full bg-green-500 text-white text-sm font-semibold py-0.5 px-1.5 mr-1 mb-1 flex items-center whitespace-nowrap',
          disabled ? 'pr-2 opacity-50' : null,
        ]">
          <img class="rounded-full w-6 h-6 mr-1.5" :src="option.image">
          {{ option.name }}
          <span
            v-if="!disabled"
            class="flex items-center justify-center p-1 mx-0.5 rounded-full hover:bg-black hover:bg-opacity-10 group"
            @mousedown.prevent="handleTagRemove(option, $event)"
          >
            <span class="mask-bg mask-form-remove bg-current inline-block w-3 h-3"></span>
          </span>
        </div>
      </template>
    </TagsElement>
  </Vueform>
</template>
vue
<template>
  <Vueform :schema />
</template>

<script setup>
import { ref } from 'vue'

const TagsOptionImageSlot = {
  props: ['option'],
  render() {
    return h('div', { class: 'flex' }, [
      h('img', {
        class: 'rounded-full w-6 h-6 mr-1.5',
        src: this.option.image,
      }),
      this.option.name
    ])
  }
}

const TagsTagImageSlot = {
  props: ['option', 'handleTagRemove', 'disabled'],
  render() {
    return h('div', { 
      class: [
        'rounded-full bg-green-500 text-white text-sm font-semibold py-0.5 px-1.5 mr-1 mb-1 flex items-center whitespace-nowrap',
        this.disabled ? 'pr-2 opacity-50' : null
      ]
    }, [
      h('img', {
        class: 'rounded-full w-6 h-6 mr-1.5',
        src: this.option.image,
      }),
      this.option.name,
      !this.disabled ? h('span', {
        class: 'flex items-center justify-center p-1 mx-0.5 rounded-full hover:bg-black hover:bg-opacity-10 group',
        onMousedown: ($event) => {
          $event.preventDefault()
          this.handleTagRemove(this.option, $event)
        },
      }, [
        h('span', {
          class: 'mask-bg mask-form-remove bg-current inline-block w-3 h-3'
        })
      ]) : ''
    ])
  }
}

const schema = ref({
  tags: {
    type: 'tags',
    items: [
      { value: 'judy', name: 'Judy', image: '/images/random-user-3.jpg' },
      { value: 'jane', name: 'Jane', image: '/images/random-user-4.jpg' },
      { value: 'john', name: 'John', image: '/images/random-user-1.jpg' },
      { value: 'joe', name: 'Joe', image: '/images/random-user-2.jpg' }
    ],
    slots: {
      // Option
      option: TagsOptionImageSlot,
      // Tag
      tag: TagsTagImageSlot,
    }
  },
})
</script>
  
👋 Hire Vueform team for form customizations and developmentLearn more