2013-10-28 47 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

相关问题