Show quick info template in Vue Schedule component

11 Jun 202424 minutes to read

This demo showcases the quick popups for cells and appointments with the customized templates.

<template>
  <div id='app'>
    <div id='container'>
      <ejs-schedule ref='scheduleObj' :height='height' :width='width' :views='views' :selectedDate='selectedDate'
        :eventSettings='eventSettings' :quickInfoTemplates='quickInfoTemplates'>
        <e-resources>
          <e-resource field="RoomId" title="Room Type" name="MeetingRoom" textField="Name" idField="Id"
            colorField="Color" :dataSource="roomData"></e-resource>
        </e-resources>
        <template v-slot:headerTemplate="{ data }">
          <div class="quick-info-header">
            <div class="quick-info-header-content" v-if="data.elementType == 'cell'"
              :style="{ 'align-items': 'center', 'color': '#919191' }">
              <div class="quick-info-title"></div>
              <div class="duration-text"></div>
            </div>
            <div class="quick-info-header-content" v-else
              :style="{ 'background': getHeaderStyles(data), 'color': '#FFFFFF' }">
              <div class="quick-info-title"></div>
              <div class="duration-text"></div>
            </div>
          </div>
        </template>
        <template v-slot:contentTemplate="{ data }">
          <div class="quick-info-content">
            <div class="e-cell-content" v-if="data.elementType === 'cell'">
              <div class="content-area"><ejs-textbox ref="titleObj" id="title" placeholder="Title"></ejs-textbox></div>
              <div class="content-area"><ejs-dropdownlist ref="eventTypeObj" id="eventType" :dataSource="roomData"
                  :index="0" :fields="fields" popupHeight="200px" placeholder="Choose Type"></ejs-dropdownlist></div>
              <div class="content-area"><ejs-textbox ref="notesObj" id="notes" placeholder="Notes"></ejs-textbox></div>
            </div>
            <div class="event-content" v-else>
              <div class="meeting-type-wrap"><label>Subject</label>:<span></span></div>
              <div class="meeting-subject-wrap"><label>Type</label>:<span></span></div>
              <div class="notes-wrap"><label>Notes</label>:<span></span></div>
            </div>
          </div>
        </template>
        <template v-slot:footerTemplate="{ data }">
          <div class="quick-info-footer">
            <div class="cell-footer" v-if="data.elementType === 'cell'">
              <ejs-button id="more-details" cssClass="e-flat" content="More Details"
                v-on:click="buttonClickActions"></ejs-button>
              <ejs-button id="add" cssClass="e-flat" content="Add" :isPrimary="true"
                v-on:click="buttonClickActions"></ejs-button>
            </div>
            <div class="event-footer" v-else>
              <ejs-button id="delete" cssClass="e-flat" content="Delete" v-on:click="buttonClickActions"></ejs-button>
              <ejs-button id="more-details" cssClass="e-flat" content="More Details" :isPrimary="true"
                v-on:click="buttonClickActions"></ejs-button>
            </div>
          </div>
        </template>
      </ejs-schedule>
    </div>
  </div>
</template>
<script setup>
import { provide, ref } from "vue";
import { ScheduleComponent as EjsSchedule, ResourcesDirective as EResources, ResourceDirective as EResource, Day, Week, WorkWeek, Month, Agenda } from '@syncfusion/ej2-vue-schedule';
import { extend, Internationalization } from "@syncfusion/ej2-base";
import { ButtonComponent as EjsButton } from "@syncfusion/ej2-vue-buttons";
import { DropDownListComponent as EjsDropdownlist } from "@syncfusion/ej2-vue-dropdowns";
import { TextBoxComponent as EjsTextbox } from "@syncfusion/ej2-vue-inputs";
import { quickInfoData } from './datasource.js';

const scheduleObj = ref(null);
const resourceData = [
  { Name: "Jammy", Id: 1, Capacity: 20, Color: "#ea7a57", Type: "Conference" },
  { Name: "Tweety", Id: 2, Capacity: 7, Color: "#7fa900", Type: "Cabin" },
  { Name: "Nestle", Id: 3, Capacity: 5, Color: "#5978ee", Type: "Cabin" },
  { Name: "Phoenix", Id: 4, Capacity: 15, Color: "#fec200", Type: "Conference" },
  { Name: "Mission", Id: 5, Capacity: 25, Color: "#df5286", Type: "Conference" },
  { Name: "Hangout", Id: 6, Capacity: 10, Color: "#00bdae", Type: "Cabin" },
  { Name: "Rick Roll", Id: 7, Capacity: 20, Color: "#865fcf", Type: "Conference" },
  { Name: "Rainbow", Id: 8, Capacity: 8, Color: "#1aaa55", Type: "Cabin" },
  { Name: "Swarm", Id: 9, Capacity: 30, Color: "#df5286", Type: "Conference" },
  { Name: "Photogenic", Id: 10, Capacity: 25, Color: "#710193", Type: "Conference" }
];

const intl = new Internationalization();
const height = '650px';
const width = '100%';
const eventSettings = {
  dataSource: quickInfoData
};
const selectedDate = new Date(2020, 0, 9);
const fields = { text: "Name", value: "Id" };
const views = ['Day', 'Week', 'WorkWeek'];
const roomData = extend([], resourceData, undefined, true);
const quickInfoTemplates = {
  header: "headerTemplate",
  content: "contentTemplate",
  footer: "footerTemplate"
}

provide('schedule', [Day, Week, WorkWeek, Month, Agenda]);
const getHeaderStyles = function (data) {
  let schedule = scheduleObj.value.ej2Instances;
  const resources = schedule.getResourceCollections().slice(-1)[0];
  const resourceData = resources.dataSource.filter(resource => resource.Id === data.RoomId)[0];
  return resourceData.Color;
};
const getHeaderTitle = function (data) {
  return data.elementType === "cell" ? "Add Appointment" : "Appointment Details";
};
const getHeaderDetails = function (data) {
  return (
    intl.formatDate(data.StartTime, { type: "date", skeleton: "full" }) + " (" +
    intl.formatDate(data.StartTime, { skeleton: 'hm' }) + " - " +
    intl.formatDate(data.EndTime, { skeleton: 'hm' }) + ")"
  );
};
const getEventType = function (data) {
  let schedule = scheduleObj.value.ej2Instances;
  const resources = schedule.getResourceCollections().slice(-1)[0];
  const resourceData = resources.dataSource.filter(resource => resource.Id === data.RoomId)[0];
  return resourceData.Name;
};
const buttonClickActions = function (e) {
  let schedule = scheduleObj.value.ej2Instances;
  const quickPopup = schedule.element.querySelector(".e-quick-popup-wrapper");
  const getSlotData = function () {
    const titleObj = quickPopup.querySelector("#title").ej2_instances[0];
    const notesObj = quickPopup.querySelector("#notes").ej2_instances[0];
    const eventTypeObj = quickPopup.querySelector("#eventType").ej2_instances[0];
    const cellDetails = schedule.getCellDetails(schedule.getSelectedElements());
    let addObj = {};
    addObj.Id = schedule.getEventMaxID();
    addObj.Subject = titleObj.value;
    addObj.StartTime = new Date(+cellDetails.startTime);
    addObj.EndTime = new Date(+cellDetails.endTime);
    addObj.Description = notesObj.value;
    addObj.RoomId = eventTypeObj.value;
    return addObj;
  };
  if (e.target.id === "add") {
    const addObj = getSlotData();
    schedule.addEvent(addObj);
  } else if (e.target.id === "delete") {
    const eventDetails = schedule.activeEventData.event;
    let currentAction = "Delete";
    if (eventDetails.RecurrenceRule) {
      currentAction = "DeleteOccurrence";
    }
    schedule.deleteEvent(eventDetails, currentAction);
  } else {
    const isCellPopup = quickPopup.firstElementChild.classList.contains("e-cell-popup");
    const eventDetails = isCellPopup ? getSlotData() : schedule.activeEventData.event;
    let currentAction = isCellPopup ? "Add" : "Save";
    if (eventDetails.RecurrenceRule) {
      currentAction = "EditOccurrence";
    }
    schedule.openEditor(eventDetails, currentAction, true);
  }
  schedule.closeQuickInfoPopup();
}

</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-calendars/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-dropdowns/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-inputs/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-popups/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-schedule/styles/material.css";

.quick-info-header {
  background-color: white;
  padding: 8px 18px;
}

.quick-info-header-content {
  justify-content: flex-end;
  display: flex;
  flex-direction: column;
  padding: 5px 10px 5px;
}

.quick-info-title {
  font-weight: 500;
  font-size: 16px;
  letter-spacing: 0.48px;
  height: 22px;
}

.duration-text {
  font-size: 11px;
  letter-spacing: 0.33px;
  height: 14px;
}

.content-area {
  margin: 0;
  padding: 10px;
  width: auto;
}

.event-content {
  height: 90px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 15px;
}

.meeting-type-wrap,
.meeting-subject-wrap,
.notes-wrap {
  font-size: 11px;
  color: #666;
  letter-spacing: 0.33px;
  height: 24px;
  padding: 5px;
}

.event-content div label {
  display: inline-block;
  min-width: 45px;
  color: #666;
}

.event-content div span {
  font-size: 11px;
  color: #151515;
  letter-spacing: 0.33px;
  line-height: 14px;
  padding-left: 8px;
}

.cell-footer.e-btn {
  background-color: #ffffff;
  border-color: #878787;
  color: #878787;
}

.cell-footer {
  padding-top: 10px;
}

.e-quick-popup-wrapper .e-cell-popup .e-popup-content {
  padding: 0 14px;
}

.e-quick-popup-wrapper .e-event-popup .e-popup-footer {
  display: block;
}

.e-quick-popup-wrapper .e-popup-footer button:first-child {
  margin-right: 5px;
}
</style>
<template>
  <div id='app'>
    <div id='container'>
      <ejs-schedule ref='scheduleObj' :height='height' :width='width' :views='views' :selectedDate='selectedDate'
        :eventSettings='eventSettings' :quickInfoTemplates='quickInfoTemplates'>
        <e-resources>
          <e-resource field="RoomId" title="Room Type" name="MeetingRoom" textField="Name" idField="Id"
            colorField="Color" :dataSource="roomData"></e-resource>
        </e-resources>
        <template v-slot:headerTemplate="{ data }">
          <div class="quick-info-header">
            <div class="quick-info-header-content" v-if="data.elementType == 'cell'"
              :style="{ 'align-items': 'center', 'color': '#919191' }">
              <div class="quick-info-title"></div>
              <div class="duration-text"></div>
            </div>
            <div class="quick-info-header-content" v-else
              :style="{ 'background': getHeaderStyles(data), 'color': '#FFFFFF' }">
              <div class="quick-info-title"></div>
              <div class="duration-text"></div>
            </div>
        </template>
        <template v-slot:contentTemplate="{ data }">
          <div class="quick-info-content">
            <div class="e-cell-content" v-if="data.elementType === 'cell'">
              <div class="content-area"><ejs-textbox ref="titleObj" id="title" placeholder="Title"></ejs-textbox></div>
              <div class="content-area"><ejs-dropdownlist ref="eventTypeObj" id="eventType" :dataSource="roomData"
                  :index="0" :fields="fields" popupHeight="200px" placeholder="Choose Type"></ejs-dropdownlist></div>
              <div class="content-area"><ejs-textbox ref="notesObj" id="notes" placeholder="Notes"></ejs-textbox></div>
            </div>
            <div class="event-content" v-else>
              <div class="meeting-type-wrap"><label>Subject</label>:<span></span></div>
              <div class="meeting-subject-wrap"><label>Type</label>:<span></span></div>
              <div class="notes-wrap"><label>Notes</label>:<span></span></div>
            </div>
          </div>
        </template>
        <template v-slot:footerTemplate="{ data }">
          <div class="quick-info-footer">
            <div class="cell-footer" v-if="data.elementType === 'cell'">
              <ejs-button id="more-details" cssClass="e-flat" content="More Details"
                v-on:click="buttonClickActions"></ejs-button>
              <ejs-button id="add" cssClass="e-flat" content="Add" :isPrimary="true"
                v-on:click="buttonClickActions"></ejs-button>
            </div>
            <div class="event-footer" v-else>
              <ejs-button id="delete" cssClass="e-flat" content="Delete" v-on:click="buttonClickActions"></ejs-button>
              <ejs-button id="more-details" cssClass="e-flat" content="More Details" :isPrimary="true"
                v-on:click="buttonClickActions"></ejs-button>
            </div>
        </template>
      </ejs-schedule>
    </div>
  </div>
</template>
<script>

import { ScheduleComponent, ResourcesDirective, ResourceDirective, Day, Week, WorkWeek, Month, Agenda } from '@syncfusion/ej2-vue-schedule';
import { extend, Internationalization } from "@syncfusion/ej2-base";
import { ButtonComponent } from "@syncfusion/ej2-vue-buttons";
import { DropDownListComponent } from "@syncfusion/ej2-vue-dropdowns";
import { TextBoxComponent } from "@syncfusion/ej2-vue-inputs";
import { quickInfoData } from './datasource.js';

const resourceData = [
  { Name: "Jammy", Id: 1, Capacity: 20, Color: "#ea7a57", Type: "Conference" },
  { Name: "Tweety", Id: 2, Capacity: 7, Color: "#7fa900", Type: "Cabin" },
  { Name: "Nestle", Id: 3, Capacity: 5, Color: "#5978ee", Type: "Cabin" },
  { Name: "Phoenix", Id: 4, Capacity: 15, Color: "#fec200", Type: "Conference" },
  { Name: "Mission", Id: 5, Capacity: 25, Color: "#df5286", Type: "Conference" },
  { Name: "Hangout", Id: 6, Capacity: 10, Color: "#00bdae", Type: "Cabin" },
  { Name: "Rick Roll", Id: 7, Capacity: 20, Color: "#865fcf", Type: "Conference" },
  { Name: "Rainbow", Id: 8, Capacity: 8, Color: "#1aaa55", Type: "Cabin" },
  { Name: "Swarm", Id: 9, Capacity: 30, Color: "#df5286", Type: "Conference" },
  { Name: "Photogenic", Id: 10, Capacity: 25, Color: "#710193", Type: "Conference" }
];

export default {
  name: "App",
  components: {
    "ejs-schedule": ScheduleComponent,
    "e-resources": ResourcesDirective,
    "e-resource": ResourceDirective,
    "ejs-textbox": TextBoxComponent,
    "ejs-dropdownlist": DropDownListComponent,
    "ejs-button": ButtonComponent,
  },
  data() {
    return {
      intl: new Internationalization(),
      height: '650px',
      width: '100%',
      eventSettings: {
        dataSource: quickInfoData
      },
      selectedDate: new Date(2020, 0, 9),
      fields: { text: "Name", value: "Id" },
      views: ['Day', 'Week', 'WorkWeek'],
      roomData: extend([], resourceData, undefined, true),
      quickInfoTemplates: {
        header: "headerTemplate",
        content: "contentTemplate",
        footer: "footerTemplate"
      }
    };
  },
  provide: {
    schedule: [Day, Week, WorkWeek, Month, Agenda]
  },
  methods: {
    getHeaderStyles: function (data) {
      let scheduleObj = this.$refs.scheduleObj.ej2Instances;
      const resources = scheduleObj.getResourceCollections().slice(-1)[0];
      const resourceData = resources.dataSource.filter(resource => resource.Id === data.RoomId)[0];
      return resourceData.Color;
    },
    getHeaderTitle: function (data) {
      return data.elementType === "cell" ? "Add Appointment" : "Appointment Details";
    },
    getHeaderDetails: function (data) {
      return (
        this.intl.formatDate(data.StartTime, { type: "date", skeleton: "full" }) + " (" +
        this.intl.formatDate(data.StartTime, { skeleton: 'hm' }) + " - " +
        this.intl.formatDate(data.EndTime, { skeleton: 'hm' }) + ")"
      );
    },
    getEventType: function (data) {
      let scheduleObj = this.$refs.scheduleObj.ej2Instances;
      const resources = scheduleObj.getResourceCollections().slice(-1)[0];
      const resourceData = resources.dataSource.filter(resource => resource.Id === data.RoomId)[0];
      return resourceData.Name;
    },
    buttonClickActions: function (e) {
      let scheduleObj = this.$refs.scheduleObj.ej2Instances;
      const quickPopup = scheduleObj.element.querySelector(".e-quick-popup-wrapper");
      const getSlotData = function () {
        const titleObj = quickPopup.querySelector("#title").ej2_instances[0];
        const notesObj = quickPopup.querySelector("#notes").ej2_instances[0];
        const eventTypeObj = quickPopup.querySelector("#eventType").ej2_instances[0];
        const cellDetails = scheduleObj.getCellDetails(scheduleObj.getSelectedElements());
        let addObj = {};
        addObj.Id = scheduleObj.getEventMaxID();
        addObj.Subject = titleObj.value;
        addObj.StartTime = new Date(+cellDetails.startTime);
        addObj.EndTime = new Date(+cellDetails.endTime);
        addObj.Description = notesObj.value;
        addObj.RoomId = eventTypeObj.value;
        return addObj;
      };
      if (e.target.id === "add") {
        const addObj = getSlotData();
        scheduleObj.addEvent(addObj);
      } else if (e.target.id === "delete") {
        const eventDetails = scheduleObj.activeEventData.event;
        let currentAction = "Delete";
        if (eventDetails.RecurrenceRule) {
          currentAction = "DeleteOccurrence";
        }
        scheduleObj.deleteEvent(eventDetails, currentAction);
      } else {
        const isCellPopup = quickPopup.firstElementChild.classList.contains("e-cell-popup");
        const eventDetails = isCellPopup ? getSlotData() : scheduleObj.activeEventData.event;
        let currentAction = isCellPopup ? "Add" : "Save";
        if (eventDetails.RecurrenceRule) {
          currentAction = "EditOccurrence";
        }
        scheduleObj.openEditor(eventDetails, currentAction, true);
      }
      scheduleObj.closeQuickInfoPopup();
    }
  }
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-calendars/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-dropdowns/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-inputs/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-popups/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-schedule/styles/material.css";

.quick-info-header {
  background-color: white;
  padding: 8px 18px;
}

.quick-info-header-content {
  justify-content: flex-end;
  display: flex;
  flex-direction: column;
  padding: 5px 10px 5px;
}

.quick-info-title {
  font-weight: 500;
  font-size: 16px;
  letter-spacing: 0.48px;
  height: 22px;
}

.duration-text {
  font-size: 11px;
  letter-spacing: 0.33px;
  height: 14px;
}

.content-area {
  margin: 0;
  padding: 10px;
  width: auto;
}

.event-content {
  height: 90px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 15px;
}

.meeting-type-wrap,
.meeting-subject-wrap,
.notes-wrap {
  font-size: 11px;
  color: #666;
  letter-spacing: 0.33px;
  height: 24px;
  padding: 5px;
}

.event-content div label {
  display: inline-block;
  min-width: 45px;
  color: #666;
}

.event-content div span {
  font-size: 11px;
  color: #151515;
  letter-spacing: 0.33px;
  line-height: 14px;
  padding-left: 8px;
}

.cell-footer.e-btn {
  background-color: #ffffff;
  border-color: #878787;
  color: #878787;
}

.cell-footer {
  padding-top: 10px;
}

.e-quick-popup-wrapper .e-cell-popup .e-popup-content {
  padding: 0 14px;
}

.e-quick-popup-wrapper .e-event-popup .e-popup-footer {
  display: block;
}

.e-quick-popup-wrapper .e-popup-footer button:first-child {
  margin-right: 5px;
}
</style>