问题描述
下面code从PrimeFaces DataGrid中+的DataTable教程启发,放入<电话号码:标签>
A &LT的;电话号码:TabView的>
驻留在<电话号码:layoutUnit>
的<电话号码:布局>
。这里是code的内部(从点开始:标签
部分);外层部分是微不足道的。
The following code is inspired from PrimeFaces DataGrid + DataTable Tutorials and put into a <p:tab>
of a <p:tabView>
residing in a <p:layoutUnit>
of a <p:layout>
. Here is the inner part of the code (starting from p:tab
component); the outer part is trivial.
<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>
当我点击&LT;电话号码:commandLink&GT;
中,code停止工作并给出消息:
When I click the <p:commandLink>
, the code stops working and gives the message:
无法找到EX pression组件不稳定:显示从引用选项卡:不稳定:选择。
当我尝试同样使用&LT; F:AJAX&GT;
时,出现了不同的信息基本上是告诉相同的:
When I try the same using <f:ajax>
, it fails with a different message basically telling the same:
&LT; F:AJAX&GT;
包含未知的ID不稳定:显示无法找到它的组件的上下文选项卡:不稳定:选择
这是怎么造成的,我该怎么解决呢?
How is this caused and how can I solve it?
推荐答案
您需要在生成的HTML输出看,找出合适的客户端ID。在浏览器中打开网页,做一个单击鼠标右键,并的查看源文件的。找到感兴趣的JSF组件的HTML再presentation,并采取了 ID
作为客户端ID。可以在一个绝对的根据当前的命名容器相对的方式使用它。请参见下面的章节。
Look in HTML output for actual client ID
You need to look in the generated HTML output to find out the right client ID. Open the page in browser, do a rightclick and View Source. Locate the HTML representation of the JSF component of interest and take its id
as client ID. You can use it in an absolute of relative way depending on the current naming container. See following chapter.
请注意:如果它恰好包含重复的索引,比如 0:
,:1:
,等等(因为这是一个迭代组件内),那么你需要认识到,更新特定迭代轮并不总是支持。见回答底部上更多的细节。
Note: if it happens to contain iteration index like :0:
, :1:
, etc (because it's inside an iterating component), then you need to realize that updating a specific iteration round is not always supported. See bottom of answer for more detail on that.
如果一个你想用AJAX程序引用组件/执行/更新/渲染是相同的的父母,然后就引用自己的ID。
If a component which you'd like to reference by ajax process/execute/update/render is inside the same NamingContainer
parent, then just reference its own ID.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
如果它的不可以中的一样 NamingContainer
,则需要使用绝对客户端ID来引用它。绝对的客户端ID以 NamingContainer
分隔符,默认情况下是:
If it's not inside the same NamingContainer
, then you need to reference it using an absolute client ID. An absolute client ID starts with the NamingContainer
separator character, which is by default :
.
<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
的组件,例如&LT; H:形式GT;
,&LT; H:dataTable的&GT;
,&LT;电话号码:TabView的&GT;
,&LT; CC:实施&GT;
(因此,所有的复合材料部件)等你认出他们很容易通过查看生成的HTML输出,其ID将是prepended所有子组件生成的客户端ID。需要注意的是,当他们没有一个固定的ID,那么JSF将使用自动生成的ID在 j_idXXX
格式。你绝对应该避免给他们一个固定的ID。该 OmniFaces NoAutoGeneratedIdViewHandler
可能在这个有帮助在开发过程中。
NamingContainer
components are for example <h:form>
, <h:dataTable>
, <p:tabView>
, <cc:implementation>
(thus, all composite components), etc. You recognize them easily by looking at the generated HTML output, their ID will be prepended to the generated client ID of all child components. Note that when they don't have a fixed ID, then JSF will use an autogenerated ID in j_idXXX
format. You should absolutely avoid that by giving them a fixed ID. The OmniFaces NoAutoGeneratedIdViewHandler
may be helpful in this during development.
如果您知道找的Javadoc中的 UIComponent
有问题,那么你也可以只检查是否有它实现的接口与否。例如, 的HtmlForm
(即 UIComponent
背后&LT; H:形式GT;
标记)显示它实现 NamingContainer
,而(即 UIComponent
背后&LT ; H:panelGroup中&GT;
标签)不显示它,所以它不执行 NamingContainer
。 这里是所有标准组件的Javadoc 和这里是PrimeFaces 的javadoc的。
If you know to find the javadoc of the UIComponent
in question, then you can also just check in there whether it implements the NamingContainer
interface or not. For example, the HtmlForm
(the UIComponent
behind <h:form>
tag) shows it implements NamingContainer
, but the HtmlPanelGroup
(the UIComponent
behind <h:panelGroup>
tag) does not show it, so it does not implement NamingContainer
. Here is the javadoc of all standard components and here is the javadoc of PrimeFaces.
因此,在你的案件:
So in your case of:
<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">
1所述的生成的HTML输出; H:panelGrid的ID =显示&GT;
是这样的:
<table id="tabs:insTable:display">
您需要采取正是 ID
作为客户端ID,然后preFIX与:在
的用法更新
:
You need to take exactly that id
as client ID and then prefix with :
for usage in update
:
<p:commandLink update=":tabs:insTable:display">
引用外包括/ TAGFILE /复合
如果该命令链接是一个包含/ TAGFILE内,目标是在它之外,这样的话你不一定知道当前的命名容器命名容器父的ID,那么你就可以动态地通过 UIComponent#getNamingContainer()像这样:
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
或者,如果该命令链路是复合部件内,目标是在它之外:
Or, if this command link is inside a composite component and the target is outside it:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
或者,如果命令链接和目标都是相同的复合组件中:
Or, if both the command link and target are inside same composite component:
<p:commandLink update=":#{cc.clientId}:display">
另请参见Get父模板命名容器的ID呈现
这一切被指定为搜索EX pression的的的 UIComponent#findComponent()
的javadoc :
This all is specified as "search expression" in the UIComponent#findComponent()
javadoc:
一个的搜索EX pression 的由任一个标识符(这是完全匹配的 UIComponent
或id属性一系列这样的标识符由 UINamingContainer#getSeparatorChar
字符值链接的搜索算法应操作如下,尽管替代算法的可使用,只要最终的结果是一样的:
- 确定
UIComponent
,这将是该基地进行搜索,以尽快满足下列条件之一停止:- 如果搜索EX pression开头的分隔符(称为绝对的搜索EX pression),该基地将是根
UIComponent
。领先的分隔符将被剥离,并在对搜索前pression剩余部分将被视为如下所述相对搜索前pression。 - 否则,如果该
UIComponent
是NamingContainer
将以此为基础。 - 否则,搜索了该组件的父母。如果
NamingContainer
遇到,这将是基础。 - 否则(如果没有
NamingContainer
遇到)根UIComponent
将是基础。
- 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 aNamingContainer
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 rootUIComponent
will be the base.
- 如果搜索EX pression是一个简单的标识符,该值与id属性,然后递归地通过底座的方面和儿童
UIComponent
(但如果一个子NamingContainer
发现,自己的面和儿童不搜索)。 - 如果搜索前pression包括多于一个标识符由分隔符分隔,所述第一标识符用于定位一
NamingContainer
通过在$规则p $ pvious圆点。那么,这样做的findComponent()
方法NamingContainer
将被调用,传递搜索EX $ P $的其余部分pssion。
- 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 descendantNamingContainer
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, thefindComponent()
method of thisNamingContainer
will be called, passing the remainder of the search expression.
需要注意的是PrimeFaces还坚持了JSF规范,但RichFaces使用一些额外的例外。
Note that PrimeFaces also adheres the JSF spec, but RichFaces uses "some additional exceptions".
重新解析的用途
UIComponent.findComponent()
算法(有一些额外的例外)发现,在组件树中的组件。这些额外的例外是无处中所描述的细节,但据了解,相关的组件ID(即那些不是以
:
)不仅搜查,最接近的背景下父NamingContainer
,而且在同一个视图中的所有其他NamingContainer
成分(这是由方式相对昂贵的工作)。Those additional exceptions are nowhere in detail described, but it's known that relative component IDs (i.e. those not starting with
:
) are not only searched in the context of the closest parentNamingContainer
, but also in all otherNamingContainer
components in the same view (which is a relatively expensive job by the way).如果这一切仍然无法正常工作,然后验证,如果你不使用
&LT; H:形式prependId =假&GT;
。这将在处理过程中的AJAX提交和渲染失败。请参阅此相关的问题:<一href="http://stackoverflow.com/questions/7415230/jsf-namingcontainer-and-uiform-with-$p$ppendid">UIForm其中prependId =&QUOT;假&QUOT;休息&LT; F:。AJAX渲染&GT;If this all still doesn't work, then verify if you aren't using
<h:form prependId="false">
. This will fail during processing the ajax submit and render. See also this related question: UIForm with prependId="false" breaks <f:ajax render>.这是长时间不能引用迭代组件特定的迭代项目如
&LT; UI:重复&GT;
和&LT; H: dataTable的&GT;
像这样:It was for long time not possible to reference a specific iterated item in iterating components like
<ui:repeat>
and<h:dataTable>
like so:<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
&LT; F:AJAX&GT;
开始支持它(它只是停止验证它,因此你绝不会面对的问题上述异常了;另一种增强修复计划在稍后)。However, since Mojarra 2.2.5 the
<f:ajax>
started to support it (it simply stopped validating it; thus you would never face the in the question mentioned exception anymore; another enhancement fix is planned for that later).这只是还没有在当前的MyFaces 2.2.7和PrimeFaces 5.2版本。该支持可能会在未来的版本。在此期间,最好的办法是更新迭代组件本身,或在父母不显示HTML,如
&LT; UI:重复&GT;
This only doesn't work yet in current MyFaces 2.2.7 and PrimeFaces 5.2 versions. The support might come in the future versions. In the meanwhile, your best bet is to update the iterating component itself, or a parent in case it doesn't render HTML, like
<ui:repeat>
.PrimeFaces选择器(PFS),您可以通过jQuery的CSS选择器语法参考组件。例如。参考具有所有常见的样式类在HTML输出组件。这是如果你需要引用很多组件特别有用。这仅prerequires,目标组件在HTML输出的所有客户端ID(固定或自动生成的,并不重要)。另请参见How做PrimeFaces选择器在更新=&QUOT;(MyClass的)@&QUOT;工作?
PrimeFaces Selectors (PFS) allows you to reference components via jQuery CSS selector syntax. E.g. referencing components having all a common style class in the HTML output. This is particularly helpful in case you need to reference "a lot of" components. This only prerequires that the target components have all a client ID in the HTML output (fixed or autogenerated, doesn't matter). See also How do PrimeFaces Selectors as in update="@(.myClass)" work?
这篇关于如何找出成分为Ajax更新客户端ID /渲染?无法找到EX pression&QUOT组成部分;富&QUOT;酒吧&QUOT;从&QUOT参考;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
- If the search expression begins with the the separator character (called an "absolute" search expression), the base will be the root
- 如果搜索EX pression开头的分隔符(称为绝对的搜索EX pression),该基地将是根