---
title: "Vue Event calendar Event Popover Example | Mobiscroll"
component: "Event calendar"
framework: "Vue"
library_version: "6.2.0"
url: "https://demo.mobiscroll.com/vue/eventcalendar/customize-event-popover"
---

# Event Popover - Vue Event calendar demo

Customize how events appear in the day popover of a Vue event calendar — use full custom layouts or add fields like assignee, location, and participants. For Vue and Nuxt.

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

## Description

The events listed in the popover can be customized in two ways:

- **Full event customization** *(like in this example)* - The calendar handles the rendering of events in the correct order. Styling the content, colors and everything else is your responsibility.
- **Content customization** - The calendar prints the `start` and `end` times, `allDay` and sets the appropriate `color`. Content like title and other fields can be shown.

You can provide styling to the `title` field and any other custom fields like `description`, `location`, `participants` ...

Create an event content template and pass it to the [`popoverEventContent`](https://mobiscroll.com/docs/vue/eventcalendar/api#slot-popoverEventContent) template. All original event fields along with computed fields like `isMultiDay`, `lastDay` are passed to the template. For a fully custom event rendering use the [`popoverEvent`](https://mobiscroll.com/docs/vue/eventcalendar/api#slot-popoverEvent) template.

If you add custom markup you will want to add styling too. Use the `popoverClass` under the `view` option to tell the calendar what CSS class it should append to the popover container so that you can write specific CSS rules.

## What this demo shows

- A mobile-style month event calendar with fully customized events shown in the popover.
- **Month grid** Days with scheduled events show a small marker below the day number.
- **Day hover state** Hovering over a day cell highlights the day number with a gray background.
- **Day selection** Clicking a day selects it and highlights the day number with a blue background.
- **Popover trigger** Clicking a day with an event marker opens a popover below the day cell.
- **Popover content** The popover lists the events scheduled for the selected day.
- **Custom event layout** Each customized event includes a colored leading line, event title, assignee image, assignee name, and time information.
- **All-day events** All-day events display an `All-day` label instead of a time range.
- **Timed events** Time-specific events display the start and end time.
- **Event action** Each event includes a blue `Add participant` button that highlights on hover and can be wired to a custom action.
- **Calendar navigation** The calendar supports horizontal drag navigation for moving between months.
- **Header controls** The header shows the current month and year on the left side, while the right side includes blue previous and next navigation arrows, and a `Today` button for returning to the current date.

## Best for

- **Assigned work and people-based scheduling** Displaying assignees, avatars, and event ownership directly in the popover list.
- **Actionable event lists** Adding buttons or other controls to day-level event previews so users can trigger follow-up actions from the popover.
- **Compact month browsing** Letting users scan a month quickly, spot days with events, and open a lightweight detail view only when needed.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-themeVariant) - option
- [`labels`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-labels) - option
- [`view`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-view) - option
- [`data`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-data) - option
- [`close`](https://mobiscroll.com/docs/vue/notifications/toast#event-onClose) - event

## Code

### SFC JS

```vue
<script setup>
import {
  getJson,
  MbscButton,
  MbscEventcalendar,
  MbscToast,
  setOptions
} from '@mobiscroll/vue'
import { onMounted, ref } from 'vue'

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

const myEvents = ref([])
const toastMessage = ref('')
const isToastOpen = ref(false)

const myView = {
  calendar: {
    labels: false,
    popover: true,
    popoverClass: 'custom-event-popover'
  }
}

function getParticipant(id) {
  switch (id) {
    case 1:
      return {
        img: 'https://img.mobiscroll.com/demos/m1.png',
        name: 'Barry L.'
      }
    case 2:
      return {
        img: 'https://img.mobiscroll.com/demos/f1.png',
        name: 'Hortense T.'
      }
    case 3:
      return {
        img: 'https://img.mobiscroll.com/demos/m2.png',
        name: 'Carl H.'
      }
    default:
      return {
        img: '',
        name: ''
      }
  }
}

function add(ev, data) {
  ev.stopPropagation()
  toastMessage.value = getParticipant(data.participant).name + "'s event clicked"
  isToastOpen.value = true
}

function handleToastClose() {
  isToastOpen.value = false
}

onMounted(() => {
  getJson(
    'https://trial.mobiscroll.com/custom-events/',
    (events) => {
      myEvents.value = events
    },
    'jsonp'
  )
})
</script>

<template>
  <MbscEventcalendar :view="myView" :data="myEvents">
    <template #popoverEventContent="data">
      <div>{{ data.title }}</div>
      <div class="md-custom-event-cont">
        <img class="md-custom-event-img" :src="getParticipant(data.original.participant).img" />
        <div class="mbsc-custom-event-name">
          {{ getParticipant(data.original.participant).name }}
        </div>
        <MbscButton
          className="md-custom-event-btn"
          color="primary"
          variant="outline"
          @click="add($event, data.original)"
        >
          Add participant
        </MbscButton>
      </div>
    </template>
  </MbscEventcalendar>
  <MbscToast :message="toastMessage" :isOpen="isToastOpen" @close="handleToastClose" />
</template>

<style>
.md-custom-event-img {
  width: 30px;
  height: 30px;
}

.mbsc-custom-event-name {
  padding: 0 10px;
}

.md-custom-event-cont {
  display: flex;
  align-items: center;
  padding-top: 10px;
  font-size: 13px;
}

.md-custom-event-btn.mbsc-button {
  position: absolute;
  right: 10px;
  bottom: 8px;
  line-height: 20px;
  padding: 0px 6px;
}

.custom-event-popover.mbsc-material .mbsc-popover-list .mbsc-event {
  padding: 10px 14px;
}

.custom-event-popover.mbsc-ios .mbsc-popover-list {
  width: 340px;
}

.custom-event-popover.mbsc-material .mbsc-popover-list {
  width: 320px;
}

.custom-event-popover.mbsc-windows .mbsc-popover-list {
  width: 340px;
}
</style>
```

### SFC TS

```vue
<script setup lang="ts">
import {
  getJson,
  MbscButton,
  MbscEventcalendar,
  MbscToast,
  setOptions
} from '@mobiscroll/vue'
import type { MbscCalendarEvent, MbscEventcalendarView } from '@mobiscroll/vue'
import { onMounted, ref } from 'vue'

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

const myEvents = ref<MbscCalendarEvent[]>([])
const toastMessage = ref<string>('')
const isToastOpen = ref<boolean>(false)

const myView: MbscEventcalendarView = {
  calendar: {
    labels: false,
    popover: true,
    popoverClass: 'custom-event-popover'
  }
}

function getParticipant(id: any) {
  switch (id) {
    case 1:
      return {
        img: 'https://img.mobiscroll.com/demos/m1.png',
        name: 'Barry L.'
      }
    case 2:
      return {
        img: 'https://img.mobiscroll.com/demos/f1.png',
        name: 'Hortense T.'
      }
    case 3:
      return {
        img: 'https://img.mobiscroll.com/demos/m2.png',
        name: 'Carl H.'
      }
    default:
      return {
        img: '',
        name: ''
      }
  }
}

function add(ev: any, data: any) {
  ev.stopPropagation()
  toastMessage.value = getParticipant(data.participant).name + "'s event clicked"
  isToastOpen.value = true
}

function handleToastClose() {
  isToastOpen.value = false
}

onMounted(() => {
  getJson(
    'https://trial.mobiscroll.com/custom-events/',
    (events: MbscCalendarEvent[]) => {
      myEvents.value = events
    },
    'jsonp'
  )
})
</script>

<template>
  <MbscEventcalendar :view="myView" :data="myEvents">
    <template #popoverEventContent="data">
      <div>{{ data.title }}</div>
      <div class="md-custom-event-cont">
        <img class="md-custom-event-img" :src="getParticipant(data.original.participant).img" />
        <div class="mbsc-custom-event-name">
          {{ getParticipant(data.original.participant).name }}
        </div>
        <MbscButton
          className="md-custom-event-btn"
          color="primary"
          variant="outline"
          @click="add($event, data.original)"
        >
          Add participant
        </MbscButton>
      </div>
    </template>
  </MbscEventcalendar>
  <MbscToast :message="toastMessage" :isOpen="isToastOpen" @close="handleToastClose" />
</template>

<style>
.md-custom-event-img {
  width: 30px;
  height: 30px;
}

.mbsc-custom-event-name {
  padding: 0 10px;
}

.md-custom-event-cont {
  display: flex;
  align-items: center;
  padding-top: 10px;
  font-size: 13px;
}

.md-custom-event-btn.mbsc-button {
  position: absolute;
  right: 10px;
  bottom: 8px;
  line-height: 20px;
  padding: 0px 6px;
}

.custom-event-popover.mbsc-material .mbsc-popover-list .mbsc-event {
  padding: 10px 14px;
}

.custom-event-popover.mbsc-ios .mbsc-popover-list {
  width: 340px;
}

.custom-event-popover.mbsc-material .mbsc-popover-list {
  width: 320px;
}

.custom-event-popover.mbsc-windows .mbsc-popover-list {
  width: 340px;
}
</style>
```

## Implementation notes

- Set `view: { calendar: { labels: false, popover: true, popoverClass: 'custom-event-popover' } }`: `labels: false` suppresses inline labels so only a dot marker appears; `popover: true` opens the event list on day click; `popoverClass` adds a custom CSS class to the popover container for targeted styling.
- Use `renderPopoverEventContent` (Angular: `popoverEventContentTemplate`, Vue: `popoverEventContent` slot) to customize the content of each event row in the popover while the calendar handles event ordering and the outer popover frame. The render function receives `data` with `data.title` and `data.original` for any custom event fields - this demo uses `data.original.participant` to look up an assignee name and avatar image. For full control over the outer event wrapper, use `renderPopoverEvent` (Angular: `popoverEventTemplate`, Vue: `popoverEvent` slot) instead.
- Add a `Button` inside the custom content with `color="primary"` and `variant="outline"`. Call `ev.stopPropagation()` in its click handler to prevent the calendar's `onEventClick` from firing, then show a `Toast` with the participant's name.
- Load events from a remote endpoint using `getJson` and assign them to `data`; for the imperative API, call `inst.setEvents(events)` in the callback.

## 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: [Custom Label Styling](https://demo.mobiscroll.com/vue/eventcalendar/customize-label-look-and-feel.md) - Fully customize event labels in the Vue event calendar — set colors, show timed-event dots, and include custom fields beyond the event title.
- Next: [Custom Header](https://demo.mobiscroll.com/vue/eventcalendar/customizing-header.md) - Customize the Vue event calendar header — rearrange navigation controls, toggle calendar/scheduler views or add any custom action.
