將DHTMLX Scheduler元件與React JS庫一起使用教程
dhtmlxScheduler是一個類似於Google日曆的JavaScript日程安排控制元件,日曆事件通過Ajax動態載入,支援通過拖放功能調整事件日期和時間。事件可以按天,周,月三個種檢視顯示。
本文介紹了dhtmlxScheduler v5.3各小版本更新內容集合,請檢視文章內容瞭解詳細資訊。
我們繼續進行一系列教程,致力於將我們的Web應用程式元件與不同的客戶端框架進行整合。查閱我們有關將DHTMLX Scheduler與流行的基於React JS元件的庫一起使用的新分步指南。
在這裡,您將學習如何:
- 建立一個基本的React Scheduling應用程式
- 通過自定義功能擴充套件事件日曆功能
- 使其能夠實時聆聽並響應使用者的操作
在深入探討該主題之前,我們邀請您在我們的React Scheduler GitHub儲存庫上檢視完整的演示。
如何開始
我們的第一步是初始化應用程式結構。為此,我們將使用建立React應用程式工具。您可以在本文中找到有關它的其他資訊。
要建立一個應用程式,請執行以下命令:
npx create-react-app scheduler-react
然後,我們進入app資料夾並使用以下命令執行該應用程式:
cd scheduler-react yarn start (if you use yarn) npm start (if you use npm)
現在我們的應用程式應該從http:// localhost:3000 /開始
將DHTMLX Scheduler新增到React App
讓我們從我們的Scheduler元件開始。
您需要做的第一件事是將DHTMLX Scheduler程式包新增到您的專案中。
可以通過npm或yarn新增它的免費版本:
yarn add dhtmlx-scheduler (for yarn) or npm install dhtmlx-scheduler (for npm)
然後,建立src / components / Scheduler資料夾。在這裡,我們將為DHTMLX Scheduler新增一個React Component包裝器。
建立Scheduler.js檔案並開啟它:
{{ src/components/Scheduler/Scheduler.js }} import React, { Component } from 'react'; import 'dhtmlx-scheduler'; import 'dhtmlx-scheduler/codebase/dhtmlxscheduler_material.css'; const scheduler = window.scheduler; export default class Scheduler extends Component { componentDidMount() { scheduler.skin = 'material'; scheduler.config.header = [ 'day', 'week', 'month', 'date', 'prev', 'today', 'next' ]; const { events } = this.props; scheduler.init(this.schedulerContainer, new Date(2020, 5, 10)); scheduler.clearAll(); scheduler.parse(events); } render() { return ( <div ref={ (input) => { this.schedulerContainer = input } } style={ { width: '100%', height: '100%' } } ></div> ); } }
現在建立Scheduler.css檔案併為scheduler-container新增樣式:
{{ src/components/Scheduler/Scheduler.css }} .scheduler-container { height: 100vh; width: 100vw; }
最後,建立具有以下內容的index.js檔案:
{{ src/components/Scheduler/index.js }} import Scheduler from './Scheduler'; import './Scheduler.css'; export default Scheduler;
由於DHTMLX Scheduler是位於ReactJS世界之外的常規JS庫,因此我們建立了包裝器元件。裝入元件後,我們將初始化DHTMLX Scheduler並將其附加到DOM。我們還可以使用通過props傳遞的資料來填充它。
請注意,由於DHTMLX Scheduler的免費版本沒有解構函式,因此我們沒有定義componentWillUnmount。這也意味著,如果我們在某個時候從React中刪除了一個元件,則DHTMLX Scheduler的例項將保留在記憶體中,並在下次再次安裝該元件時再次使用。
現在,將Scheduler新增到我們的App元件中。請注意,我們對此示例使用硬編碼資料:
{{ src/App.js }} import React, { Component } from 'react'; import Scheduler from './components/Scheduler'; import './App.css'; const data = [ { start_date:'2020-06-10 6:00', end_date:'2020-06-10 8:00', text:'Event 1', id: 1 }, { start_date:'2020-06-13 10:00', end_date:'2020-06-13 18:00', text:'Event 2', id: 2 } ]; class App extends Component { render() { return ( <div> <div className='scheduler-container'> <Scheduler events={data}/> </div> </div> ); } } export default App;
如果我們現在執行該應用程式,我們應該在頁面上看到一個帶有初始事件的簡單事件日曆:
yarn start or npm start
配置React Scheduler元件
讓我們在React js事件日曆中新增一些自定義功能。假設我們需要新增一個帶有複選框的工具欄,該複選框將負責在小時刻度上切換時間格式。
我們可以使用hour_date配置和hour_scale模板更改時間格式。之後,我們需要使用渲染器以新格式重新繪製檢視。讓我們嘗試在React中實現它。首先,讓我們轉到Scheduler元件,併為檢視配置實現幾個預設。
開啟Scheduler.js,向其新增以下程式碼:
{{ src/components/Scheduler/Scheduler.js }} componentDidMount() { scheduler.skin = 'material'; scheduler.config.header = [ 'day', 'week', 'month', 'date', 'prev', 'today', 'next' ]; scheduler.config.hour_date = '%g:%i %A'; scheduler.xy.scale_width = 70; const { events } = this.props; scheduler.init(this.schedulerContainer, new Date(2020, 5, 10)); scheduler.clearAll(); scheduler.parse(events); } shouldComponentUpdate(nextProps) { return this.props.timeFormatState !== nextProps.timeFormatState; } componentDidUpdate() { scheduler.render(); } setTimeFormat(state) { scheduler.config.hour_date = state ? '%H:%i' : '%g:%i %A'; scheduler.templates.hour_scale = scheduler.date.date_to_str(scheduler.config.hour_date); }
在這裡,我們添加了componentDidUpdate處理程式(將在更新時重新繪製檢視)和shouldComponentUpdate處理程式,在其中將確定是否需要更新檢視。
並在render方法的開頭新增對setTimeFormat函式的呼叫:
{{ src/components/Scheduler/Scheduler.js }} render() { const { timeFormatState } = this.props; this.setTimeFormat(timeFormatState); return ( <div ref={ (input) => { this.schedulerContainer = input } } style={ { width: '100%', height: '100%' } } ></div> ); }
現在,排程程式將以24小時格式顯示時間。當hour_date屬性和hour_scale模板更改時,我們需要呼叫檢視的更新。
讓我們新增用於更改時間格式的UI。我們將使用一個簡單的工具欄和切換器。
建立工具欄元件:
{{ src/components/Toolbar/index.js }} import Toolbar from './Toolbar'; import './Toolbar.css'; export default Toolbar;
{{ src/components/Toolbar/Toolbar.js }} import React, { Component } from 'react'; export default class Toolbar extends Component { handleTimeFormatStateChange = (e) => { if (this.props.onTimeFormatStateChange) { this.props.onTimeFormatStateChange(e.target.checked) } } render() { return ( <div className='time-format-section'> <label className='time-format-chkbx'> Time format: <input type='checkbox' checked={ this.props.timeFormatState } onChange={ this.handleTimeFormatStateChange } /> <div className='chkbx-text'></div> </label> </div> ); } }
{{ src/components/Toolbar/Toolbar.css }} .tool-bar { background: #ededed; height: 40px; line-height: 14px; padding: 5px 10px; text-align: center; padding-left: 60px; } .time-format-chkbx { display: inline-flex; padding-top: 10px; font-family: Roboto,Arial; user-select: none; font-weight: 500; font-size: 20px; color: rgba(0,0,0,.75); } .time-format-chkbx input { position: absolute; z-index: -1; opacity: 0; margin: 10px 0 0 20px; } .chkbx-text { position: relative; cursor: pointer; user-select: none; font-weight: 800; font-size: 20px; line-height: 30px; font-family: Roboto,Arial; margin-left: 10px; } .chkbx-text:before { content: '12h'; text-align: right; padding: 0 10px; position: absolute; top: -8px; left: 0; width: 60px; height: 30px; border-radius: 15px; background: #CDD1DA; box-shadow: inset 0 2px 3px rgba(0,0,0,.2); transition: .2s; } .chkbx-text:after { content: ''; position: absolute; top: -6px; left: 2px; width: 25px; height: 25px; border-radius: 15px; background: #FFF; box-shadow: 0 2px 5px rgba(0,0,0,.3); transition: .2s; } .time-format-chkbx input:checked + .chkbx-text:before { content: '24h'; color: white; text-align: left; background: #0288d1; } .time-format-chkbx input:checked + .chkbx-text:after { left: 53px; } .time-format-chkbx input:focus + .chkbx-text:before { box-shadow: inset 0 2px 3px rgba(0,0,0,.2), 0 0 0 3px rgba(2,136,209,.7); }
並更新排程程式容器的高度:
{{ src/components/Scheduler/Scheduler.css }} .scheduler-container { height: calc(100vh - 50px); width: 100vw; }
在這裡,我們添加了用於更改時間格式的複選框,併為父元件提供了onTimeFormatStateChange處理程式。現在,您需要將工具欄新增到App元件中:
{{ src/App.js }} import Toolbar from './components/Toolbar';
以及用於更改事件的處理程式:
{{ src/App.js }} state = { currentTimeFormatState: true }; handleTimeFormatStateChange = (state) => { this.setState({ currentTimeFormatState: state }); }
JSX:
{{ src/App.js }} render() { const { currentTimeFormatState } = this.state; return ( <div> <div className="tool-bar"> <Toolbar timeFormatState={currentTimeFormatState} onTimeFormatStateChange={this.handleTimeFormatStateChange} /> </div> <div className='scheduler-container'> <Scheduler events={data} timeFormatState={currentTimeFormatState} /> </div> </div> ); }
因此,每次使用者更改時間格式時,我們就有機會將更新後的狀態傳遞給我們的React Scheduler:
處理DHTMLX React Scheduler中所做的更改
現在,我們將展示如何捕獲日曆檢視更改,然後將其傳遞到應用程式中的某處。
我們將使用dhtmlxScheduler事件捕獲Scheduler的更改。
讓我們看看如何在實踐中做到這一點。開啟src / components / Scheduler / Scheduler.js並新增以下方法:
{{ src/components/Scheduler/Scheduler.js }} initSchedulerEvents() { if (scheduler._$initialized) { return; } const onDataUpdated = this.props.onDataUpdated; scheduler.attachEvent('onEventAdded', (id, ev) => { if (onDataUpdated) { onDataUpdated('create', ev, id); } }); scheduler.attachEvent('onEventChanged', (id, ev) => { if (onDataUpdated) { onDataUpdated('update', ev, id); } }); scheduler.attachEvent('onEventDeleted', (id, ev) => { if (onDataUpdated) { onDataUpdated('delete', ev, id); } }); scheduler._$initialized = true; } componentDidMount() { scheduler.skin = 'material'; scheduler.config.header = [ 'day', 'week', 'month', 'date', 'prev', 'today', 'next' ]; scheduler.config.hour_date = '%g:%i %A'; scheduler.xy.scale_width = 70; this.initSchedulerEvents(); const { events } = this.props; scheduler.init(this.schedulerContainer, new Date(2020, 5, 10)); scheduler.clearAll(); scheduler.parse(events); }
我們使用排程程式的全域性例項,並且由於可以多次掛載它,因此需要確保僅新增一次事件偵聽器。
為此,我們使用一個自定義的“ scheduler ._ $ initialized”標誌。首次初始化排程程式時,未定義此標誌,因此我們添加了事件偵聽器並將此標誌設定為`true`。這樣,我們確保不再將事件偵聽器附加到同一Scheduler例項。
這樣,我們就可以捕獲在Scheduler中所做的所有更改並將其傳送到父元件。
我們需要捕獲事件,為事件建立訊息,並將這些訊息置於本地狀態。為此,請更新App元件:
{{ src/App.js }} state = { currentTimeFormatState: true, messages: [] }; addMessage(message) { const maxLogLength = 5; const newMessage = { message }; const messages = [ newMessage, ...this.state.messages ]; if (messages.length > maxLogLength) { messages.length = maxLogLength; } this.setState({ messages }); } logDataUpdate = (action, ev, id) => { const text = ev && ev.text ? ` (${ev.text})` : ''; const message = `event ${action}: ${id} ${text}`; this.addMessage(message); }
之後,建立一個元件,將在頁面上顯示以下訊息:
{{ src/components/MessageArea/MessageArea.js }} import React, { Component } from 'react'; export default class MessageArea extends Component { render() { const messages = this.props.messages.map(({ message }) => { return <li key={ Math.random() }>{message}</li> }); return ( <div className="message-area"> <h3>Messages:</h3> <ul> { messages } </ul> </div> ); } } MessageArea.defaultProps = { messages: [] };
{{ src/components/MessageArea/index.js }} import MessageArea from './MessageArea'; import './MessageArea.css'; export default MessageArea;
新增樣式:
{{ src/components/MessageArea/MessageArea.css }} .message-area { background: #ebebeb; height: 200px; overflow: auto; padding: 10px; box-sizing:border-box; } .message-area ul{ margin: 0; padding: 0; list-style: none; } .message-area li:before { content: "\003e"; padding-right: 10px; }
並更新排程程式容器的高度:
{{ src/components/Scheduler/Scheduler.css }} .scheduler-container { height: calc(100vh - 50px - 200px); width: 100vw; }
最後,將此元件連線到App:
匯入:
{{ src/App.js }} import MessageArea from './components/MessageArea';
JSX:
render() { const { currentTimeFormatState, messages } = this.state; return ( <div> <div className="tool-bar"> <Toolbar timeFormatState={currentTimeFormatState} onTimeFormatStateChange={this.handleTimeFormatStateChange} /> </div> <div className='scheduler-container'> <Scheduler events={data} timeFormatState={currentTimeFormatState} onDataUpdated={this.logDataUpdate} /> </div> <MessageArea messages={messages} /> </div> ); }
因此,現在每次使用者更改日曆事件時,處理程式都會呼叫App元件並更新MessageArea,後者在頁面上列印有關使用者操作的資訊。
如果執行該應用程式,我們將看到以下結果:
我們希望我們的教程對您的專案有用。如果您遇到任何困難,請隨時在下面的評論中向我們傳送您的問題。