vuetify icon indicating copy to clipboard operation
vuetify copied to clipboard

Feat(VCalendar): Add eventHandlers and slots

Open blalan05 opened this issue 1 year ago • 9 comments
trafficstars

<template>
  <v-app>
    <v-main>
      <v-container>
        <v-row>
          <v-col>
            <v-select v-model="view" :items="['month', 'week', 'day']" label="View" />
          </v-col>
        </v-row>
        <v-row>
          <v-col>
            <v-switch v-model="showHeaderSlot" label="Header Slot" />
          </v-col>
          <v-col>
            <v-switch v-model="showTitleSlot" label="Title Slot" />
          </v-col>
          <v-col v-if="view === 'month'">
            <v-switch v-model="showDayTitleSlot" label="Day Title Slot" />
          </v-col>
          <v-col v-if="view === 'month'">
            <v-switch v-model="showDayBodySlot" label="Day Body Slot" />
          </v-col>
          <v-col v-if="view === 'month'">
            <v-switch v-model="showDayEventSlot" label="Day Event Slot" />
          </v-col>
          <v-col v-if="view === 'week'">
            <v-switch v-model="showIntervalTitleSlot" label="Interval Title Slot" />
          </v-col>
        </v-row>
        <v-row>
          <v-col>
            <v-calendar
              v-model="thisDate"
              :events="events"
              :view-mode="view"
              @click:date="clickedDate"
              @click:day="clickedDay"
              @click:event="clickedEvent"
              @click:interval="clickedInterval"
              @click:interval-date="clickedIntervalDate"
              @next="clickedNext"
              @prev="clickedPrev"
              @today="clickedToday"
            >
              <template v-if="showHeaderSlot" #header="{ title }">
                <span>{{ `Header ${title}` }}</span>
              </template>
              <template v-if="showTitleSlot" #title="{ title }">
                <span>Test {{ title }}</span>
              </template>
              <template v-if="showDayTitleSlot" #dayTitle="{ title }">
                {{ `Test ${title}` }}
              </template>
              <template v-if="showDayBodySlot" #dayBody="props">
                <span>{{ props }}</span>
              </template>
              <template v-if="showDayEventSlot" #dayEvent="{ event }">
                <v-sheet color="green">{{ event.title }}</v-sheet>
              </template>
              <template v-if="showIntervalTitleSlot" #intervalTitle="{ interval }">
                <span>Test {{ adapter.format(interval.start, 'hours24h') }}</span>
              </template>
            </v-calendar>
          </v-col>
        </v-row>
      </v-container>
    </v-main>
  </v-app>
</template>
<script setup>
  import { ref } from 'vue'
  import { useDate } from 'vuetify'

  const adapter = useDate()

  const thisDate = ref([new Date()])

  const events = ref([
    {
      start: new Date(),
      end: adapter.addHours(new Date(), 3),
      title: 'Event 1',
      color: 'green',
    },
  ])

  const view = ref('month')
  const showHeaderSlot = ref(false)
  const showTitleSlot = ref(false)
  const showDayTitleSlot = ref(false)
  const showDayBodySlot = ref(false)
  const showDayEventSlot = ref(false)
  const showIntervalTitleSlot = ref(false)

  // TODO: Not Working
  const clickedDate = function (data) {
    console.log('clicked Date', data)
  }

  const clickedDay = function (data) {
    console.log('clicked Day', data)
  }

  // TODO Not Working
  const clickedEvent = function (data) {
    console.log('clicked Event', data)
  }

  // TODO: Not Working
  const clickedInterval = function (data) {
    console.log('clicked interval', data)
  }

  const clickedIntervalDate = function (data) {
    console.log('clicked Interval Date', data)
  }

  const clickedPrev = function (data) {
    console.log('clicked prev', data)
  }

  const clickedNext = function (data) {
    console.log('clicked next', data)
  }

  const clickedToday = function (data) {
    console.log('clicked today', data)
  }
</script>

blalan05 avatar Apr 09 '24 02:04 blalan05

@nekosaur I started this code a few weeks ago, but wasn't able to get it working. I've tried to match what you PR'd in #19555. But I still don't see the slots overriding content. This PRs also addresses the missing event handling and more slots.

blalan05 avatar Apr 09 '24 02:04 blalan05

Is there support for <slot> in jsx?

nekosaur avatar Apr 10 '24 11:04 nekosaur

No.

KaelWD avatar Apr 10 '24 11:04 KaelWD

Here is my solution for #19624 : I just count the 'v-chip__content' (in month-day format) on the screen. When you fetch monthly data from the server, if you retrieve it sorted by date and time, you can know which event you are currently clicking on. This is the code to find the index of the event on the screen and print it with console.log. Just you know, my current code is a temporary solution until Vuetify further develops the data format for the calendar.

findElementIndex(event) {
      const clickedElement = event.target.closest('.v-chip__content');
      if (!clickedElement) {
        console.log('Clicked element is not a .v-chip__content element');
        return;
      }
      const allElements = Array.from(document.querySelectorAll('.v-chip__content'));
      const elementIndex = allElements.indexOf(clickedElement);
      console.log('Clicked .v-chip__content Element Index:', elementIndex);
    }

Jang-Eun-Ji avatar Apr 19 '24 01:04 Jang-Eun-Ji

I rebased and pushed some changes

nekosaur avatar Apr 27 '24 08:04 nekosaur

Any news on this merge request? It would be realy nice to have the event slot working again.

macdoy avatar Jul 04 '24 09:07 macdoy

Need help with events and torture testing slots.

blalan05 avatar Jul 12 '24 04:07 blalan05

Any news on this merge request?

DevilGeek avatar Sep 12 '24 14:09 DevilGeek