如何找出ajax更新/渲染的组件的客户端ID?找不到从“bar”引用表达式“foo”的组件

前端之家收集整理的这篇文章主要介绍了如何找出ajax更新/渲染的组件的客户端ID?找不到从“bar”引用表达式“foo”的组件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
以下代码源自PrimeFaces DataGrid DataTable教程,并放入一个< p:tab>的< p:tabView>居住在< p:layoutUnit>的< p:layout&gt ;.这里是代码的内部部分(从p:tab组件开始);外部是微不足道的。
<p:tabView id="tabs">
    <p:tab id="search" title="Search">                        
        <h:form id="insTable">
            <p:dataTable id="table" var="lndInstrument" value="#{instrumentBean.instruments}">
                <p:column>
                    <p:commandLink id="select" update="insTable:display" oncomplete="dlg.show()">
                        <f:setPropertyActionListener value="#{lndInstrument}" 
                                        target="#{instrumentBean.selectedInstrument}" />
                        <h:outputText value="#{lndInstrument.name}" />
                    </p:commandLink>                                    
                </p:column>
            </p:dataTable>
            <p:dialog id="dlg" modal="true" widgetVar="dlg">
                <h:panelGrid id="display">
                    <h:outputText value="Name:" />
                    <h:outputText value="#{instrumentBean.selectedInstrument.name}" />
                </h:panelGrid>
            </p:dialog>                            
        </h:form>
    </p:tab>
</p:tabView>

当我点击< p:commandLink&gt ;,代码停止工作,并给出消息:

Cannot find component with expression “insTable:display” referenced from “tabs:insTable:select”.

当我尝试使用< f:ajax&gt ;,它失败了一个不同的消息基本上告诉同样:

<f:ajax> contains an unknown id “insTable:display” cannot locate it in the context of the component “tabs:insTable:select”

这是怎么造成的,我该如何解决呢?

在HTML输出中查找实际的客户端ID

您需要查看生成的HTML输出以找出正确的客户端ID。在浏览器中打开页面,右键单击并查看源代码。找到感兴趣的JSF组件的HTML表示,并将其id作为客户端ID。您可以根据当前命名容器以绝对或相对的方式使用它。请参见以下章节。

注意:如果它恰好包含迭代索引,如:0 :,:1 :,etc(因为它在迭代组件中),那么您需要意识到更新特定的迭代轮并不总是被支持。有关更多详细信息,请参阅答案底部

记住NamingContainer组件,并始终为它们提供固定的ID

如果你想要由ajax process / execute / update / render引用的组件在同一个NamingContainer父级中,那么只需引用自己的ID。

<h:form id="form">
    <p:commandLink update="result"> <!-- OK! -->
    <h:panelGroup id="result" />
</h:form>

如果它不在同一个NamingContainer内,那么您需要使用绝对客户端ID来引用它。绝对客户端ID以NamingContainer分隔符开头,默认情况下:。

<h:form id="form">
    <p:commandLink update="result"> <!-- FAIL! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
    <p:commandLink update=":result"> <!-- OK! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
    <p:commandLink update=":result"> <!-- FAIL! -->
</h:form>
<h:form id="otherform">
    <h:panelGroup id="result" />
</h:form>
<h:form id="form">
    <p:commandLink update=":otherform:result"> <!-- OK! -->
</h:form>
<h:form id="otherform">
    <h:panelGroup id="result" />
</h:form>

NamingContainer组件例如< h:form>,< h:dataTable>,< p:tabView>,< cc:implementation> (因此,所有复合组件)等。您通过查看生成的HTML输出容易地识别它们,它们的ID将被预先附加到所有子组件的生成的客户端ID。请注意,当它们没有固定的ID时,JSF将使用j_idXXX格式的自动生成的ID。你应该通过给他们一个固定的ID绝对避免。 OmniFaces NoAutoGeneratedIdViewHandler在开发过程中可能对此有所帮助。

如果你知道找到有问题的UIComponent的javadoc,那么你也可以在那里检查它是否实现了NamingContainer接口。例如,HtmlForm(在< h:form>标签后面的UIComponent)显示它实现了NamingContainer,但HtmlPanelGroup(< h:panelGroup>标签后面的UIComponent)不显示它,所以它不实现NamingContainer。 Here is the javadoc of all standard componentshere is the javadoc of PrimeFaces

解决您的问题

所以在你的情况:

<p:tabView id="tabs"><!-- This is a NamingContainer -->
    <p:tab id="search"><!-- This is NOT a NamingContainer -->
        <h:form id="insTable"><!-- This is a NamingContainer -->
            <p:dialog id="dlg"><!-- This is NOT a NamingContainer -->
                <h:panelGrid id="display">

生成的HTML输出< h:panelGrid id =“display”>看起来像这样:

<table id="tabs:insTable:display">

您需要将完全相同的ID作为客户端ID,然后加上:for update in update:

<p:commandLink update=":tabs:insTable:display">

引用外部include / tagfile / composite

如果这个命令链接在一个include / tag文件中,并且目标在其外部,因此你不一定知道当前命名容器的命名容器父的ID,那么你可以通过UIComponent#getNamingContainer )像这样:

<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">

或者,如果此命令链接在复合组件内部,并且目标位于复合组件外部:

<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">

或者,如果命令链接和目标都在同一复合组件内:

<p:commandLink update=":#{cc.clientId}:display">

参见Get id of parent naming container in template for in render / update attribute

它如何在封面下工作

这一切都在the UIComponent#findComponent() javadoc中被指定为“搜索表达式”:

A search expression consists of either an identifier (which is matched exactly against the id property of a UIComponent,or a series of such identifiers linked by the UINamingContainer#getSeparatorChar character value. The search algorithm should operates as follows,though alternate alogrithms may be used as long as the end result is the same:

  • Identify the UIComponent that will be the base for searching,by stopping as soon as one of the following conditions is met:
    • If the search expression begins with the the separator character (called an “absolute” search expression),the base will be the root UIComponent of the component tree. The leading separator character will be stripped off,and the remainder of the search expression will be treated as a “relative” search expression as described below.
    • Otherwise,if this UIComponent is a NamingContainer it will serve as the basis.
    • Otherwise,search up the parents of this component. If a NamingContainer is encountered,it will be the base.
    • Otherwise (if no NamingContainer is encountered) the root UIComponent will be the base.
  • The search expression (possibly modified in the prevIoUs step) is now a “relative” search expression that will be used to locate the component (if any) that has an id that matches,within the scope of the base component. The match is performed as follows:
    • If the search expression is a simple identifier,this value is compared to the id property,and then recursively through the facets and children of the base UIComponent (except that if a descendant NamingContainer is found,its own facets and children are not searched).
    • If the search expression includes more than one identifier separated by the separator character,the first identifier is used to locate a NamingContainer by the rules in the prevIoUs bullet point. Then,the findComponent() method of this NamingContainer will be called,passing the remainder of the search expression.

注意,PrimeFaces也遵守JSF规范,但RichFaces使用“some additional exceptions”

“reRender” uses UIComponent.findComponent() algorithm (with some additional exceptions) to find the component in the component tree.

这些额外的异常没有详细描述,但是已知相对组件ID(即不以:)开头的组件ID不仅在最近的父NamingContainer的上下文中被搜索,而且在相同视图中的所有其他NamingContainer组件是一个相对昂贵的工作)。

不要使用prependId =“false”

如果这一切仍然无效,请验证您是否未使用< h:form prependId =“false”>。这将在处理ajax提交和呈现期间失败。另见这个相关问题:UIForm with prependId=”false” breaks <f:ajax render>

引用迭代组件的特定迭代轮次

很长时间以来不可能在迭代诸如< ui:repeat>等组件中引用特定的迭代项。和< h:dataTable>像这样:

<h:form id="form">
    <ui:repeat id="list" value="#{['one','two','three']}" var="item">
        <h:outputText id="item" value="#{item}" /><br/>
    </ui:repeat>

    <h:commandButton value="Update second item">
        <f:ajax render=":form:list:1:item" />
    </h:commandButton>
</h:form>

然而,由于Mojarra 2.2.5的< f:ajax>开始支持它(它只是停止验证它;因此你永远不会面临的问题提到的异常了;以后计划另一个增强修复)。

这只在当前的MyFaces 2.2.7和PrimeFaces 5.2版本中不起作用。该支持可能在未来的版本中。同时,最好的办法是更新迭代组件本身,或者如果它不呈现HTML(例如< ui:repeat>)时的父元素。

使用PrimeFaces时,请考虑搜索表达式或选择器

PrimeFaces Search Expressions允许您通过JSF组件树搜索表达式引用组件。 JSF有几个内置:

> @this:current component
> @form:parent UIForm
> @all:整个文档
> @none:nothing

PrimeFaces通过新的关键字和复合表达式支持增强了这一点:

> @parent:parent component
> @namingcontainer:parent UINamingContainer
> @widgetVar(name):由给定的widgetVar标识的组件

您还可以在复合表达式中混合这些关键字,例如@form:@parent,@this:@parent:@parent等。

PrimeFaces Selectors (PFS)在@(。someclass)允许你通过jQuery CSS选择器语法来引用组件。例如。引用在HTML输出中具有所有通用样式类的组件。这在您需要引用“很多”组件的情况下尤其有用。这只需要目标组件在HTML输出中具有所有客户端ID(固定或自动生成,无所谓)。参见How do PrimeFaces Selectors as in update=”@(.myClass)” work?

猜你在找的Ajax相关文章