代码之家  ›  专栏  ›  技术社区  ›  Thang Pham

Mojarra findComponent在复合组件内部时为有效id返回null

  •  1
  • Thang Pham  · 技术社区  · 12 年前

    我有一个自定义组件,如下所示

    <custom:container>
        <custom:checkbox index="0"/>
        <custom:checkbox index="1"/>
    </custom:container>
    

    因此,当encodeBegin第一次调用时,它将显示命中标记 <custom:container> ,并且它将尝试保存此组件cliend id,

    private String containerClientId;
    public void encodeBegin(FacesContext context, UIComponent component){
        if (component instanceof ManyCheckboxContainer) {            
            containerClientId = component.getClientId(context);
            return; 
        }
    }
    

    所以encodeEnd在我点击时被调用 <custom:checkbox index="0"/> ,像这样

    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
    
        ...
    
        if (component instanceof Checkbox) {
            renderCheckbox(context, (Checkbox) component);
        } 
        ...
    }
    
    protected void renderCheckbox(FacesContext facesContext, InforRadio radio) throws IOException {
        ...
        UIComponent uiComponent = radio.findComponent(containerClientId);
        if(uiComponent == null){
             //throw error
        }
        ...
    }
    

    如果我在复合组件中没有这个自定义组件,那么一切都很好,但一旦我将其放入复合组件中, radio.findComponent(containerClientId); 回来 null 。这是莫哈拉的一只虫子吗?我在2.1.10和2.1.11下测试了这一点,行为相同。

    编辑
    所以我收回这一点,当我的自定义组件位于两个嵌套中时,就会发生这种行为 NamingContainer ,所以像这样

    <h:form id="myForm">
        <f:subView id="myView">
            <custom:container id="myCustom">
                <custom:checkbox index="0"/>
                <custom:checkbox index="1"/>
            </custom:container>
        </f:subView>
    </h:form>
    

    因此在本例中,客户端id(返回 component.getClientId(context) )对于 <自定义:容器> myForm:myView:myCustom ,但在Mojarra内部 findComponent 方法有这个

    public UIComponent findComponent(String expr) {
         ...
    
         else if (!(base instanceof NamingContainer)) {
         // Relative expressions start at the closest NamingContainer or root
         while (base.getParent() != null) {
             if (base instanceof NamingContainer) {
                 break;
             }
             base = base.getParent();
         }
         ...
    }
    

    所以它在寻找下一个祖先 Naming容器 ,在我的情况下是 f:subView 不是 h:form 然后,它解析客户端id,循环通过它,每次都将id的一部分传递给 UIComponent findComponent(UIComponent base, String id, boolean checkId) 。所以第一次在,这个方法 form3 由于id和当前UIComponent是f:subView,它会搜索其所有方面和子项,以查看是否有任何组件匹配 形式3 当然,没有人能比得上 形式3 是的父级 f: 子视图 在我的结构中。所以 无效的 是返回。这是Mojarra bug还是我做错了什么。我认为客户端id是相对于下一个NamingContainer祖先的,而不是一直到NamingContainer的根?我错了吗?

    1 回复  |  直到 12 年前
        1
  •  3
  •   Eelke    12 年前

    阅读后 docs 在我看来,莫贾拉做得对。

    根据文档,如果你想从树的根进行“绝对”搜索,你应该在搜索表达式前面放一个分隔符(冒号)。 否则,如果组件本身是NamingContainer或第一个父级是NamingContainer,它将从组件本身进行相对搜索。

    顺便说一句:我链接到的文档似乎与随规范一起发布的官方文档相同。官方规格为 here