JSF PrimeFaces 扩展时间线:如何通过 AJAX 更新时间线?

JSF PrimeFaces Extensions Timeline: How to update a Timeline via AJAX?

我很难对时间线进行基本 AJAX 更新。

让我从一个基本示例开始,我想根据下拉列表的 selection 更新时间线的开始和结束时间:

<h:form id="form">
            <h:outputLabel for="period" value="#{str.schedule_period}"/>
            <h:selectOneMenu id="period" value="#{timelineController.period}" label="#{str.schedule_period}">
                <f:selectItems value="#{timelineController.periodWeeks}" />
                <p:ajax event="change" update="timeline" />
            </h:selectOneMenu>
            <pe:timeline id="timeline" value="#{timelineController.model}"
                         editable="true" 
                         eventMargin="0"
                         minHeight="120"
                         stackEvents="false"
                         start="#{timelineController.timelineStart}"
                         min="#{timelineControllertimelineStart}"
                         end="#{timelineController.timelineEnd}"
                         max="#{timelineController.timelineEnd}"
                         showNavigation="false" showButtonNew="false"
                         showCurrentTime="false"
                         axisOnTop="true"
                         timeZone="#{timelineController.timezone}"
                         zoomMin="28800000" 
                         dropActiveStyleClass="ui-state-highlight" dropHoverStyleClass="ui-state-hover">
                <p:ajax event="drop" listener="#{timelineController.onDrop}"
                        global="false" process="timeline"/>  
            </pe:timeline>
</h:form>

当我 select 下拉列表中的项目时,会触发 AJAX 事件并在辅助 bean 中设置句点 属性,但新值不会反映在时间轴组件。作为一种解决方法,我将时间轴包装在 p:outputPanel 中并更新了包装器,它起作用了:

...
<h:selectOneMenu id="period" value="#{timelineController.period}" label="#{str.schedule_period}">
                <f:selectItems value="#{timelineController.periodWeeks}" />
                <p:ajax event="change" update="wrapper" />
</h:selectOneMenu>
...
<p:outputPanel id="wrapper">
   <pe:timeline id="timeline" value="#{timelineController.model}"
                         editable="true" 
                         eventMargin="0"
                         minHeight="120"
                         stackEvents="false"
                         start="#{timelineController.timelineStart}"
                         min="#{timelineControllertimelineStart}"
                         end="#{timelineController.timelineEnd}"
                         max="#{timelineController.timelineEnd}"
                         showNavigation="false" showButtonNew="false"
                         showCurrentTime="false"
                         axisOnTop="true"
                         timeZone="#{timelineController.timezone}"
                         zoomMin="28800000" 
                         dropActiveStyleClass="ui-state-highlight" dropHoverStyleClass="ui-state-hover">
                <p:ajax event="drop" listener="#{timelineController.onDrop}"
                        global="false" process="wrapper"/>  
            </pe:timeline>
</p:outputPanel>

请注意,我还必须将 p:ajax 的进程属性更改为包装器。

所以我的第一个问题是:为什么不包装时间线组件就无法进行更新?

我的第二个问题是关于拖放的。正如您从我上面的代码中看到的那样,我在时间轴上附加了一个下拉监听器。在下拉列表中创建 selection 之前,我还可以从 p:dataList 拖放事件。一旦我在下拉列表中 select 一个新的时间段,时间线就会得到适当的更新,但我无法再将事件拖放到时间线(不会触发 onDrop 侦听器)。这是我的 p:dataList:

<p:dataList id="eventsList" value="#{timelineController.users}"
                        var="user" itemType="none">  
                <h:panelGroup id="eventBox" layout="box" style="z-index:9999; cursor:move;">  
                    #{user.toString()}  
                </h:panelGroup>  
                <p:draggable for="eventBox" revert="true" helper="clone" cursor="move"/>  
</p:dataList> 

知道这里出了什么问题吗?

我还包括 TimelineController class 以供参考:

@ManagedBean
@ViewScoped
public class TimelineController {
    @EJB UserService userDao;

    private TimelineModel model;
    private String name;
    private ZoneId timezone;
    private Period period;
    private Duration defaultShiftDuration;
    private LocalDateTime timelineStart;
    private LocalDateTime timelineEnd;



    @PostConstruct
    protected void initialize() {
        timezone = ZoneId.of("Europe/Berlin);
        period = Period.ofWeeks(2);
        defaultShiftDuration = Duration.ofHours(8);
        timelineStart = LocalDateTime.now().with(DayOfWeek.MONDAY).withHour(0).withMinute(0).truncatedTo(ChronoUnit.MINUTES);

        // create timeline model
        model = new TimelineModel();

    }

    public TimelineModel getModel() {
        return model;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTimezone() {
        return timezone.getId();
    }

    public void setTimezone(String timezone) {
        this.timezone = ZoneId.of(timezone);
    } 

    public List<SelectItem> getPeriodWeeks() {
        List<SelectItem> weeks = Lists.newArrayList();
        weeks.add(new SelectItem(1, "1 " + JsfUtil.getStringResource("schedule_week")));
        weeks.add(new SelectItem(2, "2 " + JsfUtil.getStringResource("schedule_weeks")));
        weeks.add(new SelectItem(3, "3 " + JsfUtil.getStringResource("schedule_weeks")));
        return weeks;
    }



    public int getPeriod() {
        return period.getDays() / 7;
    }

    public void setPeriod(int nWeeks) {
        this.period = Period.ofWeeks(nWeeks);
        timelineEnd = null;
    }

    public Date getTimelineStart() {
        return Date.from(timelineStart.atZone(timezone).toInstant());
    }

    public Date getTimelineEnd() {
        if (timelineEnd == null) {
            timelineEnd = timelineStart.plus(period);
        }
        return Date.from(timelineEnd.atZone(timezone).toInstant());
    }

    public void setStartsOn(String startsOn) {
        timelineStart = LocalDateTime.parse(startsOn + "T00:00");
        timelineEnd = null;
    }


    public List<User> getUsers(){
        return userDao.findAll();
    }

    public void onDrop(TimelineDragDropEvent e) {  
        // get dragged model object (event class) if draggable item is within a data iteration component,  
        // update event's start and end dates.  
        User user = (User) e.getData();  

        Date endDate =  Date.from(e.getStartDate().toInstant().plus(defaultShiftDuration));
        // create a timeline event (not editable)  
        TimelineEvent event = new TimelineEvent(user, e.getStartDate(), endDate, true, e.getGroup());  

        // add a new event  
        TimelineUpdater timelineUpdater = TimelineUpdater.getCurrentInstance(":form:timeline");  
        model.add(event, timelineUpdater);  

    }
 }

问题是时间轴组件中缺少 widgetVar 属性。这对我来说像是一个错误,因为我没有使用组件的客户端 API。我将在 PF 扩展项目中提交错误。