Feature request: context menu for an calendar entry
Closed this issue · 3 comments
It would be nice, if an entry in the calendar can get a context menu like other Vaadin components.
For a requirement to copy the text of the tooltip into the clipboard, I put a small snippet in the event handler for "mouseenter"of my fullcalendar-tooltip.js but maybe there are additional requirements in the future for what a context menu for such an entry would be more convenient.
...
let tooltip = e.event.getCustomProperty("tooltip", e.event.title);
// Moderne Clipboard API
navigator.clipboard.writeText(tooltip)
.then(() => {
console.log('Text copied');
})
.catch(err => {
console.error('error on copy text:', err);
});
e.el._tippy = tippy(e.el, {
...
Addition: check, if it is possible and suitable to have a general possibility to allow client side events beside the already existing ones. Maybe FC already allows the defintion of native/custom events per event, but I am not aware of that atM.
With the latest 6.2.0 it is now possible to register event handlers for native javascript events. With that you can create a custom context menu based on the clicked entry. Using the Vaadin Context Menu will most likely not be possible as that requires a Vaadin component to be targeted. Entries are not components. But you may use some overlay on your own to create a context menu like popup, e.g. with the Popup Addon
This is a sample on how to integrate a context menu for entries. It is optimizable, but should provide a good foundation for any addition content :)
@Route(...)
public void MyCalendarView extends VerticalLayout {
private Popup popup;
public MyCalendarView() {
FullCalendar calender = new FullCalendar();
// adds a contextmenu / right client event listener, that calls our openContextMenu.
// "this" is the fc object, "this.el" is the Flow element and "this.el.parentElement" is our current view.
// This hierarchy access may changed, when you nest the FC into other containers.
calendar.addEntryNativeEventListener("contextmenu",
"e => {" +
" e.preventDefault(); " +
" this.el.parentElement.$server.openContextMenu(info.event.id);" +
"}");
// by default, the entry element has no id attribute. Therefore we have to add it ourselves, using the
// entry id, that is by default an auto generated UUID
calendar.setEntryDidMountCallback("""
function(info) {
info.el.id = "entry-" + info.event.id;
}""");
}
@ClientCallable
public void openContextMenu (String id){
initPopup(); // init the popp
popup.removeAll(); // remove old content
// setup the context menu
// (side note: the list box shows a checkmark, when selecting an item, therefore you may want to use a different
// component for a real application or hide the checkmark with CSS)
ListBox<String> listBox = new ListBox<>();
listBox.setItems("Option A", "Option B", "Option C");
listBox.addValueChangeListener(event -> {
Notification.show("Selected " + event.getValue());
popup.hide();
});
popup.add(listBox);
popup.setFor("entry-" + id);
popup.show();
}
private void initPopup () {
if (popup == null) {
popup = new Popup();
popup.setFocusTrap(true);
add(popup);
}
}
}