我创建了一些Facelets来简化我们的页面的开发。特别是,我为输入组件创建了一系列Facelets。我有1个Facelet,<xxx:input />
在输入字段周围显示标签。除此之外,我还使用了诸如<xxx:inputText />
和<xxx:inputSecret />
之类的Facelets来渲染实际的输入字段。这些都使用<xxx:input />
来显示标签。 Facelet看起来像这样:
<html ...>
<composite:interface>
...
</composite:interface>
<composite:implementation>
<label><h:outputText value="#{cc.attrs.labelText}" /></label>
<composite:insertChildren />
</composite:implementation>
</html>
然后
<xxx:inputText />
Facelet看起来像这样...<html ...>
<composite:interface>
...
</composite:interface>
<composite:implementation>
<xxx:input labelText=...>
<h:inputText id="myinput" ... />
</xxx:input>
</composite:implementation>
</html>
一切都可以正常显示,但是尝试添加
<f:validator />
或其他验证标签时遇到了麻烦。从阅读的内容来看,我必须在Facelet中添加标签。因此,我在接口部分添加了<composite:editableValueHolder name="myinput" targets="myinput" />
行。但是,我仍然看不到我的验证器被解雇。我的.xhtml文件中有类似的内容... ...
<xxx:inputText value="...">
<f:validateLength minimum="10" for="myinput" />
</xxx:inputText>
...
无论我输入什么输入,验证器似乎都不会触发,也永远不会收到错误消息。一位同事建议,这是由于我使用的目标ID以及它由
<xxx:input />
Facelet包裹的事实所致。我是否需要在目标定义中包含父组件ID?还有其他我想念的东西吗?如果我排除
<xxx:input />
Facelet,它就可以正常工作,所以我假设它与此有关,但不知道如何解决。非常感谢您提供的任何帮助。 最佳答案
您需要指定验证器的for
属性以匹配name
的<composite:editableValueHolder>
。
<xxx:inputText value="...">
<f:validateLength for="myinput" minimum="10" />
</xxx:inputText>
您还需要确保在两个组合中都指定了
<composite:editableValueHolder>
,因此也要指定input.xhtml
。这是一个完整的示例,在Mojarra 2.1.12上对我来说效果很好:/resources/components/input.xhtml
:<ui:component
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:cc="http://java.sun.com/jsf/composite"
>
<cc:interface>
<cc:attribute name="label" required="true" />
<cc:editableValueHolder name="input" targets="input" />
</cc:interface>
<cc:implementation>
<h:outputLabel for="input" value="#{cc.attrs.label}" />
<cc:insertChildren />
</cc:implementation>
</ui:component>
/resources/components/inputText.xhtml
:<ui:component
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:my="http://java.sun.com/jsf/composite/components"
>
<cc:interface>
<cc:attribute name="label" required="true" />
<cc:attribute name="value" required="true" />
<cc:editableValueHolder name="input" targets="input:text" />
</cc:interface>
<cc:implementation>
<my:input id="input" label="#{cc.attrs.label}">
<h:inputText id="text" value="#{cc.attrs.value}" />
</my:input>
</cc:implementation>
</ui:component>
在某些
test.xhtml
中的用法:<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:my="http://java.sun.com/jsf/composite/components"
>
<h:head>
<title>SO question 12188638</title>
</h:head>
<h:body>
<h:form>
<my:inputText label="foo" value="#{bean.input}">
<f:validateLength minimum="10" for="input" />
</my:inputText>
<h:commandButton value="submit" action="#{bean.submit}">
<f:ajax execute="@form" render="@form"/>
</h:commandButton>
<h:messages/>
</h:form>
</h:body>
</html>
也可以看看:
How to specify a validator for an input component inside a composite component?
与具体问题无关,您知道
<h:outputLabel>
吗?<h:outputLabel value="#{cc.attrs.labelText}" />
您是否可以直接在模板文本中内嵌EL而无需显式使用
<h:outputText>
的事实呢?<label>#{cc.attrs.labelText}</label>
您是否注意到您的标签还缺少
for
属性,该属性应引用标签应引用的输入元素的ID?<h:outputLabel for="someId" ... />
<h:inputText id="someId" ... />