NativeScript & Vue.JS

RadCalendar - Populating with data

RadCalendar allows you to define a list of events for a particular date. This is done by using the eventSource property. This article describes the steps you need to take in order to feed RadCalendar with your custom events using an events source.

The CalendarEvent class

Feeding events into RadCalendar is done via instances of the class. The class is model describing a single event. It exposes properties allowing you to specify things like:

  • start time of the event
  • end time of the event
  • whether the event is an 'all-day' event
  • title of the event, etc.

To create instances of the class you need to import the calendar module into your .ts file as shown below:

import { CalendarEvent } from 'nativescript-ui-calendar';

Create an events service and bind the events to RadCalendar

Assuming we have imported the calendar module as instructed above, we can now create a function that will create the events:

import { Color } from 'tns-core-modules/color';
import { CalendarEvent } from 'nativescript-ui-calendar';

export const getEvents = (count: Number) => {
  let now = new Date();
  let startDate: Date,
      endDate: Date,
      event: CalendarEvent;
  let colors: Array<Color> = [
    new Color(200, 188, 26, 214),
    new Color(220, 255, 109, 130),
    new Color(255, 55, 45, 255),
    new Color(199, 17, 227, 10),
    new Color(255, 255, 54, 3),
  ];
  let events: Array<CalendarEvent> = new Array<CalendarEvent>();
  for (let i = 1; i < count; i++) {
    startDate = new Date(
      now.getFullYear(), now.getMonth(), i * 2, 1
    );
    endDate = new Date(
      now.getFullYear(), now.getMonth(), (i * 2), 3
    );
    event = new CalendarEvent(
      `event ${i}`, startDate, endDate, false, colors[i * 10 % (colors.length - 1)]
    );
    events.push(event);
    if (i % 3 === 0) {
        const event = new CalendarEvent(`second ${i}`, startDate, endDate, true, colors[i * 5 % (colors.length - 1)]);
        events.push(event);
    }
  }
  return events;
};

export function getCalendarDayEvents(): Array<CalendarEvent> {
  const eventTitles: Array<string> = ["Meeting with Jack", "Lunch with Peter", "Planning meeting",
      "Go shopping", "Very important meeting", "Another meeting"];
  const eventColors: Array<Color> = [new Color("#0288D1"), new Color("#009688"), new Color("#E040FB")];

  const events: Array<CalendarEvent> = new Array<CalendarEvent>();
  const now: Date = new Date();
  const startDate: Date = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const endDate: Date = new Date(now.getFullYear(), now.getMonth(), now.getDate());

  startDate.setHours(9);
  endDate.setHours(10);
  let event = new CalendarEvent(eventTitles[0], startDate, endDate, false, eventColors[0]);
  events.push(event);

  startDate.setHours(12);
  endDate.setHours(13);
  event = new CalendarEvent(eventTitles[1], startDate, endDate, false, eventColors[1]);
  events.push(event);

  startDate.setHours(13);
  endDate.setHours(14);
  event = new CalendarEvent(eventTitles[2], startDate, endDate, false, eventColors[0]);
  events.push(event);

  startDate.setHours(20);
  endDate.setHours(22);
  event = new CalendarEvent(eventTitles[3], startDate, endDate, false, eventColors[2]);
  events.push(event);

  startDate.setHours(2);
  endDate.setHours(4);
  event = new CalendarEvent(eventTitles[4], startDate, endDate, false, eventColors[0]);
  events.push(event);

  startDate.setHours(16);
  endDate.setHours(17);
  event = new CalendarEvent(eventTitles[5], startDate, endDate, false, eventColors[0]);
  events.push(event);

  return events;
}

We can then use the getEvents() method of our service to populate the calendar using its eventSource property:

import { getEvents } from '../data';

const description = 'Populating with data';

export default {
  name: 'PopulatingWithData',
  description: description,
  template: `
  <Page>
    <ActionBar :title="title">
      <NavigationButton text="Back" android.systemIcon="ic_menu_back" @tap="onNavigationButtonTap"></NavigationButton>
    </ActionBar>
    <GridLayout orientation="vertical" rows="*, 100">
      <RadCalendar row="0" ref="calendar"
        :eventSource="events" @dateSelected="onDateSelected">
      </RadCalendar>
      <StackLayout row="1">
        <ListView ref="listView"
                  for="item in myItems">
          <v-template>
              <Label class="titleLabel" :text="item.title">
              </Label>
          </v-template>
        </ListView>
      </StackLayout>
    </GridLayout>
  </Page>
  `,
  data () {
    return {
      events: getEvents(10),
      title: description,
      myItems: ""
    };
  },
  methods: {
    onNavigationButtonTap() {
      frameModule.topmost().goBack();
    },
    onDateSelected(eventData) {
      this.myItems = this.$refs.calendar.nativeView.getEventsForDate(eventData.date);
    },
  },
};

Extending the CalendarEvent

If you need, you can extend the CalendarEvent with an id to track more easily the selected items or any other information that you need that is missing from the default event. Here's an example:

export class CustomEvent extends CalendarEvent {
  id: number;
  location: string;
  formattedTime: string;

  constructor(id: number, title: string, location: string, startDate: Date, endDate: Date, isAllDay?: boolean, eventColor?: Color) {
      super(title, startDate, endDate, isAllDay, eventColor);
      this.id = id;
      this.location = location;
      const hours = startDate.getHours();
      const minutes = startDate.getMinutes();
      this.formattedTime = (hours < 10 ? "0" : "") + hours + ':' + (minutes < 10 ? "0" : "") + minutes;
  }
}

Then you can use the new type to populate the list of items that will be bound to RadCalendar's eventSource property:

export function getCalendarCustomEvents(): Array<CustomEvent> {
  const eventColors: Array<Color> = [new Color("#71CBED"), new Color("#689F38"), new Color("#7B1FA2")];
  const events: Array<CustomEvent> = new Array<CustomEvent>();
  const now: Date = new Date();
  let startDate: Date;
  let endDate: Date;
  let event: CustomEvent;
  for (let i = 1; i < 10; i++) {
    startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() + i % 2, 12 + i);
    endDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() + i % 2, 12 + i, 30);
    let eventLocation = i > 5 ? "at home" : "at the office";
    event = new CustomEvent(i, "event " + i, eventLocation, startDate, endDate, false, eventColors[i % 3]);
    events.push(event);
  }
  return events;
}

Event view modes

The events for each date cell are shown as dots (iOS) or squares with a summary (Android). RadCalendar allows you to show more information about the events by changing the eventsViewMode property. The default value is None meaning that there will be no additional event representation coming out-of-the-box and the detailed information about events could be added through an additional ListView added below the RadCalendar and populated with information about events in a selected date. There are other event modes - Inline and Popover that present similar information within the calendar. Here are the available event view modes:

  • None - the default option
  • Inline - event details are displayed in a list that appears in the calendar
  • Popover - event details are displayed in a popup over the calendar

All of these values are exposed by the CalendarEventsViewMode enum defined in the calendar module.

To change the events view mode you need to set the eventsViewMode property of RadCalendar to one of these values.

import { CalendarEventsViewMode } from 'nativescript-ui-calendar';
import { getEvents } from '../data';

const description = 'Events view modes';

export default {
  name: 'EventsViewModes',
  description: description,
  template: `
  <Page>
    <ActionBar :title="title">
      <NavigationButton text="Back" android.systemIcon="ic_menu_back" @tap="onNavigationButtonTap"></NavigationButton>
    </ActionBar>
    <GridLayout orientation="vertical" rows="*, auto">
      <RadCalendar
        :eventSource="events"
        :eventsViewMode="eventsViewMode">
      </RadCalendar>
      <StackLayout row="1" orientation="horizontal" class="m-10">
        <Button text="None"  @tap="onNoneTap"></Button>
        <Button text="Inline"  @tap="onInlineTap"></Button>
        <Button text="Popover" @tap="onPopoverTap"></Button>
      </StackLayout>
    </GridLayout>
  </Page>
  `,
  data () {
    return {
      events: getEvents(10),
      eventsViewMode: CalendarEventsViewMode.None,
      title: description
    };
  },
  methods: {
    onNavigationButtonTap() {
      frameModule.topmost().goBack();
    },
    onNoneTap() {
      this.eventsViewMode = CalendarEventsViewMode.None;
    },
    onInlineTap() {
      this.eventsViewMode = CalendarEventsViewMode.Inline;
    },
    onPopoverTap() {
      this.eventsViewMode = CalendarEventsViewMode.Popover;
    },
  },
};