DevExtreme v23.2 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Google Calendar Integration

To display appointments from Google Calendar in the Scheduler, follow the steps below:

  1. Get Google API key
    Follow the instructions from step 1 in the Browser Quickstart tutorial.

  2. Restrict the API key
    Set application and API restrictions.

  3. Make your calendar public
    Refer to the following help topic: Create & manage a public Google calendar.

  4. Get the calendar ID
    Open Google Calendar settings, choose the calendar to be integrated, and copy its ID from the Integrate calendar section.

  5. Set up the Scheduler
    Configure the CustomStore to load data from Google Calendar as shown in this demo. If a timeZone is specified in the Scheduler, ensure it is the same as in Google Calendar.

Backend API
import 'whatwg-fetch'; import React from 'react'; import Scheduler, { SchedulerTypes } from 'devextreme-react/scheduler'; import CustomStore from 'devextreme/data/custom_store'; // eslint-disable-next-line space-before-function-paren const getData = async (_, requestOptions) => { const GOOGLE_CALENDAR_URL = 'https://www.googleapis.com/calendar/v3/calendars/'; const CALENDAR_ID = 'f7jnetm22dsjc3npc2lu3buvu4@group.calendar.google.com'; const PUBLIC_KEY = 'AIzaSyBnNAISIUKe6xdhq1_rjor2rxoI3UlMY7k'; const dataUrl = [GOOGLE_CALENDAR_URL, CALENDAR_ID, '/events?key=', PUBLIC_KEY].join(''); const response = await fetch(dataUrl, requestOptions); const data = await response.json(); return data.items; }; const dataSource = new CustomStore({ load: (options) => getData(options, { showDeleted: false }), }); const currentDate = new Date(2017, 4, 25); const views: SchedulerTypes.ViewType[] = ['day', 'workWeek', 'month']; const App = () => ( <React.Fragment> <div className="long-title"> <h3>Tasks for Employees (USA Office)</h3> </div> <Scheduler dataSource={dataSource} views={views} defaultCurrentView="workWeek" defaultCurrentDate={currentDate} height={500} startDayHour={7} editing={false} showAllDayPanel={false} startDateExpr="start.dateTime" endDateExpr="end.dateTime" textExpr="summary" timeZone="America/Los_Angeles" /> </React.Fragment> ); export default App;
import 'whatwg-fetch'; import React from 'react'; import Scheduler from 'devextreme-react/scheduler'; import CustomStore from 'devextreme/data/custom_store'; // eslint-disable-next-line space-before-function-paren const getData = async (_, requestOptions) => { const GOOGLE_CALENDAR_URL = 'https://www.googleapis.com/calendar/v3/calendars/'; const CALENDAR_ID = 'f7jnetm22dsjc3npc2lu3buvu4@group.calendar.google.com'; const PUBLIC_KEY = 'AIzaSyBnNAISIUKe6xdhq1_rjor2rxoI3UlMY7k'; const dataUrl = [GOOGLE_CALENDAR_URL, CALENDAR_ID, '/events?key=', PUBLIC_KEY].join(''); const response = await fetch(dataUrl, requestOptions); const data = await response.json(); return data.items; }; const dataSource = new CustomStore({ load: (options) => getData(options, { showDeleted: false }), }); const currentDate = new Date(2017, 4, 25); const views = ['day', 'workWeek', 'month']; const App = () => ( <React.Fragment> <div className="long-title"> <h3>Tasks for Employees (USA Office)</h3> </div> <Scheduler dataSource={dataSource} views={views} defaultCurrentView="workWeek" defaultCurrentDate={currentDate} height={500} startDayHour={7} editing={false} showAllDayPanel={false} startDateExpr="start.dateTime" endDateExpr="end.dateTime" textExpr="summary" timeZone="America/Los_Angeles" /> </React.Fragment> ); export default App;
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.tsx'; ReactDOM.render( <App />, document.getElementById('app'), );
window.exports = window.exports || {}; window.config = { transpiler: 'ts', typescriptOptions: { module: 'system', emitDecoratorMetadata: true, experimentalDecorators: true, jsx: 'react', }, meta: { 'react': { 'esModule': true, }, 'typescript': { 'exports': 'ts', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, }, paths: { 'npm:': 'https://unpkg.com/', }, defaultExtension: 'js', map: { 'ts': 'npm:plugin-typescript@4.2.4/lib/plugin.js', 'typescript': 'npm:typescript@4.2.4/lib/typescript.js', 'react': 'npm:react@17.0.2/umd/react.development.js', 'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js', 'prop-types': 'npm:prop-types@15.8.1/prop-types.js', 'whatwg-fetch': 'npm:whatwg-fetch@2.0.4/fetch.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign@1.1.0', 'devextreme': 'npm:devextreme@23.2.5/cjs', 'devextreme-react': 'npm:devextreme-react@23.2.5/cjs', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@1.6.4/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.51/dist/dx-gantt.js', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12', 'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js', 'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js', 'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js', 'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js', 'inferno-hydrate': 'npm:inferno-hydrate@7.4.11/dist/inferno-hydrate.min.js', 'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js', 'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js', 'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js', 'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3', // SystemJS plugins 'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js', // Prettier 'prettier/standalone': 'npm:prettier@2.8.4/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.4/parser-html.js', }, packages: { 'devextreme': { defaultExtension: 'js', }, 'devextreme-react': { main: 'index.js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/localization/messages': { format: 'json', defaultExtension: '', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.12/inferno/package.json', ], babelOptions: { sourceMaps: false, stage0: true, react: true, }, }; System.config(window.config);
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js'; ReactDOM.render(<App />, document.getElementById('app'));
<!DOCTYPE html> <html> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/23.2.5/css/dx.light.css" /> <link rel="stylesheet" type="text/css" href="styles.css" /> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.tsx"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></div> </div> </body> </html>
.long-title h3 { font-family: "Segoe UI Light", "Helvetica Neue Light", "Segoe UI", "Helvetica Neue", "Trebuchet MS", Verdana; font-weight: 200; font-size: 28px; text-align: center; margin-bottom: 20px; }