11

与复合组件一起使用p:outputLabel时,我遇到了问题。我有带p:inputText字段的复合组件(我从组件中删除了不相关的部分):

<cc:interface>
  <cc:editableValueHolder name="myInput" targets="myInput"/>
  <cc:attribute name="required" required="true" type="java.lang.Boolean" default="false"/>
</cc:interface>

<cc:implementation>
  <p:inputText id="myInput" required="#{cc.attrs.required}"/>
</cc:implementation>

现在,我不会将此组件用于p:outputLabel

<p:outputLabel for="myComponent:myInput" value="#{resources['myLabel']}:"/>
<my:myComponent id="myComponent" required="#{myBean.required}"/>

一切正常,需要验证,也显示消息,但*标签上没有标志,就像我将标签直接连接到p:inputText组件时一样。另一方面,如果我required="true"对所有内容进行硬编码p:inputText都可以正常工作。

我调试org.primefaces.component.outputlabel.OutputLabelRenderer并发现该组件被识别为UIInput,但input.isRequired()返回false。进一步调试发现该required属性尚未在组件上定义,因此它返回false为默认值 i UIInput

(Boolean) getStateHelper().eval(PropertyKeys.required, false);

此外,如果我只是p:outputLabel在复合组件内移动,一切正常。就像 EL 稍后在复合组件内部进行评估?

我正在使用 Primefaces 3.5 和 Mojarra 2.1.14

4

1 回答 1

13

不幸的是,这是“设计使然”。表达式的评估#{}被推迟到访问时间的确切时刻。它们与${}JSP 中的“标准”EL 不同,它们没有在它们被标记处理程序解析并“缓存”以供将来在同一请求/视图期间访问的确切时刻进行评估。在<p:outputLabel>渲染的那一刻,因此需要评估#{cc.attrs.required}所引用的 as,在 EL 上下文中没有任何方法。所以它的任何属性都不会评估任何东西。仅当您坐在中时,EL 上下文中才可用,因此它的所有属性都会成功评估。UIInput#isRequired()#{cc}<cc:implementation>#{cc}

从技术上讲,这是<p:outputLabel>. 标准 JSF 和 EL 即按规定行事。基本上,取决于输入required属性的标签星号的表示应该以相反的方式评估:此时<p:inputText>要渲染复合材料的内部,或者甚至可能已经在构建复合材料时。因此,标签组件不应该询问输入组件是否需要它,但输入组件应该以某种方式通知标签组件它是必需的。这反过来又难以实施且笨拙(因此效率低下)。

如果将标签移动到复合内部不是一种选择,那么最好的办法是创建一个标签文件,而不是围绕输入组件创建一个复合组件。它只需要一些额外的 XML 样板。

/WEB-INF/tags/input.xhtml

<ui:composition
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:p="http://primefaces.org/ui"
>
    <c:set var="id" value="#{not empty id ? id : 'myInput'}" />
    <c:set var="required" value="#{not empty required and required}" />

    <p:inputText id="#{id}" required="#{required}"/>
</ui:composition>

/WEB-INF/my.taglib.xml

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
    version="2.0"
>
    <namespace>http://example.com/my</namespace>

    <tag>
        <tag-name>input</tag-name>
        <source>tags/input.xhtml</source>
    </tag>
</facelet-taglib>

/WEB-INF/web.xml

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>

用法:

<html ... xmlns:my="http://example.com/my">
...
<p:outputLabel for="myInput" value="#{resources['myLabel']}:" />
<my:input id="myInput" required="#{myBean.required}" />

我刚刚做了一个快速测试,它对我来说很好用。

也可以看看:

于 2013-02-25T14:43:32.403 回答