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}" />
Я только что сделал быстрый тест, и он отлично работает для меня.