---
title: "Angular Agenda Load Public Google Calendar Events Example | Mobiscroll"
component: "Agenda"
framework: "Angular"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/angular/agenda/load-events-from-google-calendar"
---

# Load Public Google Calendar Events - Angular Agenda demo

Load events from a public Google Calendar into the Angular agenda view using the integration plugin — connect with a Calendar ID and API key. For Angular 22 and Ionic 8.

- [Live demo](https://demo.mobiscroll.com/angular/agenda/load-events-from-google-calendar)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-angular/tree/main/src/demos/eventcalendar/agenda/load-events-from-google-calendar)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/agenda/load-events-from-google-calendar.md), [jQuery](https://demo.mobiscroll.com/jquery/agenda/load-events-from-google-calendar.md), [React](https://demo.mobiscroll.com/react/agenda/load-events-from-google-calendar.md), [Vue](https://demo.mobiscroll.com/vue/agenda/load-events-from-google-calendar.md)

## Description

Event data can be loaded from remote sources, like public google calendars. Through the [**integration plugin**](https://mobiscroll.com/docs/angular/eventcalendar/calendar-integrations) you can easily show events that are available in a public calendar. The integration plugin needs to be added to the download package or installed separately from a dedicated NPM package.

You will just need the `CALENDAR_ID` and an `apiKey` from google and you should be ready to roll.

Public calendars are read-only. If you are interested in syncing private google calendars with read/write/delete access, [check out this example](https://demo.mobiscroll.com/angular/agenda/sync-events-google-calendar).

This example uses the [**integration plugin**](https://mobiscroll.com/docs/angular/eventcalendar/calendar-integrations) to connect to and load events from Google Calendar and it is not available in the trial. Give the live demo a try and see how it can be configured.

## What this demo shows

- Shows a weekly agenda view with events listed and grouped by date.
- **Custom header** The current month and year are shown on the left side of the header.
- **View switching** A segmented control in the center lets users switch between `Month`, `Week`, `Day`, and `Agenda` views, with `Agenda` selected by default.
- **Secondary navigation** Blue previous and next arrow buttons are shown on the right side of the header with a `Today` button between them.
- **Week view** A week calendar is displayed at the top of the view.
- **Week navigation** The week strip can be changed by clicking and dragging left or right.
- **Day cell states** Hovering a day highlights the day number with a gray background. Selecting a day highlights the day number with a blue background. The current date is highlighted by default.
- **Event markers** Days with events show a small dot marker inside the day cell.
- **Agenda list** The area below the calendar lists events for the selected day.
- **Date selection** Selecting a day in the week calendar updates the agenda to show events for that date.
- **Events** Events appear as agenda cards with a colored strip on the left and the event title next to it. Start and end times are stacked on the right side of timed events. All-day events show the all-day label on the right.
- **Event interaction** Hovering an event highlights it.
- **Event selection** Clicking an event selects and highlights it.
- **Weekly scheduler view** Selecting the `Week` option from the segmented control switches the layout to a weekly scheduler view. This shows the days of the week at the top, an all-day section for all-day events, and a 24-hour time grid for each day of the week for timed events.
- **Daily scheduler view** Selecting the `Day` option from the segmented control switches the layout to a daily scheduler view. This shows the days of the week at the top, an all-day section for all-day events, and a 24-hour time grid for one day for timed events.
- **Scheduler view** The current time is marked with a blue line in the time grid.
- **Scheduler view** The time grid can be scrolled vertically with the mouse wheel while the header stays sticky.
- **Monthly calendar view** Selecting the `Month` option from the segmented control switches the layout to a monthly calendar view. Days with events display event labels inside the month grid cells.

## Best for

- **Google Calendar overlays** Showing events from public Google Calendars inside an agenda view.
- **Read-only event publishing** Sharing team, organization, or community calendars where visitors need to browse events but not edit them.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-themeVariant) - option
- [`firstDay`](https://mobiscroll.com/docs/angular/eventcalendar/api#localization-firstDay) - option
- [`labels`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-labels) - option
- [`onInit`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onInit) - event
- [`data`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-data) - option
- [`exclusiveEndDates`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-exclusiveEndDates) - option
- [`headerTemplate`](https://mobiscroll.com/docs/angular/eventcalendar/api#template-headerTemplate) - template
- [`view`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-view) - option
- [`onPageLoading`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onPageLoading) - event

## Code

### Component

```ts
import { CommonModule } from '@angular/common';
import { Component, NgZone, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {
  MbscCalendarEvent,
  MbscEventcalendarView,
  MbscModule,
  MbscPageLoadingEvent,
  Notifications,
  setOptions,
} from '@mobiscroll/angular';
import { googleCalendarSync } from '@mobiscroll/calendar-integration';

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

const CALENDAR_ID = 'theacidmedia.net_8l6v679q5j2f7q8lpmcjr4mm3k@group.calendar.google.com';

@Component({
  selector: 'app-root', 
  templateUrl: './app.component.html',
  standalone: true,
  imports: [CommonModule, FormsModule, MbscModule],
})
export class AppComponent implements OnInit {
  constructor(
    public notify: Notifications,
    public zone: NgZone,
  ) {}

  currentView = 'agenda';
  firstDay!: Date;
  lastDay!: Date;
  isLoading = false;
  myEvents: MbscCalendarEvent[] = [];
  myView: MbscEventcalendarView = {
    calendar: { type: 'week' },
    agenda: { type: 'week' },
  };

  onPageLoading(event: MbscPageLoadingEvent): void {
    const start = event.viewStart;
    const end = event.viewEnd;

    // Calculate dates
    // (pre-load events for previous and next pages as well)
    if (this.currentView === 'month') {
      this.firstDay = start;
      this.lastDay = end;
    } else {
      this.firstDay = new Date(start.getFullYear(), start.getMonth(), start.getDate() - 7);
      this.lastDay = new Date(end.getFullYear(), end.getMonth(), end.getDate() + 7);
    }
    this.loadEvents();
  }

  onError(resp: { error?: string; result: { error: { message: string } } }): void {
    this.notify.toast({
      message: resp.error ? resp.error : resp.result.error.message,
    });
  }

  loadEvents(): void {
    this.isLoading = true;
    googleCalendarSync
      .getEvents(CALENDAR_ID, this.firstDay, this.lastDay)
      .then((resp) => {
        this.zone.run(() => {
          this.myEvents = resp;
          this.isLoading = false;
        });
      })
      .catch((error) => {
        this.onError(error);
      });
  }

  changeView(): void {
    setTimeout(() => {
      switch (this.currentView) {
        case 'month':
          this.myView = { calendar: { labels: true } };
          break;
        case 'week':
          this.myView = { scheduler: { type: 'week' } };
          break;
        case 'day':
          this.myView = { scheduler: { type: 'day' } };
          break;
        case 'agenda':
        default:
          this.myView = {
            calendar: { type: 'week' },
            agenda: { type: 'week' },
          };
          break;
      }
    });
  }

  ngOnInit(): void {
    googleCalendarSync.init({
      apiKey: '<YOUR_GOOGLE_API_KEY>',
      onInit: () => {
        this.loadEvents();
      },
    });
  }
}
```

### Template

```html
<mbsc-eventcalendar
  [data]="myEvents"
  [exclusiveEndDates]="true"
  [headerTemplate]="customHeaderTemplate"
  [view]="myView"
  (onPageLoading)="onPageLoading($event)"
>
  <ng-template #customHeaderTemplate>
    <mbsc-calendar-nav class="mds-google-cal-nav"></mbsc-calendar-nav>
    <div [style.visibility]="isLoading ? 'visible' : 'hidden'" class="mds-loader"></div>
    <div class="mds-google-cal-switch mbsc-flex-1-0">
      <mbsc-segmented-group [(ngModel)]="currentView" (change)="changeView()">
        <mbsc-segmented value="month">Month</mbsc-segmented>
        <mbsc-segmented value="week">Week</mbsc-segmented>
        <mbsc-segmented value="day">Day</mbsc-segmented>
        <mbsc-segmented value="agenda">Agenda</mbsc-segmented>
      </mbsc-segmented-group>
    </div>
    <mbsc-calendar-prev class="mds-google-cal-prev"></mbsc-calendar-prev>
    <mbsc-calendar-today class="mds-google-cal-today"></mbsc-calendar-today>
    <mbsc-calendar-next class="mds-google-cal-next"></mbsc-calendar-next>
  </ng-template>
</mbsc-eventcalendar>
```

### CSS

```css
.mds-google-cal-switch .mbsc-segmented {
  max-width: 300px;
  margin: 0 auto;
}

.mds-google-cal-nav {
  width: 200px;
}

.mds-loader {
  width: 32px;
  height: 32px;
  border: 4px solid #8c8c8c;
  border-bottom-color: transparent;
  border-radius: 50%;
  display: inline-block;
  box-sizing: border-box;
  animation: mds-loader-rotation 1s linear infinite;
  visibility: hidden;
}

@keyframes mds-loader-rotation {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* Material header order */

.mbsc-material.mds-google-cal-prev {
  order: 1;
}

.mbsc-material.mds-google-cal-next {
  order: 2;
}

.mbsc-material.mds-google-cal-nav {
  order: 3;
}

.mbsc-material .mds-google-cal-switch {
  order: 4;
}

.mbsc-material .mds-google-cal-today {
  order: 5;
}

/* Windows header order */

.mbsc-windows.mds-google-cal-nav {
  order: 1;
}

.mbsc-windows.mds-google-cal-prev {
  order: 2;
}

.mbsc-windows.mds-google-cal-next {
  order: 3;
}

.mbsc-windows .mds-google-cal-switch {
  order: 4;
}

.mbsc-windows .mds-google-cal-today {
  order: 5;
}
```

## Implementation notes

- Install the `@mobiscroll/calendar-integration` package. Call `googleCalendarSync.init({ apiKey: '<YOUR_GOOGLE_API_KEY>', onInit: loadEvents })` on mount to authenticate. Provide a `CALENDAR_ID` (the public Google Calendar ID).
- Set `exclusiveEndDates: true` on the Eventcalendar - Google Calendar uses exclusive end dates.
- Start with `view: { calendar: { type: 'week' }, agenda: { type: 'week' } }`. The view is switchable via a `SegmentedGroup` (Month / Week / Day / Agenda) in the custom header. On segment change, update the view: month → `{ calendar: { type: 'month' } }`, week → `{ scheduler: { type: 'week' } }`, day → `{ scheduler: { type: 'day' } }`, agenda → `{ calendar: { type: 'week' }, agenda: { type: 'week' } }`.
- Use `onPageLoading` to load events on every page change. Extract `args.viewStart` and `args.viewEnd` to determine the range. For non-month views, extend the range ±7 days to pre-load the previous and next pages. Call `googleCalendarSync.getEvents(CALENDAR_ID, firstDay, lastDay)` - it returns a Promise. On resolve, update the events array; on reject, show a Toast with the error message from `resp.error` or `resp.result.error.message`.
- Build a custom header using `renderHeader` (Angular: `headerTemplate`, Vue: `header` slot) containing: `CalendarNav`, a CSS loading spinner (toggle visibility while the Promise is pending), a `SegmentedGroup` for view switching, `CalendarPrev`, `CalendarToday`, `CalendarNext`.

## Run it in your project

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/angular/getting-started/installation

## Related demos

- Previous: [Outlook Calendar Sync](https://demo.mobiscroll.com/angular/agenda/sync-events-outlook-calendar.md) - Use the Angular event calendar integration plugin to authenticate users, load their Outlook calendars, and display events in an agenda view.
