为啥我的 JSF 复合方面的验证在未呈现方面时完成
Posted
技术标签:
【中文标题】为啥我的 JSF 复合方面的验证在未呈现方面时完成【英文标题】:Why are validations from my JSF composite facet being done when the facet is not rendered为什么我的 JSF 复合方面的验证在未呈现方面时完成 【发布时间】:2016-05-18 17:24:45 【问题描述】:我有一个问题,即使我不渲染复合材料,来自复合材料方面的验证也会被触发。
我将问题简化为以下准系统代码。
这里是复合entityDetailPanel
:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:common="http://java.sun.com/jsf/composite/common">
<composite:interface>
<composite:attribute name="prefix" required="true" />
<composite:facet name="lowerPanel"/>
</composite:interface>
<composite:implementation>
<h:form id="#cc.attrs.prefixentityDetailForm2"
styleClass="#cc.attrs.prefixEntityDetailPanelForm #cc.attrs.prefixListener" >
<p:messages id="#cc.attrs.prefixmessages" autoUpdate="true" closable="true"/>
<p:commandButton
value="SAVE"
update="@(.#cc.attrs.prefixListener), @(.#cc.attrs.prefixEntityDetailPanelForm"/>
<composite:renderFacet name="lowerPanel" rendered="false"/>
</h:form>
</composite:implementation>
</ui:composition>
这里是调用:
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:common="http://xmlns.jcp.org/jsf/composite/common">
<common:entityDetailPanel id="foo" prefix="Instruments">
<f:facet name="lowerPanel">
<!-- <p:inputText id="assetClassPrompt" required="true" requiredMessage="Why do we get this message?"/>-->
<p:selectOneMenu id="assetClassPrompt" required="true" requiredMessage="Why do we get this message?"
value="#instrumentController.selectedData.assetClass">
<f:selectItem itemLabel="foo" itemValue="foo"/>
<f:selectItem itemLabel="bar" itemValue="bar"/>
</p:selectOneMenu>
</f:facet>
</common:entityDetailPanel>
</ui:composition>
组合框没有显示在屏幕上(因为它没有被渲染),但是为什么我会得到一个没有被渲染的东西的验证呢?
这是我单击“保存”按钮时看到的内容:
更奇怪的是,即使在没有该组合框的其他复合调用中,我也会看到此验证错误。
我还注意到,如果我在 <messages>
标记上不包含唯一 ID,则来自复合材料的一种用途的消息将显示在复合材料的其他用途中。
这是 PrimeFaces 或 JSF 错误,还是我遗漏了什么?
您可能会注意到我有一个注释掉的<inputText>
标记。值得一提的是,当我将<selectOneMenu>
替换为<inputText>
时,我不再看到问题。
我认为这可能有助于阐明我正在尝试解决的更大问题。
我想创建类似于<p:layout>
的东西,它既有固定元素(用于复合材料的所有用途),也有非固定元素/面板,它们以参数方式传入(用于组件的每次使用)。
这是一个屏幕截图,其中 read 中指示的项目是随着组合的每次调用而变化的内容。其他所有内容始终存在于复合的所有调用中。
如你所见,参数为:
-
按钮面板(按钮因上下文而异)
要添加到表单末尾的一些附加字段(可能包含验证)
整个下部面板(可能包含验证)
值得一提的是,所有这些东西都是一起验证的(对于“SAVE”按钮),因此最好将<form>
标签放在复合输出中(包括作为参数传入的面板)。
【问题讨论】:
【参考方案1】:这个问题有两个方面。
首先,<cc:renderFacet>
从未设计为以这种方式工作。它does not 支持rendered
属性。它以某种方式起作用是因为方面在内部被重新解释为UIPanel
组件,并且所有属性(错误地)自动从标签继承。你不应该依赖它。 rendered
属性在渲染响应期间被错误地考虑,导致它“起作用”的令人困惑的行为。这在技术上是 JSF 实现中的一个错误。这些属性(正确地)不在回发期间继承,导致您观察到的问题。 “尽管”组件没有被渲染,组件仍然被解码和验证。
其次,<p:inputText>
扩展自 UIInput
,它在验证之前检查是否有 任何 提交值。 null
的提交值被解释为表单中完全没有输入字段,因此它被跳过。一个空字符串的提交值作为一个空值被插入,所以它被验证了。但是,<p:selectOneMenu>
覆盖了标准的UIInput
行为,并将null
视为空字符串。即使提交的值为null
(这意味着输入字段根本不在表单中),它仍在验证中。这在技术上是 PrimeFaces 方面的一个错误。
您的意图至少是明确的:有条件地渲染一个方面。 <cc:xxx>
标签是在 Facelets 编译期间评估的(这是视图构建时间之前的一个步骤),因此使用 JSTL <c:if>
有条件地构建 <cc:renderFacet>
也将永远无法工作。
您最好的选择是将“渲染下面板”重新定义为复合属性,并创建一个支持组件,以便在将该属性添加到视图后将其显式复制到构面中。
<cc:interface componentType="entityDetailPanelComposite">
...
<cc:facet name="lowerPanel" />
<cc:attribute name="renderLowerPanel" type="java.lang.Boolean" default="false" />
</cc:interface>
<cc:implementation>
<f:event type="postAddToView" listener="#cc.init" />
...
<cc:renderFacet name="lowerPanel" />
...
</cc:implementation>
@FacesComponent("entityDetailPanelComposite")
public class EntityDetailPanelComposite extends UINamingContainer
public void init()
UIComponent lowerPanel = getFacets().get("lowerPanel");
ValueExpression renderLowerPanel = getValueExpression("renderLowerPanel");
if (renderLowerPanel != null)
lowerPanel.setValueExpression("rendered", renderLowerPanel); // It's an EL expression.
else
lowerPanel.getAttributes().put("rendered", getAttributes().get("renderLowerPanel")); // It's a literal value, or the default value.
这有额外的好处,您可以从客户端指定它。
<my:entityDetailPanel ... renderLowerPanel="true" />
【讨论】:
BalusC,感谢您出色的解释和解决方案。我仍然对某事感到困惑。在我的精简版本中引入了带有无效渲染属性的com.example.Image
属性<my:inputFileCropImage value="#bean.image">
相关联。或者三个与(Local)Date
属性<my:inputDate value="#bean.date">
相关的d/m/y 下拉列表。我想你只想要一个带有定义/插入的标签文件。另见 a.o. ***.com/q/6822000
好的。您显然是正确的,这是一个模板而不是复合材料。我非常感谢您的投入,如果您有这样的设置,我会捐款。以上是关于为啥我的 JSF 复合方面的验证在未呈现方面时完成的主要内容,如果未能解决你的问题,请参考以下文章
JSF拒绝处理深层嵌套的复合组件。不,真的:“JSF1098:[...]这浪费了处理器时间[...]”
如何对 jsf 复合组件中的集合属性进行 bean 验证,约束不会触发