2013-12-22 93 views
2

(在這個例子中,我們使用primefaces組件,但問題是不與Primefaces相關)JSF組合 - 迭代元素AJAX行爲

簡介:

爲了對複合材料部件元素Ajax支持我們只是使用元素:

  • 複合: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> 

這當然不起作用。

問:

如何獲得通過中生成的所有元素的AJAX支持:forEach循環?

回答

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拒絕它們。在這裏,您可以爲單個輸入實現組合實現,該輸入可以啓動偵聽器方法,也可以是組件的動態編號,它將通知用戶定義的方法。 默認情況下,它們都不會啓動。

<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> 

測試與鑽嘴魚科JSF 2.1.25 &的Tomcat 7

+0

如果我們想要添加更多屬性到ajax,我們必須編輯複合組件,例如添加'onchange'(在一般情況下講話,不特別是日曆)。這裏的解決方案非常具體,我認爲,即時生成clientBehavior會很好。我厭倦了在問題中使用相同的示例,主要問題是如果實現標記(例如日曆)沒有預先評估的ID,它將無法工作! –

+0

@HatemAlimam,這是一個很好的觀點。我要更新我的答案,我認爲不可能在OP的建議方式上隨時添加ajax行爲。然而,看起來像一個解決方案似乎是有一個可能的Ajax行爲事件,並定義它們中的哪一個使用和他們的接口上的監聽器。 –

+1

@Xtreme Biker,看起來你是對的,在不可能的atm上動態添加ajax行爲。根據輸入屬性,至少不可能。但你的第二個解決方案看起來很好。我會這樣做。謝謝。 – Hubert