在JSF primefaces中动态生成日期标签

时间:2014-11-04 10:23:57

标签: java jsf-2 primefaces

在页面中,我有一个用于priod持续时间的InputText框(月份为int)和一个用于选择初始日期的p:日历输入。 我需要从初始日期开始生成所有月份的标签(月 - 年)。 例如,如果持续时间为3且初始日期为2014年12月10日,则应生成以下三个标签: 2014年12月至2015年2月至2015年12月 我试图在没有支持bean的情况下做到这一点:

<c:forEach var="i" begin="1" end="${myBean.duration}">
                        <p:outputLabel value=" ${i+myVar} ${year+1900} " />
                        <h:panelGrid columnClasses="input, slider" columns="2">
                            <p:inputText id="inputTxt_${i}" style="width:70px;" />
                            <p:slider for="inputTxt_${i}"
                                style="padding-left: 100px; margin-left:5px">
                                <p:ajax event="slideEnd" />
                            </p:slider>
                        </h:panelGrid>

但是这样我无法正确生成标签。 任何人都知道如何使用JSF或Backing bean,无论是否有提交按钮(例如使用event =“keyup”或event =“dateSelect”等事件)?

2 个答案:

答案 0 :(得分:2)

每当我像你想做的那样做动态jsf-stuff时,我倾向于通过支持bean在java中创建组件。这主要是因为我觉得在一种既定的编程语言中编写条件语句或循环更为舒服,结果在我看来更容易理解。 为此,您需要定义一个绑定到辅助bean的组件。 JSF将在创建时使用setter方法将该元素插入到bean中,并在每次更新时通过相应的getter检索它。在这两者之间,您基本上可以对组件执行任何操作。这包括删除和添加子项,更改属性等。 因此,在您的情况下,您可以按如下方式定义html标记:

<h:form id="dateform">
    <!-- calendar for setting the date -->
    <p:calendar value="#{backingbean.date}">
        <p:ajax event="change" update=":#{p:component('dateform')}" />
    </p:calendar>
    <!-- input for setting the duration -->
    <p:inputText value="#{backingbean.duration}">
        <p:ajax event="change" update=":#{p:component('dateform')}" />
    </p:inputText>
    <!-- panel for printing the labels, bound to a backingbean -->
    <p:outputPanel binding="#{backingbean.labelPanel}" />
</h:form>

这里的重要部分是primefaces库提供的outputPanel。它的内容将绑定到backing-bean,并在日历或持续时间的值发生变化时更新。对于支持bean,除了日期和持续时间的setter和getter之外,还需要labelPanel的getter和setter,以便JSF能够将组件填充到bean中:

private Date date;
private int duration;
private OutputPanel panel;

public Date getDate() {
    return this.date;
}

public void setDate(Date date) {
    this.date = date;
    this.updatePanel();
}

public int getDuration() {
    return this.duration;
}

public void setDuration(int duration) {
    this.duration = duration;
    this.updatePanel();
}

public OutputPanel getLabelPanel() {
    return this.panel;
}

public void setLabelPanel(OutputPanel panel) {
    this.panel = panel;
}

private void updatePanel() {
    if (this.panel != null) {
        this.panel.getChildren().clear();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(this.date);
        for (int i = 0; i < this.duration; i++) {
            calendar.add(Calendar.MONTH, 1);
            OutputLabel label = new OutputLabel();
            label.setValue(calendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault()));
            this.panel.getChildren().add(label);
        }
    }
}

正如您所看到的,每次调用日期或持续时间的setter时,代码都会动态构建OutputLabel元素并将它们添加到您的bean管理的OutputPanel中。

我确定你的问题有很多其他解决方案,但这是我个人实现这一点的方式,它通常可以正常工作。

答案 1 :(得分:2)

我认为你的xhtml-Structure不正确。

  • 您错过了结束</c:forEach>
  • 如果在代码段末尾关闭,您将获得{i}幻灯片

假设您想要一个滑块和{i}日期输出

  • 建立一个BackingBean来保存您的值
  • 值为:&#34; monthCount&#34;持有整数,&#34; dateList&#34;持有(计算的)日期
  • listener - 根据滑块public void listenerMonthCount(SlideEndEvent ae)的整数输入计算日期的方法

    <h:form id="form">
        <h:panelGrid columns="2">
            <p:inputText id="monthCount" style="width:70px;" value="#{backingBean.monthCount}" />
            <p:slider for="monthCount" style="padding-left: 100px; margin-left:5px" maxValue="12">
                <p:ajax event="slideEnd" process="@form" listener="#{backingBean.listenerMonthCount}" update="form" />
            </p:slider>
        </h:panelGrid>
        <ui:repeat var="month" value="#{backingBean.dateList}">
            <h:outputText value="#{month}">
                <f:convertDateTime pattern="MMM-yyyy" />
            </h:outputText>
            <br />
        </ui:repeat>
    </h:form>
    

更详细的解释: p:ajax - 标签不仅需要event - 属性,还需要告知要做什么。因此,定义监听器listener="#{backingBean.listenerMonthCount}"。要使侦听器知道新选择的monthValue,必须将其传送到服务器process="@form"用于将此表单中的所有值从客户端传输到服务器。 update="form"指示在处理侦听器后更新所有值。

<ui:repeat> - 块包含输出的渲染。它遍历List<Date>并将每个项目分配给变量month。这是使用f:convertDataTime打印和格式化的,它将Java-DateFormatPattern作为pattern - 属性。

在你的Backing-Bean中你基本上需要这个

private int monthCount = 0; // +getter/setter

private List<Date> dateList = new ArrayList<Date>(); // +getter/setter

public void listenerMonthCount(SlideEndEvent ae) {
    dateList.clear(); // clear the list to remove entries from possible old runs
    if (monthCount > 0) {
        Date now = new Date();
        dateList.add(now); // add first date
        Calendar cal = Calendar.getInstance();
        for (int i = 1; i < monthCount; i++) {
            cal.setTime(dateList.get(dateList.size() - 1)); // get last date from list and set calendar
            cal.add(Calendar.MONTH, 1);// add one month
            dateList.add(cal.getTime()); // add calculated date
        }
    }
}