Feature --
I have enable isSelectable in my calendar, but want to have the user select a few timeslots and have a popup menu being rendered after they have selected. Essentially, I want to render a react component after onSelectSlot is called. Is there any way to do this?
The only thing i can think of right now is injecting something in the DOM when onSelectSlot is called but I can't take advantage of react then. I don't see a react class i can override in components for this either.
Does anyone have any suggestions?
I am not a contributor, but you can use any css framework that has a modal or popover component for this.
I am using Material-ui for that very purpose right now. Modal & Popover
I am using custom events react class like
class CustomEvent extends Component {
constructor(props) {
super(props);
this.state = {
isModalOpen: 0
};
}
handleOpen = () => {
this.setState({ isModalOpen: 1 });
};
handleClose = () => {
this.setState({ isModalOpen: 0 });
};
render() {
const { classes } = this.props;
const startm = moment(Date.parse(start)).format("h:mm a");
return (
<div>
<div onClick={this.handleOpen}>
{/* whatever you want to display for your event*/}
</div>
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={this.state.isModalOpen}
onClose={this.handleClose}
>
<div className={classes.paper}>
{/*whatever you want to display in the popup*/}
</div>
</Modal>
</div>
);
}
}
Then when I am instantiating my BigCalendar component I specify my event component like:
<BigCalendar
events={events}
defaultDate={new Date()}
components={{
event: CustomEvent,
}}
/>
The problem I have with this approach is that it doesn't seem to work when you click on the date header. Wouldn't overwriting the EventWrapper work a lot better :)
Downside being that you can't have access to the event object.
You are right. I just went back and checked, and I actually changed the code after posting my answer because of that problem.
I believe setting .rbc-event's z-index fixes that problem.
.rbc-event {
z-index: 999 !important;
}
Hopefully this doesn't break your styling conventions. It did break mine, but I couldn't find a better solution. Let me know if find something better.
Additionally I refactored my Calendar like so
export class Calendar extends Component {
constructor(props) {
super(props);
this.state = {
isAddModalOpen: false,
isEditModalOpen: false,
};
}
toggleAddModal = event => {
if (!this.state.isEditModalOpen) {
this.setState({
currentEvent: event,
isAddModalOpen: !this.state.isAddModalOpen,
});
}
};
toggleEditModal = event => {
if (!this.state.isAddModalOpen) {
this.setState({
currentEvent: event,
isEditModalOpen: !this.state.isEditModalOpen,
});
}
};
render() {
const { classes, toolbarVisible, defaultView } = this.props;
return (
<div className={classes.calendarWrapper}>
<BigCalendar
selectable
onSelectSlot={this.toggleAddModal}
onSelectEvent={this.toggleEditModal}
// Any other props you are using
/>
<Modal open={this.state.isAddModalOpen} toggle={this.toggleAddModal}>
// whatever is displayed when you click the calendar
</Modal>
<Modal open={this.state.isEditModalOpen} toggle={this.toggleEditModal}>
// whatever is displayed when you click an event
</Modal>
</div>
);
}
}
Sorry for the long snippet. I believe this is a better solution because my modals will contain forms that are connected components(Redux). Having one form at the Calendar level reduces unneeded connections.
I am closing this for now since the original poster is not active. Thanks @joshuawootonn for your response!
Referencing #803
@joshuawootonn Thanks for your approach; however your approach only works on modal where you can set open for your field in Material-ui or show from react-bootstrap; I'm more interested in Popover where you do not have afield where you can use state to toggle. @joshuawootonn @arecvlohe Could you please help with a popover approach; this issue seems the problem most people are facing for react-big-calendar; I appreciate your help.
Any help on this for popover or any similar solution from any CSS framework?
No update/help/direction here?!
@Amir-61 I don't understand what you are looking for. You can use the same approach for a Popover component like the modal one. Simply write a custom event component and use your framework you like the most. But you have to set your open/show state manually anyways.
I stumbled opon this issue trying to figure out correct way of introducing popovers to calendar (quite common use case). I ended up doing it like that:
export function EventPopoverWrapper({ children, popover }: Props): any {
const [anchorEl, setAnchorEl] = React.useState<HTMLDivElement | null>(null);
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? 'simple-popover' : undefined;
return (
<>
<div aria-describedby={id} onClick={handleClick}>
{children}
</div>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
>
{popover}
</Popover>
</>
);
}
Then in actual calendar:
eventWrapper: props => (
<EventPopoverWrapper
{...props}
popover={
<OffAssignmentsCalendarPopover
assignment={props.event}
userEntities={userEntities}
/>
}
/>
),
I stumbled opon this issue trying to figure out correct way of introducing popovers to calendar (quite common use case). I ended up doing it like that:
export function EventPopoverWrapper({ children, popover }: Props): any { const [anchorEl, setAnchorEl] = React.useState<HTMLDivElement | null>(null); const handleClick = (event: React.MouseEvent<HTMLDivElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; const open = Boolean(anchorEl); const id = open ? 'simple-popover' : undefined; return ( <> <div aria-describedby={id} onClick={handleClick}> {children} </div> <Popover id={id} open={open} anchorEl={anchorEl} onClose={handleClose} anchorOrigin={{ vertical: 'bottom', horizontal: 'center', }} transformOrigin={{ vertical: 'top', horizontal: 'center', }} > {popover} </Popover> </> ); }Then in actual calendar:
eventWrapper: props => ( <EventPopoverWrapper {...props} popover={ <OffAssignmentsCalendarPopover assignment={props.event} userEntities={userEntities} /> } /> ),
Awesome... will try it. Thanks!
Most helpful comment
I am closing this for now since the original poster is not active. Thanks @joshuawootonn for your response!