Primefaces outputLabel for composite component

前端 未结 1 625
时光说笑
时光说笑 2020-12-14 04:40

I have an issue with using p:outputLabel when used with composite component. I have composite component with p:inputText field (I removed irrelevan

相关标签:
1条回答
  • 2020-12-14 05:13

    This is, unfortunately, "by design". The evaluation of the #{} expressions is deferred to the exact moment of the access-time. They're unlike "standard" EL ${} in JSP not evaluated at the exact moment they're been parsed by the tag handler and "cached" for future access during the same request/view. At the moment the <p:outputLabel> is rendered, and thus the #{cc.attrs.required} as referenced by UIInput#isRequired() needs to be evaluated, there's no means of any #{cc} in the EL context. So any of its attributes would not evaluate to anything. Only when you're sitting inside the <cc:implementation>, the #{cc} is available in the EL context and all of its attribues would thus successfully evaluate.

    Technically, this is an unfortunate corner case oversight in the design of <p:outputLabel>. Standard JSF and EL are namely behaving as specified. Basically, the presentation of the label's asterisk depending on the input's required attribute should be evaluated the other way round: at the moment the <p:inputText> inside the composite is to be rendered or perhaps even already when it's to be built. Thus, the label component should not ask the input component if it's required, but the input component should somehow notify the label component that it's required. This is in turn hard and clumsy (and thus inefficient) to implement.

    If moving the label to inside the composite is not an option, then your best bet is to create a tag file instead of a composite component around the input component. It only requires some additional XML boilerplate.

    /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>
    

    Usage:

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

    I just did a quick test and it works fine for me.

    See also:

    • When to use <ui:include>, tag files, composite components and/or custom components?
    0 讨论(0)
提交回复
热议问题