【问题标题】:force jsf to render autogenerated clientid强制jsf呈现自动生成的clientid
【发布时间】:2013-01-28 16:17:48
【问题描述】:

我使用组件绑定和 clientId 属性在我的 javascript 代码中查找组件,如下所示:

<div data-for="@parent" data-example="#{componentBindings.myInput.clientId}" />
...
<h:inputText binding="#{componentBindings.myInput}" value="#{myBean.myProperty}" />

唯一的问题是,jsf有时不会渲染inputText字段的id属性,所以即使我知道js代码中的clientId,我也找不到该元素,因为它在客户端没有id属性一边。

  1. 渲染自动生成的 id标签有什么要求?
  2. 有没有办法让jsf自动渲染所有的cliendId-s? (如 faces-config 条目)
  3. 有什么方法可以确保呈现单个元素的 clientId(无需显式为其指定 id)?

更新

我发现了一个诡计:

<span id="#{componentBindings.myInput.clientId}">
    <h:inputText binding="#{componentBindings.myInput}" value="#{myBean.myProperty}" />
</span>

虽然在这种情况下有更好的方法,例如使用建议的名称,但如果它不是您希望使用 ajax 呈现的输入字段,它会很有用。以方面为例:

<!-- myComponent.xhtml -->
<!-- ... -->
<cc:interface>
    <cc:facet name="someFacet" required="true" />
</cc:interface>
<cc:implementation>
    <h:form>
        <cc:renderFacet name="someFacet"/>
    </h:form>
</cc:implementation>

<!-- page.xhtml -->
<!-- ... -->
<my:myComponent>
    <f:facet name="someFacet">
        <h:inputText />
        <!-- ... -->
    </f:facet>
</my:myComponent>

如果您查看组件树,您会看到,构面没有嵌套在表单中,它是 cc 的直接子代。所以用ajax执行cc就好了:

<!-- myComponent.xhtml -->
<!-- ... -->
<cc:interface>
    <cc:facet name="someFacet" required="true" />
</cc:interface>
<cc:implementation>
    <h:form>
        <cc:renderFacet name="someFacet"/>
        <h:commandLink>
            <f:ajax execute=":#{cc.clientId}" render=":#{cc.clientId}" />
        </h:commandLink>
    </h:form>
</cc:implementation>

但这会引发格式错误的 xml 异常,因为在客户端没有具有请求 id 的元素。有了这个技巧,你可以让它工作:

<cc:interface>
    <cc:facet name="someFacet" required="true" preferred="true"/>
</cc:interface>

<cc:implementation>
    <span id=#{cc.clientId}>
        <h:form>
            <cc:renderFacet name="someFacet"/>
            <h:commandLink>
                <f:ajax execute=":#{cc.clientId}" render=":#{cc.clientId}" />
            </h:commandLink>
        </h:form>
    </span>
</cc:implementation>

我可能不是第一个发现这个解决方法的人,但我决定分享它,因为我在任何地方都没有找到它

【问题讨论】:

    标签: jsf client-side clientid


    【解决方案1】:

    来自 Mojarra 的 HtmlBasicRenderer 源代码(从 2.1.17 的第 672 行开始):

    /**
     * @param component the component of interest
     *
     * @return true if this renderer should render an id attribute.
     */
    protected boolean shouldWriteIdAttribute(UIComponent component) {
    
        // By default we only write the id attribute if:
        //
        // - We have a non-auto-generated id, or...
        // - We have client behaviors.
        //
        // We assume that if client behaviors are present, they
        // may need access to the id (AjaxBehavior certainly does).
    
        String id;
        return (null != (id = component.getId()) &&
                    (!id.startsWith(UIViewRoot.UNIQUE_ID_PREFIX) ||
                        ((component instanceof ClientBehaviorHolder) &&
                          !((ClientBehaviorHolder)component).getClientBehaviors().isEmpty())));
    }
    

    因此,如果组件具有 id 属性集或组件具有客户端行为持有者(阅读:&lt;f:ajax&gt; 子级),它只会呈现 HTML 元素的 id 属性。

    所以,你真的需要自己指定:

    <h:inputText id="foo" ... />
    

    否则,请更改您的 JS 代码,使其通过 name 而不是 id 选择输入。

    【讨论】:

      猜你喜欢
      • 2013-09-10
      • 1970-01-01
      • 2018-08-25
      • 1970-01-01
      • 2015-08-25
      • 1970-01-01
      • 2021-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多