下面的代码是从PrimeFaces的DataGrid + DataTable的教程启发和放入<p:tab>
一个的<p:tabView>
居住在<p:layoutUnit>
的<p:layout>
.这是代码的内部部分(从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>
Run Code Online (Sandbox Code Playgroud)
当我单击时<p:commandLink>
,代码停止工作并给出消息:
找不到表达式为"insTable:display"的组件,引用自"tabs:insTable:select".
当我尝试相同的使用时<f:ajax>
,它失败了,基本上告诉相同的不同消息:
<f:ajax>
包含一个未知的id"insTable:display"无法在组件"tabs:insTable:select"的上下文中找到它
这是怎么造成的,我该如何解决?
我对这个事实背后的想法有一个疑问,即只有UIForm
属性prependId
.为什么NamingContainer
界面中没有指定属性?你现在可能会说这是因为后向兼容性但我宁愿打破兼容性并让实现该接口的用户也实现prependId的方法.
从我对UIForm
组件中的prependId的观点来看,主要的问题是它会破坏findComponent()
我希望如果我使用prependId
,那么NamingContainer
行为会改变,不仅与渲染有关,而且在想要在组件树中搜索组件时也是如此.
这是一个简单的例子:
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
Run Code Online (Sandbox Code Playgroud)
现在,当我想获得panelGroup组件时,我希望将字符串传递"group"
给方法findComponent()
,但它不会找到任何东西,我必须使用"test:group"
.
具体问题是,当使用ajax时prependId="false"
.ajax标记在属性更新和处理中期望值关注命名容器.有点奇怪的是,当我使用它时prependId="false"
,我必须指定完整的id或路径,但没关系.
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
<h:form id="test1" prependId="false">
<h:commandButton value="go">
<f:ajax render="test:group"/>
</h:commandButton>
</h:form>
Run Code Online (Sandbox Code Playgroud)
那么这段代码将呈现没有问题,但它不会更新panelGroup,因为它无法找到它.在PartialViewContext
将只包含ID "group"
为renderIds的元素.我不知道这是否是预期的,可能是但我不知道代码.现在我们到了方法findComponent()
无法找到组件的位置,因为作为参数传递的表达式是"group"
方法期望"test:group"
找到组件的位置.
一种解决方案是编写自己的解决方案,findComponent()
这是我选择处理此问题的方式.在这个方法中,我处理一个组件,它是一个NamingContainer
并且具有属性prependId像正常一样设置为false UIComponent
.我将不得不为每个UIComponent
提供prependId属性的事情做到这一点,这很糟糕.反射将有助于绕过类型的静态定义,但它仍然不是一个非常干净的解决方案.
另一种方法是在NamingContainer
接口中引入prependId属性,并改变行为,findComponent()
如上所述.
最后提出的解决方案是改变ajax标记的行为以传递整个id,但这只能解决ajax问题而不是findComponent()
实现背后的程序问题.
你怎么看待这个以及它为什么会这样实现呢?我不能成为第一个遇到这个问题的人,但是我找不到相关的主题?!
我发现NamingContainer
JSF 中有一些东西叫做.目前尚不清楚哪个组件是命名容器.据我所知,<h:form>
,<h:dataTable>
和自定义组件的命名容器.
我在哪里可以获得实现的类列表javax.faces.component.NamingContainer
?