---
title: "Vue Select Image & text Example | Mobiscroll"
component: "Select"
framework: "Vue"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/vue/select/image-text"
---

# Image & text - Vue Select demo

Vue select with custom item templates rendering in image & text. Build custom UI, not just plain text/value picker. For Vue and Nuxt.

- [Live demo](https://demo.mobiscroll.com/vue/select/image-text)
- [View SFC JS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue/tree/main/src/demos/pickers/select/image-text)
- [View SFC TS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue-ts/tree/main/src/demos/pickers/select/image-text)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/select/image-text.md), [jQuery](https://demo.mobiscroll.com/jquery/select/image-text.md), [Angular](https://demo.mobiscroll.com/angular/select/image-text.md), [React](https://demo.mobiscroll.com/react/select/image-text.md)

## Description

An image & text value picker can be easily implemented by building a [custom item template](https://demo.mobiscroll.com/vue/select/item-templating). Pass the items with its base properties, like `text` and `value` and all the custom properties needed to the [`data` array](https://mobiscroll.com/docs/vue/select/api#opt-data).

## What this demo shows

- Shows a select that lets users choose multiple options from a predefined list containing images and text.
- **Opening the picker** Focusing or clicking the input opens the picker below it.
- **Closing the picker** Clicking outside the picker closes it.
- **Option content** Each option displays an image or avatar alongside a person's name.
- **Hover state** Hovering over an option highlights it in the picker.
- **Selection** Selecting one or more options adds a checkmark to indicate that it is selected.
- **Scrolling** The picker supports scrolling through the full list of options.
- **Selected values** Selected options appear as chips inside the input.
- **Removing values** Each selected value can be removed individually using the close icon on its chip.

## Best for

- **Team member selection** Choose multiple people from a team directory using avatars and names for quick identification.
- **Participant assignment** Add several attendees, collaborators, or assignees to an item.
- **Contact selection** Select multiple recipients from a contact list where profile images help distinguish people with similar names.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/vue/select/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/vue/select/api#opt-themeVariant) - option
- [`data`](https://mobiscroll.com/docs/vue/select/api#opt-data) - option
- [`itemHeight`](https://mobiscroll.com/docs/vue/select/api#opt-itemHeight) - option
- [`selectMultiple`](https://mobiscroll.com/docs/vue/select/api#opt-selectMultiple) - option
- [`label`](https://mobiscroll.com/docs/vue/select/api#opt-label) - option
- [`display`](https://mobiscroll.com/docs/vue/select/api#opt-display) - option
- [`inputStyle`](https://mobiscroll.com/docs/vue/select/api#opt-inputStyle) - option
- [`labelStyle`](https://mobiscroll.com/docs/vue/select/api#opt-labelStyle) - option

## Code

### SFC JS

```vue
<script setup>
import { MbscPage, MbscSelect, setOptions } from '@mobiscroll/vue'
import { ref } from 'vue'

setOptions({
  theme: 'ios',
  themeVariant: 'light'
})

const myValue = ref(['42976', '47883'])
const myData = [
  {
    text: 'Barry Lyon',
    value: '42976',
    avatar: 'm1'
  },
  {
    text: 'Hortense Tinker',
    value: '45290',
    avatar: 'f1'
  },
  {
    text: 'Carl Hambledon',
    value: '76208',
    avatar: 'm2'
  },
  {
    text: 'Arlene Sharman',
    value: '47883',
    avatar: 'f2'
  },
  {
    text: 'Keila Delores',
    value: '33379',
    avatar: 'f3'
  },
  {
    text: 'Paula Bush',
    value: '16076',
    avatar: 'f4'
  },
  {
    text: 'Gene Cortez',
    value: '62551',
    avatar: 'm3'
  },
  {
    text: 'Pete Nichols',
    value: '20929',
    avatar: 'm4'
  }
]
</script>

<template>
  <MbscPage>
    <MbscSelect
      :data="myData"
      :itemHeight="50"
      :selectMultiple="true"
      v-model="myValue"
      label="Users"
      display="anchored"
      inputStyle="box"
      labelStyle="stacked"
      placeholder="Please select..."
    >
      <template #item="item">
        <div class="md-image-text-item">
          <img
            class="md-image-text-avatar"
            :src="'https://img.mobiscroll.com/demos/' + item.data.avatar + '.png'"
          />
          <div class="md-image-text-name">{{ item.display }}</div>
        </div>
      </template>
    </MbscSelect>
  </MbscPage>
</template>

<style>
.md-image-text-item {
  position: relative;
  padding: 15px 0 15px 50px;
  text-align: left;
  line-height: normal;
}

.md-image-text-avatar {
  width: 40px;
  height: 40px;
  position: absolute;
  left: 0;
  top: 5px;
}
</style>
```

### SFC TS

```vue
<script setup lang="ts">
import { MbscPage, MbscSelect, setOptions } from '@mobiscroll/vue'
import { ref } from 'vue'

setOptions({
  theme: 'ios',
  themeVariant: 'light'
})

const myValue = ref(['42976', '47883'])
const myData = [
  {
    text: 'Barry Lyon',
    value: '42976',
    avatar: 'm1'
  },
  {
    text: 'Hortense Tinker',
    value: '45290',
    avatar: 'f1'
  },
  {
    text: 'Carl Hambledon',
    value: '76208',
    avatar: 'm2'
  },
  {
    text: 'Arlene Sharman',
    value: '47883',
    avatar: 'f2'
  },
  {
    text: 'Keila Delores',
    value: '33379',
    avatar: 'f3'
  },
  {
    text: 'Paula Bush',
    value: '16076',
    avatar: 'f4'
  },
  {
    text: 'Gene Cortez',
    value: '62551',
    avatar: 'm3'
  },
  {
    text: 'Pete Nichols',
    value: '20929',
    avatar: 'm4'
  }
]
</script>

<template>
  <MbscPage>
    <MbscSelect
      :data="myData"
      :itemHeight="50"
      :selectMultiple="true"
      v-model="myValue"
      label="Users"
      display="anchored"
      inputStyle="box"
      labelStyle="stacked"
      placeholder="Please select..."
    >
      <template #item="item">
        <div class="md-image-text-item">
          <img
            class="md-image-text-avatar"
            :src="'https://img.mobiscroll.com/demos/' + item.data.avatar + '.png'"
          />
          <div class="md-image-text-name">{{ item.display }}</div>
        </div>
      </template>
    </MbscSelect>
  </MbscPage>
</template>

<style>
.md-image-text-item {
  position: relative;
  padding: 15px 0 15px 50px;
  text-align: left;
  line-height: normal;
}

.md-image-text-avatar {
  width: 40px;
  height: 40px;
  position: absolute;
  left: 0;
  top: 5px;
}
</style>
```

## Implementation notes

- `selectMultiple: true` (Angular `[selectMultiple]="true"`, Vue `:selectMultiple="true"`) switches the select into multi-select mode: each `data` item gets a checkmark toggle instead of single-select replace-on-pick behavior, and the bound value becomes an array of selected `value`s.
- `data` items carry the standard `text`/`value` pair plus a custom `avatar` field (e.g. `'m1'`, `'f2'`); any extra field beyond `text`/`value` is passed straight through to the item template via `item.data`.
- The avatar image isn't a built-in option - a custom item template builds its URL from `item.data.avatar` against a fixed `https://img.mobiscroll.com/demos/<avatar>.png` pattern and renders `item.display` (the resolved label) next to it.
- Custom item markup differs per framework: React passes a `renderItem` function prop returning JSX for `(item: MbscSelectItemData)`; Angular uses `[itemTemplate]="itemTemp"` with a named `<ng-template #itemTemp let-item>`; Vue uses the `#item` named slot on `<MbscSelect>`; JS/jQuery pass a `renderItem` function option returning an HTML string.
- `itemHeight={50}` must match the custom template's rendered row height so the scrollable list measures rows correctly.
- Value binding differs per framework: React controls `value`/`onChange` (the change event's `.value` is the full array of selected values, used to update local state); Angular/Vue use two-way binding (`[(ngModel)]="selected"` / `v-model="myValue"`) so the array updates automatically; JS/jQuery would read/set the array via `.getVal()`/`.setVal()` or the `value` option.
- Selected items render as removable chips inside the input; clicking a chip's close icon removes that value from the array (equivalent to unchecking the matching option in the picker) - this chip rendering is built into multi-select mode, not custom markup.
- `inputStyle`/`labelStyle`/`placeholder` are cosmetic input-decoration options and unrelated to the multi-select or templating behavior.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-vue.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config vue
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config vue --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/vue/getting-started/installation

## Related demos

- Previous: [Country Dropdown](https://demo.mobiscroll.com/vue/select/country-picker.md) - Vue Country picker scroller select for mobile/tablet. Alphabetical ordering, jump to value and filtering is supported.
- Next: [Multiline select](https://demo.mobiscroll.com/vue/select/multiple-lines.md) - Vue Select scroller style demo supporting long text rendered in multiple rows. With smooth scrolling and native look & feel.
