Primefaces outputLabel для составного компонента

У меня проблема с использованием 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() возвращает ложь Дальнейшая отладка обнаружила, что required атрибут еще не определен в компоненте, поэтому он возвращает false как значение по умолчанию я UIInput:

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

Кроме того, если я просто перееду p:outputLabel внутри композитного компонента все работает нормально. Как EL оценивается позже внутри составного компонента?

Я использую Primefaces 3.5 с Mojarra 2.1.14

1 ответ

Решение

Это, к сожалению, "по замыслу". Оценка #{} Выражения откладываются до точного момента времени доступа. Они не похожи на "стандартные" EL ${} в JSP не оценивается в тот момент, когда они анализируются обработчиком тега и "кэшируются" для последующего доступа во время того же запроса / представления. На данный момент <p:outputLabel> и, таким образом, #{cc.attrs.required} на что ссылается UIInput#isRequired() необходимо оценить, нет никаких средств #{cc} в контексте EL. Так что ни один из его атрибутов не оценит ни к чему. Только когда ты сидишь внутри <cc:implementation>, #{cc} доступен в контексте EL, и все его атрибуты, таким образом, будут успешно оценены.

Технически, это неудачный упущение в дизайне <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}" />

Я только что сделал быстрый тест, и он отлично работает для меня.

Смотрите также:

Другие вопросы по тегам