Vaadin FullCalendar插件addEntry功能失效问题求助
Vaadin FullCalendar 添加事件无效的解决方案
核心问题分析
你的代码存在两个关键问题导致事件无法正常添加:
- 类型不匹配:初始化的是
InMemoryEntryProvider<ResourceEntry>,但创建的事件对象是Entry类型,两者泛型类型不兼容,Provider无法正确处理非指定类型的对象。 - 重复复用同一事件实例:始终修改同一个
entryCustom对象并重复添加,Provider无法识别为新事件,甚至会引发重复引用问题。
修正后的代码实现
1. 统一事件对象类型
将Entry entryCustom = new Entry();改为ResourceEntry entryCustom = new ResourceEntry();,确保与Provider的泛型类型一致。
2. 优化Update按钮逻辑
根据需求分为两种场景处理:
场景1:每次点击添加新事件
InMemoryEntryProvider<ResourceEntry> entryProvider = new InMemoryEntryProvider<>(); calendar.setEntryProvider(entryProvider); // 事件控制布局 HorizontalLayout entryControlsLayout = new HorizontalLayout(); entryControlsLayout.setSpacing(true); entryControlsLayout.setAlignItems(Alignment.BASELINE); Select<String> selectTitle = new Select<>(); DatePicker datePickerStart = new DatePicker("inzio"); DatePicker datePickerEnd = new DatePicker("fine"); TimePicker timePicker = new TimePicker("Select Time"); TimePicker timePickerEnd = new TimePicker("Select Time"); datePickerStart.setValue(LocalDate.now()); datePickerEnd.setValue(LocalDate.now()); timePicker.setValue(LocalTime.now()); timePickerEnd.setValue(LocalTime.now()); selectTitle.setLabel("Ordina Come"); selectTitle.setItems("Primo più recente", "Rating: high to low", "Rating: low to high", "Price: high to low", "Price: low to high"); selectTitle.setValue("Primo più recente"); Button updateButton = new Button("Update", e -> { // 每次点击创建新的事件实例 ResourceEntry newEntry = new ResourceEntry(); newEntry.setTitle(selectTitle.getValue()); newEntry.setColor("#ff3333"); newEntry.setStartEditable(true); // 处理时间,确保结束时间不早于开始时间 LocalDateTime start = datePickerStart.getValue().atTime(timePicker.getValue()); LocalDateTime end = datePickerEnd.getValue().atTime(timePickerEnd.getValue()); if (end.isBefore(start)) { end = start.plusHours(1); } newEntry.setStart(start); newEntry.setEnd(end); // 使用提前定义的entryProvider,避免重复类型转换 entryProvider.addEntries(newEntry); }); Button removeButton = new Button("Remove", e -> { // 如果需要删除选中事件,可结合事件选中监听实现(见场景2) // 此处示例为删除最后添加的事件,或根据业务逻辑调整 }); entryControlsLayout.add(selectTitle, datePickerStart, datePickerEnd, timePicker, timePickerEnd, updateButton, removeButton );
场景2:编辑选中的现有事件
如果需要支持编辑日历中已选中的事件,添加事件选中监听:
// 跟踪当前编辑的事件 ResourceEntry currentEditingEntry = null; // 监听日历事件选中 calendar.addEntrySelectedListener(event -> { currentEditingEntry = event.getEntry(); // 将选中事件的信息填充到表单 selectTitle.setValue(currentEditingEntry.getTitle()); datePickerStart.setValue(currentEditingEntry.getStart().toLocalDate()); timePicker.setValue(currentEditingEntry.getStart().toLocalTime()); datePickerEnd.setValue(currentEditingEntry.getEnd().toLocalDate()); timePickerEnd.setValue(currentEditingEntry.getEnd().toLocalTime()); }); // 修改Update按钮逻辑为编辑模式 Button updateButton = new Button("Update", e -> { if (currentEditingEntry != null) { // 更新现有事件 currentEditingEntry.setTitle(selectTitle.getValue()); LocalDateTime start = datePickerStart.getValue().atTime(timePicker.getValue()); LocalDateTime end = datePickerEnd.getValue().atTime(timePickerEnd.getValue()); if (end.isBefore(start)) { end = start.plusHours(1); } currentEditingEntry.setStart(start); currentEditingEntry.setEnd(end); // 通知Provider更新事件 entryProvider.refreshEntry(currentEditingEntry); } else { // 无选中事件则添加新事件 ResourceEntry newEntry = new ResourceEntry(); newEntry.setTitle(selectTitle.getValue()); newEntry.setColor("#ff3333"); newEntry.setStartEditable(true); LocalDateTime start = datePickerStart.getValue().atTime(timePicker.getValue()); LocalDateTime end = datePickerEnd.getValue().atTime(timePickerEnd.getValue()); if (end.isBefore(start)) { end = start.plusHours(1); } newEntry.setStart(start); newEntry.setEnd(end); entryProvider.addEntries(newEntry); } }); // 修改Remove按钮逻辑 Button removeButton = new Button("Remove", e -> { if (currentEditingEntry != null) { entryProvider.removeEntries(currentEditingEntry); currentEditingEntry = null; // 清空表单 selectTitle.setValue("Primo più recente"); datePickerStart.setValue(LocalDate.now()); datePickerEnd.setValue(LocalDate.now()); timePicker.setValue(LocalTime.now()); timePickerEnd.setValue(LocalTime.now()); } });
其他注意事项
- 直接使用初始化的
entryProvider变量,避免每次调用calendar.getEntryProvider().asInMemory(),减少类型转换风险。 - 确保事件结束时间不早于开始时间,否则FullCalendar可能无法正确渲染事件。
- 原样式设置代码无问题,可保留原有逻辑。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

