Primefaces outputLabel用于复合组件

par*_*lov 11 primefaces composite-component jsf-2

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>
Run Code Online (Sandbox Code Playgroud)

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

<p:outputLabel for="myComponent:myInput" value="#{resources['myLabel']}:"/>
<my:myComponent id="myComponent" required="#{myBean.required}"/>
Run Code Online (Sandbox Code Playgroud)

一切正常,需要验证,也会显示消息,但*标签上没有标记,因为我将标签直接连接到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);
Run Code Online (Sandbox Code Playgroud)

此外,如果我只是p:outputLabel在复合组件内移动一切正常.像EL一样,后来在复合元件内进行评估?

我正在使用Primefaces 3.5和Mojarra 2.1.14

Bal*_*usC 13

不幸的是,这是"按设计".#{}表达式的评估被推迟到访问时间的确切时刻.他们不像"标准" EL ${}在JSP 没有在他们被标记处理程序解析和"缓存"进行同样的请求/视图在未来的访问的确切时刻评估.在<p:outputLabel>渲染时,因此需要评估#{cc.attrs.required}所引用的那些,在EL上下文中UIInput#isRequired()没有任何方法#{cc}.所以它的任何属性都不会评估任何东西.只有当你坐在里面<cc:implementation>,将#{cc}在EL背景信息,并将其所有attribues都会从而成功地评估.

从技术上讲,这是一个不幸的角落案例监督设计<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>
Run Code Online (Sandbox Code Playgroud)

/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>
Run Code Online (Sandbox Code Playgroud)

/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>
Run Code Online (Sandbox Code Playgroud)

用法:

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

我只是做了一个快速测试,它对我来说很好.

也可以看看: