---
title: "Vue Timeline Task Checklist in Events Example | Mobiscroll"
component: "Timeline"
framework: "Vue"
library_version: "6.2.0"
url: "https://demo.mobiscroll.com/vue/timeline/check-list-tasks-within-events"
---

# Task Checklist in Events - Vue Timeline demo

Render a task checklist inside each Vue Timeline event card — row heights expand as the list grows, and a popup let users add new subtasks. For Vue and Nuxt.

- [Live demo](https://demo.mobiscroll.com/vue/timeline/check-list-tasks-within-events)
- [View SFC JS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue/tree/main/src/demos/eventcalendar/timeline/check-list-tasks-within-events)
- [View SFC TS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue-ts/tree/main/src/demos/eventcalendar/timeline/check-list-tasks-within-events)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/timeline/check-list-tasks-within-events.md), [jQuery](https://demo.mobiscroll.com/jquery/timeline/check-list-tasks-within-events.md), [Angular](https://demo.mobiscroll.com/angular/timeline/check-list-tasks-within-events.md), [React](https://demo.mobiscroll.com/react/timeline/check-list-tasks-within-events.md)

## Description

When there are subtasks related to work orders, it may be necessary to display them in the context of work order (or event). Subtasks can be rendered as a list with the possibility of adding new items using the [`Prompt`](https://demo.mobiscroll.com/vue/forms/alert-confirm-prompt) or more sophisticated modals even. The height of resources will dynamically increase depending on the height of the events/length of lists.

To allow dynamic changes in heights according to the length of subtask lists, `eventHeight: 'variable'` is used, along with [custom event content slot](https://mobiscroll.com/docs/vue/eventcalendar/api#slot-timelineEventContent) to maintain the appropriate theme styles.

## What this demo shows

- A desktop weekly timeline where days are arranged horizontally and resources are listed vertically on the left.
- **Header navigation** The month and year label in the top left opens date navigation, while the blue previous and next arrows and the Today button on the right make it easy to move between weeks and jump back to the current day.
- **Week view** The fixed strip below the header shows the selected week from Sunday to Saturday, using the `DD DDD MMM YYYY` date format, with the current date highlighted.
- **Resources** The left side shows six resources, each with a custom description displayed beneath the resource name.
- **Resource rows** Resource row height increases dynamically based on the height of the events and the length of their task lists.
- **Resource colors** Assigned projects use a consistent color per resource, so events for the same team share the same color.
- **Event cards** Events are rendered as large colored cards with the project name in bold, a task list below it, and a "+ Add task" action at the bottom.
- **Task entry** Clicking "+ Add task" opens a popup with an input field for the new task, plus Cancel and Ok buttons for dismissing or confirming the change.
- **Dynamic event height** Event card height updates as tasks are added to the card.
- **Event positioning** Events are positioned by assigned resource and by start and end date.
- **Event creation** New events can be created by double-clicking an individual resource row in the timeline or by clicking and dragging across a time range.
- **Event interaction** Events are highlighted on hover and show drag and resize handles for repositioning or changing duration.
- **Event selection** Clicking an event selects and highlights it.
- **Vertical scrolling** The resource area scrolls vertically so more resources can be displayed in the same timeline.

## Best for

- **Construction project planning** Scheduling resource-based assignments where each project or work order includes its own editable task list.
- **Installation workflows** Planning team assignments across a week while keeping installation tasks visible inside each scheduled event.
- **Maintenance projects** Managing work orders that need subtasks, changing durations, and resource-specific scheduling.
- **Field operations** Coordinating crews, teams, or resources across time while keeping task details attached to each assignment.
- **Task-driven project management** Using timeline events as containers for checklists that can grow as new tasks are added.

## API used in this demo

- [`cssClass`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-cssClass) - option
- [`view`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-view) - option
- [`data`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-data) - option
- [`resources`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-resources) - option
- [`dragToCreate`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-dragToCreate) - option
- [`clickToCreate`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-clickToCreate) - option
- [`dragToMove`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-dragToMove) - option
- [`dragToResize`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-dragToResize) - option
- [`extendDefaultEvent`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-extendDefaultEvent) - option
- [`close`](https://mobiscroll.com/docs/vue/notifications/prompt#event-onClose) - event
- [`close`](https://mobiscroll.com/docs/vue/notifications/toast#event-onClose) - event

## Code

### SFC JS

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

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

const myView = {
  timeline: {
    type: 'week',
    eventHeight: 'variable',
    eventDisplay: 'fill'
  }
}

const myResources = ref([
  {
    id: 1,
    name: 'Site Plumbing Squad',
    description:
      'Elite construction plumbers ensuring flawless pipeline installations on every site.',
    color: '#01adff'
  },
  {
    id: 2,
    name: 'Pipeline Builders',
    description: 'Constructing fluid pathways, one precision connection at a time.',
    color: '#239a21'
  },
  {
    id: 3,
    name: 'Blueprint Plumbers',
    description: 'Turning plans into precise pipelines with expert craftsmanship.',
    color: '#ff4600'
  },
  {
    id: 4,
    name: 'Site Supply Specialists',
    description: 'Delivering essential plumbing materials promptly to construction sites',
    color: '#4981d6'
  },
  {
    id: 5,
    name: 'Infrastructure Installers',
    description: ' Building the backbone of modern plumbing systems efficiently.',
    color: '#f1e920'
  },
  {
    id: 6,
    name: 'Steel Sinks Squad',
    description: 'Installing robust sinks for industrial and commercial settings.',
    color: '#f7961e'
  }
])

function handleDefaultEvent() {
  return {
    title: 'New Event',
    tasks: ['Default task']
  }
}

function handleClosePrompt(value) {
  if (value) {
    tempEvent.value.tasks.push(value)
    const index = myEvents.value.findIndex((event) => event.id === tempEvent.value.id)
    const newEventList = [...myEvents.value]
    newEventList.splice(index, 1, tempEvent.value)
    myEvents.value = newEventList
  }
  isPromptOpen.value = false
  toastMessage.value = 'Tasks updated for ' + tempEvent.value.title
  isToastOpen.value = true
}

function handleCloseToast() {
  isToastOpen.value = false
}

function addTask(event) {
  const ev = event.original
  tempEvent.value = ev
  promptTitle.value = 'Add new task to ' + ev.title
  isPromptOpen.value = true
}

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

<template>
  <MbscEventcalendar
    cssClass="mds-tasks-calendar"
    :view="myView"
    :data="myEvents"
    :resources="myResources"
    :dragToCreate="true"
    :clickToCreate="true"
    :dragToMove="true"
    :dragToResize="true"
    :extendDefaultEvent="handleDefaultEvent"
  >
    <template #resource="resource">
      <div class="mds-tasks-resource-name">{{ resource.name }}</div>
      <div class="mds-tasks-resource-description">{{ resource.description }}</div>
    </template>
    <template #timelineEventContent="event">
      <div class="mds-tasks-event-title">{{ event.title }}</div>
      <div class="mds-tasks-event-subtitle">Task list</div>
      <div class="mds-tasks-event-list">
        <div class="mds-tasks-event-list-item" v-for="task in event.original.tasks" :key="task">
          {{ task }}
        </div>
        <div class="mds-tasks-event-list-item mds-tasks-event-add" @click="addTask(event)">
          + Add task
        </div>
      </div>
    </template>
  </MbscEventcalendar>

  <MbscPrompt :title="promptTitle" :isOpen="isPromptOpen" @close="handleClosePrompt" />
  <MbscToast
    :isOpen="isToastOpen"
    :message="toastMessage"
    @close="handleCloseToast"
    :duration="3000"
  />
</template>

<style>
.mds-tasks-resource-name {
  padding: 15px 0 8px 0;
  font-size: 16px;
  font-weight: 700;
  line-height: 24px;
}

.mds-tasks-resource-description {
  font-size: 12px;
  font-weight: 400;
  line-height: 16px;
}

.mds-tasks-event-title {
  padding: 16px 8px 0 8px;
  white-space: normal;
  word-break: normal;
  line-height: 24px;
  font-size: 16px;
  font-weight: 700;
}

.mds-tasks-event-subtitle {
  font-weight: 600;
  font-size: 14px;
  padding: 8px 8px 0 8px;
}

.mds-tasks-event-list {
  margin: 8px 8px 16px;
  border-radius: 0.25em;
  background-color: #ffffff69;
}

.mds-tasks-event-list-item {
  padding: 8px;
  white-space: normal;
  font-size: 12px;
  line-height: 16px;
  color: #000;
  border-bottom: 1px solid #00000033;
  font-weight: 400;
}

.mds-tasks-event-add {
  padding-top: 4px;
  border-bottom: none;
  font-weight: 700;
}

.mds-tasks-event-add:hover {
  color: #0000ee;
  text-decoration: underline;
}

.mds-tasks-calendar .mbsc-timeline-row {
  height: 174px;
}

.mds-tasks-calendar .mbsc-schedule-event-inner {
  display: block;
  height: auto;
}
</style>
```

### SFC TS

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

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

const myView: MbscEventcalendarView = {
  timeline: {
    type: 'week',
    eventHeight: 'variable',
    eventDisplay: 'fill'
  }
}

const myResources = ref<MbscResource[]>([
  {
    id: 1,
    name: 'Site Plumbing Squad',
    description:
      'Elite construction plumbers ensuring flawless pipeline installations on every site.',
    color: '#01adff'
  },
  {
    id: 2,
    name: 'Pipeline Builders',
    description: 'Constructing fluid pathways, one precision connection at a time.',
    color: '#239a21'
  },
  {
    id: 3,
    name: 'Blueprint Plumbers',
    description: 'Turning plans into precise pipelines with expert craftsmanship.',
    color: '#ff4600'
  },
  {
    id: 4,
    name: 'Site Supply Specialists',
    description: 'Delivering essential plumbing materials promptly to construction sites',
    color: '#4981d6'
  },
  {
    id: 5,
    name: 'Infrastructure Installers',
    description: ' Building the backbone of modern plumbing systems efficiently.',
    color: '#f1e920'
  },
  {
    id: 6,
    name: 'Steel Sinks Squad',
    description: 'Installing robust sinks for industrial and commercial settings.',
    color: '#f7961e'
  }
])

function handleDefaultEvent() {
  return {
    title: 'New Event',
    tasks: ['Default task']
  }
}

function handleClosePrompt(value: string | null) {
  if (value) {
    tempEvent.value!.tasks.push(value)
    const index = myEvents.value.findIndex(
      (event: MbscCalendarEvent) => event.id === tempEvent.value!.id
    )
    const newEventList = [...myEvents.value]
    newEventList.splice(index, 1, tempEvent.value!)
    myEvents.value = newEventList
  }
  isPromptOpen.value = false
  toastMessage.value = 'Tasks updated for ' + tempEvent.value!.title
  isToastOpen.value = true
}

function handleCloseToast() {
  isToastOpen.value = false
}

function addTask(event: MbscCalendarEventData) {
  const ev = event.original!
  tempEvent.value = ev
  promptTitle.value = 'Add new task to ' + ev.title
  isPromptOpen.value = true
}

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

<template>
  <MbscEventcalendar
    cssClass="mds-tasks-calendar"
    :view="myView"
    :data="myEvents"
    :resources="myResources"
    :dragToCreate="true"
    :clickToCreate="true"
    :dragToMove="true"
    :dragToResize="true"
    :extendDefaultEvent="handleDefaultEvent"
  >
    <template #resource="resource">
      <div class="mds-tasks-resource-name">{{ resource.name }}</div>
      <div class="mds-tasks-resource-description">{{ resource.description }}</div>
    </template>
    <template #timelineEventContent="event">
      <div class="mds-tasks-event-title">{{ event.title }}</div>
      <div class="mds-tasks-event-subtitle">Task list</div>
      <div class="mds-tasks-event-list">
        <div class="mds-tasks-event-list-item" v-for="task in event.original.tasks" :key="task">
          {{ task }}
        </div>
        <div class="mds-tasks-event-list-item mds-tasks-event-add" @click="addTask(event)">
          + Add task
        </div>
      </div>
    </template>
  </MbscEventcalendar>

  <MbscPrompt :title="promptTitle" :isOpen="isPromptOpen" @close="handleClosePrompt" />
  <MbscToast
    :isOpen="isToastOpen"
    :message="toastMessage"
    @close="handleCloseToast"
    :duration="3000"
  />
</template>

<style>
.mds-tasks-resource-name {
  padding: 15px 0 8px 0;
  font-size: 16px;
  font-weight: 700;
  line-height: 24px;
}

.mds-tasks-resource-description {
  font-size: 12px;
  font-weight: 400;
  line-height: 16px;
}

.mds-tasks-event-title {
  padding: 16px 8px 0 8px;
  white-space: normal;
  word-break: normal;
  line-height: 24px;
  font-size: 16px;
  font-weight: 700;
}

.mds-tasks-event-subtitle {
  font-weight: 600;
  font-size: 14px;
  padding: 8px 8px 0 8px;
}

.mds-tasks-event-list {
  margin: 8px 8px 16px;
  border-radius: 0.25em;
  background-color: #ffffff69;
}

.mds-tasks-event-list-item {
  padding: 8px;
  white-space: normal;
  font-size: 12px;
  line-height: 16px;
  color: #000;
  border-bottom: 1px solid #00000033;
  font-weight: 400;
}

.mds-tasks-event-add {
  padding-top: 4px;
  border-bottom: none;
  font-weight: 700;
}

.mds-tasks-event-add:hover {
  color: #0000ee;
  text-decoration: underline;
}

.mds-tasks-calendar .mbsc-timeline-row {
  height: 174px;
}

.mds-tasks-calendar .mbsc-schedule-event-inner {
  display: block;
  height: auto;
}
</style>
```

## Implementation notes

- Use `type: 'week'` with `eventDisplay: 'fill'` and `eventHeight: 'variable'` so event rows grow automatically as subtasks are added.
- Give each event a custom `tasks` array of strings representing the subtask list. Use `extendDefaultEvent` to pre-populate newly created events with a default title and a starter task.
- Use `renderTimelineEventContent` (Angular: `timelineEventContentTemplate`, Vue: `#timelineEventContent` slot) to render the event body: show the event title, a "Task list" label, the current tasks as list items, and a "+ Add task" clickable item at the bottom.
- When the "+ Add task" item is clicked inside `renderTimelineEventContent`, open a `Prompt` dialog with a title referencing the event name. Pass the event reference to state so the correct event is updated on confirm.
- In the `Prompt` `onClose` handler, if the user entered a value, push it onto the event's `tasks` array, replace the event in the events list, and update state. Show a `Toast` confirming the update.
- Use `renderResource` (Angular: `resourceTemplate`, Vue: `#resource` slot) to display the resource name and a description line beneath it.
- Enable `clickToCreate`, `dragToCreate`, `dragToMove`, and `dragToResize` for full event management directly on the timeline.

## 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: [Work Order Assignment](https://demo.mobiscroll.com/vue/timeline/assign-unassign-work-orders-fixed-top-row.md) - Assign work orders to employees on a Vue Timeline — keep unassigned orders in a fixed top row while scrolling, and drag to assign without changing time.
- Next: [Dual Synchronized Flight Scheduling](https://demo.mobiscroll.com/vue/timeline/flight-scheduling-two-synchronized-timelines.md) - Use synchronized Vue Timeline views to build a flight scheduling UI — drag flights to assign them to aircraft, with fixed event times and conflict detection.
