jsf composite - 迭代元素的ajax行为

时间:2013-12-22 15:14:18

标签: jsf jsf-2

(在本例中我们使用primefaces组件,但问题与Primefaces无关)

简介

为了对复合组件元素提供ajax支持,我们只使用element:

  • 复合:clientBehavior

让我们看看这种情况:

<composite:interface>
    <composite:clientBehavior name="dateSelect" event="dateSelect" targets="id111 id222" /> 
</composite:interface>  

<composite:implementation>

    <p:calendar id="id111" value="#{csController.selectedDate}" mode="inline"
                mindate="#{csController.minDate(2013,9)}"
                maxdate="#{csController.maxDate(2013,9)}"/>

    <p:calendar id="id222" value="#{csController.selectedDate}" mode="inline"
                mindate="#{csController.minDate(2013,10)}"
                maxdate="#{csController.maxDate(2013,10)}"/>

</composite:implementation>

我们对这两个元素有两个元素和ajax支持。这按预期工作。 我们甚至可以改为这个界面:

<composite:interface>
    <composite:clientBehavior name="dateSelect" event="dateSelect" targets="id111" />
    <composite:clientBehavior name="dateSelect" event="dateSelect" targets="id222" />   
</composite:interface>

这仍然可以正常工作。

问题:

我想更改实现以显示自定义的日历数量,而不是如上所示的exaclty两个。所以我尝试了这个:

<composite:interface>
    <composite:attribute name="firstMonth" default="1"/>
    <composite:attribute name="lastMonth" default="12"/>

    <c:forEach var="i" begin="#{cc.attrs.firstMonth}" end="#{cc.attrs.lastMonth}">
        <composite:clientBehavior name="dateSelect" event="dateSelect" targets="#{cc.clientId}#{i}"/>
    </c:forEach>

</composite:interface>

<composite:implementation>

    <c:forEach var="i" begin="#{cc.attrs.firstMonth}" end="#{cc.attrs.lastMonth}">

            <p:calendar id="#{cc.clientId}#{i}" value="#{csController.selectedDate}" mode="inline"
                mindate="#{csController.minDate(2013,i)}"
                maxdate="#{csController.maxDate(2013,i)}"/>

    </c:forEach>
</composite:implementation>

这当然不起作用。

问题:

如何获得c:forEach循环生成的所有元素的ajax支持?

1 个答案:

答案 0 :(得分:1)

实际上,您无需按照该过程为组件添加ajax功能。只需在您的日历中使用f:ajax即可。当c:forEach在它之前工作时,这不是问题:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:cc="http://java.sun.com/jsf/composite"
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jsp/jstl/core">
<cc:interface>
    <cc:attribute name="val" />
</cc:interface>

<cc:implementation>
    <c:forEach var="date" items="#{cc.attrs.val}">
        <p:calendar value="#{date}" mode="inline">
            <f:ajax event="dateSelect" listener="#{bean.printCurrentValues}" />
        </p:calendar>
    </c:forEach>

</cc:implementation>
</html>

成为主页:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:composite="http://java.sun.com/jsf/composite/composites">
<h:head />
<h:body>
    <h:form>
        <composite:comp val="#{bean.calendars}" />
    </h:form>
</h:body>
</html>

我将这个监听器方法添加到bean中,以检查当前日期是否真正发生了变化:

@ManagedBean
@ViewScoped
public class Bean {

    public List<Date> calendars = Arrays.asList(new Date(), new Date());

    public List<Date> getCalendars() {
        return calendars;
    }

    /**
     * Just prints the updated values ;-)
     */
    public void printCurrentValues() {
        System.out.println("Current selected dates: " + calendars);
    }
}

对于您的具体情况,您只需要添加minDates列表和maxDates中的其他列表,以便将它们绑定到您的calendar属性。或者,您也可以创建自己的类来包装它们以包装所有内容。这是你自己的选择。


上面的解决方案适用于dateSelect事件和提供的侦听器。如果我们想要与不同的听众进行不同的活动怎么办?

只需在界面上定义它们并允许使用JSTL的c:if拒绝它们。在这里,您可以获得单个输入的复合实现,该输入可以启动侦听器方法,也可以是动态数量的p:calendar组件,它将通知用户定义的方法。 默认情况下,它们都没有启动。

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:cc="http://java.sun.com/jsf/composite"
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jsp/jstl/core">
<cc:interface>
    <cc:attribute name="dateSelect" default="false" />
    <cc:attribute name="click" default="false" />
    <cc:attribute name="dateSelectListener" method-signature="void f()" />
    <cc:attribute name="inputClickedListener" method-signature="void f()" />
    <cc:attribute name="val" />
</cc:interface>

<cc:implementation>
    <h:inputText>
        <c:if test="#{cc.attrs.click}">
            <f:ajax event="click" listener="#{cc.attrs.inputClickedListener}" />
        </c:if>
    </h:inputText>
    <c:forEach var="date" items="#{cc.attrs.val}">
        <p:calendar value="#{date}" mode="inline">
            <c:if test="#{cc.attrs.dateSelect}">
                <f:ajax event="dateSelect" listener="#{cc.attrs.dateSelectListener}" />
            </c:if>
        </p:calendar>
    </c:forEach>
</cc:implementation>
</html>

这里是主页:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:composite="http://java.sun.com/jsf/composite/composites">
<h:head />
<h:body>
    <h:form>
        <composite:comp val="#{bean.calendars}" dateSelect="true"
            dateSelectListener="#{bean.printCurrentValues}" click="true"
            inputClickedListener="#{bean.inputClicked}" />
    </h:form>
</h:body>
</html>

使用Mojarra JSF 2.1.25测试&amp; Tomcat 7。