2013-10-28 42 views
4

我嘗試寫我自己的樹組件。樹節點呈現爲樹組件的包含分區子組件,例如:如何實現NamingContainer?所有的孩子都得到相同的客戶端ID

<my:tree id="extendedTree" 
     value="#{controller.rootNode}" 
     var="node"> 
    <h:outputText id="xxx" value="#{node.name}" /> 
    <h:commandLink value="Test" actionListener="#{controller.nodeSelectionActionListener}" /> 
</my:tree> 

到目前爲止,一切都很好 - 一切正常,但h:outputText重複得到相同的ID。
所以,我有我的組件實現javax.faces.NamingController,覆蓋getContainerClientId()

@Override 
public String getContainerClientId(FacesContext context) { 
    String clientId = super.getClientId(context); 
    String containerClientId = clientId + ":" + index; 
    return containerClientId; 
} 

index被遍歷所有節點期間設置和更新。但是getContainerClientId()對於每個孩子只會被調用一次(不是每個迭代和每個孩子都如我所料)。這導致每個孩子ID與同一容器ID前綴:

form:treeid:0:xxx 

同樣的事情覆蓋getClientId()

我錯過了什麼?

+0

我謙卑的請求去了庫拉索島,有人知道答案嗎? :) – Zeemee

回答

5

答案就藏在第3.1.6章的JSF 1.2 specification底部:

3.1.6客戶端標識符

...

從這個方法返回的值必須是除非調用setId(),否則 組件實例的壽命相同,在這種情況下,將通過下一次調用getClientId()重新計算 。

在換句話說,getClientId()結果是在默認情況下由JSF組件緩存爲UIComponentBase#getClientId()實現(也見line 275 as it is in Mojarra 1.2_15的nullcheck),當UIComponentBase#setId()稱爲該緩存重置了(見line 358 as it is in Mojarra 1.2_15)。只要您不重置緩存的客戶端ID,它就會在每個getClientId()調用中返回相同的值。

所以,在渲染的孩子encodeChildren()實現您的組件或渲染器,將最有可能是這樣的,

for (UIComponent child : getChildren()) { 
    child.encodeAll(context); 
} 

,你應該爲每一個孩子是調用UIComponent#setId()UIComponent#getId()結果重置

for (UIComponent child : getChildren()) { 
    child.setId(child.getId()); 
    child.encodeAll(context); 
} 

<h:dataTable>實現背後的UIData類做:編碼孩子之前內部緩存客戶端ID順便說一下(見line 1382 as it is in Mojarra 1.2_15)。請注意,這不是JSF 1.x特有的,同樣適用於JSF 2.x(也適用於Facelets <ui:repeat>後面的UIRepeat類)。

-1

h:outputText id給你相同的,因爲你沒有使它動態。您可以創建它:

<h:outputText id="xxx_#{node.id}" value="#{node.name}" /> 

假設節點具有唯一的'id'屬性。

+0

我的組件應該複製其他NamingContainers(例如UIData)的行爲:沒有必要將ID設置爲動態,因爲它們自動使用行ID(索引在我的情況下)作爲前綴。 – Zeemee

+0

這絕對不行。 ID屬性在視圖編譯期間被評估,而''顯然是一個UI組件,而不是標籤處理器。請勿在實際重新創建並在當地沙箱環境中解決問題的情況下發布答案。 – BalusC

+0

@BalusC謝謝你,但是什麼可以工作呢? – Zeemee

相關問題