Looks like you can create custom components for the react calendar component. I was looking at this example:
https://github.com/intljusticemission/react-big-calendar/blob/master/examples/demos/customView.js.
But it isn't clear how to create a custom event component. I'm also looked through the documentation, but there are no explicit examples:
http://intljusticemission.github.io/react-big-calendar/examples/index.html#prop-components
I'm particularly interested in creating a tooltip for each event that shows a more detailed event description.
Can anyone point to an example of where someone has created a custom component for react-big-calendar?
UPDATE: Here is an image of the calendar and some events rendered in the month view. I'm thinking, a custom event should definitely include the 'rbc-event' and 'rbc-event-content'. To add the bootstrap tool tip I'm thinking something like this in the custom event component:
And here is where the event cell component is created in the react-big-calendar source code.
return _react2.default.createElement(
'div',
_extends({}, props, {
style: _extends({}, props.style, style),
className: (0, _classnames2.default)('rbc-event', className, xClassName, {
'rbc-selected': selected,
'rbc-event-allday': isAllDay || _dates2.default.diff(start, _dates2.default.ceil(end, 'day'), 'day') > 1,
'rbc-event-continues-prior': continuesPrior,
'rbc-event-continues-after': continuesAfter
}),
onClick: function onClick() {
return onSelect(event);
}
}),
_react2.default.createElement(
'div',
{ className: 'rbc-event-content', title: title },
Component ? _react2.default.createElement(Component, { event: event, title: title }) : title
)
);
}
});
exports.default = EventCell;
module.exports = exports['default'];
I decided to try extending the EventCell component, when I passed it in as the event component prop, the event no longer had any content. Not sure how to pass event details into the 'rcb-event' div inside of the EventCell component. See below..
import React, { PropTypes } from 'react';
import MyCalendar from '../components/bigCalendar';
import _ from 'lodash';
import EventCell from 'react-big-calendar/lib/EventCell.js';
class MyEvent extends React.Component {
constructor(props){
super(props)
}
render(){
return (
<div className="testing">
<EventCell />
</div>
);
}
}
let components = {
event: MyEvent
}
Here, I am passing the components object I just created down to the MyCalendar presentation component:
export default class Calendar extends React.Component {
constructor(props) {
super(props);
var eventsList = Object.keys(props).map(function(k){
return props[k];
});
eventsList.map(function(event){
event["start"] = new Date(event["start"])
event["end"] = new Date(event["end"])
})
this.state = {
events: eventsList
};
};
render() {
return (
<div>
<MyCalendar components={components} events={this.state.events}/>
</div>
);
}
}
And, finally passing the components object to the presentation component via props. Which does successfully render in the view, but as I said earlier - without content.
const MyCalendar = props => (
<div className="calendar-container">
<BigCalendar
selectable
popup
components={props.components}
views={{month: true, week: true, day: true}}
events={props.events}
onSelectEvent={event => onSelectEvent(event)}
eventPropGetter={eventStyleGetter}
scrollToTime={new Date(1970, 1, 1, 6)}
defaultView='month'
defaultDate={new Date(2015, 3, 12)}
/>
</div>
);
MyCalendar.propTypes = {
events: PropTypes.array.isRequired,
components: PropTypes.object.isRequired
};
Seems like I'm supposed to go about this another way...Any suggestions?
This is what I came up with, I'm sure it could be cleaned up - but it works.
Create custom Event component, which includes the popover content.
import React, { PropTypes } from 'react';
import MyCalendar from '../components/bigCalendar';
import _ from 'lodash';
class MyEvent extends React.Component {
constructor(props){
super(props)
}
componentDidMount(){
MyGlobal.popOver();
}
render(){
return (
<div>
<div className="custom_event_content"
data-toggle="popover"
data-placement="top"
data-popover-content={"#custom_event_" + this.props.event.id}
tabIndex="0"
>
{this.props.event.title}
</div>
<div className="hidden" id={"custom_event_" + this.props.event.id} >
<div className="popover-heading">
{this.props.event.driver}
</div>
<div className="popover-body">
{this.props.event.title}<br/>
</div>
</div>
</div>
);
}
}
let components = {
event: MyEvent
}
export default class Calendar extends React.Component {
constructor(props) {
super(props);
var eventsList = Object.keys(props).map(function(k){
return props[k];
});
eventsList.map(function(event){
event["start"] = new Date(event["start"])
event["end"] = new Date(event["end"])
})
this.state = {
events: eventsList
};
};
render() {
return (
<div>
<MyCalendar components={components} events={this.state.events}/>
</div>
);
}
}
Add event listeners:
MyGlobal.popOver = function(){
$('body').on('click', function (e) {
//did not click a popover toggle or popover
if ($(e.target).data('toggle') !== 'popover'
&& $(e.target).parents('.popover.in').length === 0) {
$('[data-toggle="popover"]').popover('hide');
}
});
$("[data-toggle=popover]").popover({
html : true,
container: 'body',
content: function() {
var content = $(this).attr("data-popover-content");
return $(content).children(".popover-body").html();
},
title: function() {
var title = $(this).attr("data-popover-content");
return $(title).children(".popover-heading").html();
}
});
}
Pass custom props to MyCalendar presentation component:
const MyCalendar = props => (
<div className="calendar-container">
<BigCalendar
selectable
popup
components={props.components}
views={{month: true, week: true, day: true}}
events={props.events}
onSelectEvent={event => onSelectEvent(event)}
eventPropGetter={eventStyleGetter}
scrollToTime={new Date(1970, 1, 1, 6)}
defaultView='month'
defaultDate={new Date(2015, 3, 12)}
/>
</div>
);
MyCalendar.propTypes = {
events: PropTypes.array.isRequired,
components: PropTypes.object.isRequired
};
Just to update answer to 2020 using moment and reactstrap.
import React, {FC} from "react";
import {Calendar, Event, momentLocalizer, ToolbarProps} from "react-big-calendar";
import {UncontrolledTooltip} from "reactstrap";
import moment from "moment";
const localizer = momentLocalizer(moment);
interface CalendarToolbarProps extends ToolbarProps {
}
const CalendarToolbar: FC<CalendarToolbarProps> = ({date, view: viewMode, onView, ...props}) => {
return <div>Whatever you want on toolbar</div>
};
const eventPropGetter = (event: any, start: any, end: any, isSelected: boolean) => {
const style = {
backgroundColor: "#FF0000",
paddingLeft: "10px",
color: 'white',
};
return {
style: style
};
}
export interface FooEvent extends Event {
}
interface CalendarWithTooltipProps {
events: Event[]
}
const CalendarWithTooltip: FC<CalendarWithTooltipProps> = ({events, ...props}) => {
return <Calendar
events={events}
localizer={localizer}
eventPropGetter={eventPropGetter}
className={"overflow-scroll"}
components={{
event: (component: any) => {
const targetId = "...."
const {event} = component
return <div id={targetId}>
{event?.title}
<UncontrolledTooltip placement={"top"}
autohide={false}
style={{minWidth: 200}}
target={targetId} trigger={"hover"}>
Your tooltip content
</UncontrolledTooltip>
</div>
},
toolbar: (props) => <CalendarToolbar {...props}/>
}}
/>
}
export default CalendarWithTooltip
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With