Search code examples
jsf-2attributesfaceletstagfileconditional-rendering

Conditional render in tagfile depending on whether the attribute is specified or not


I have a Facelet tagfile and need to render different components depending on whether the attribute is specified or not. I tried it as below,

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui"
    xmlns:pe="http://primefaces.org/ui/extensions"
    xmlns:c="http://java.sun.com/jsp/jstl/core">

    <h:panelGrid columns="1">
        <p:outputLabel value="test1" rendered="#{empty myParam}" />
        <p:outputLabel value="test2" rendered="#{not empty myParam}" />
    </h:panelGrid>
</ui:composition>

Which is used as below,

<mt:myTag myParam="#{myManagedBean.someProperty}" />

However, it didn't work. It takes the evaluated value of #{myManagedBean.someProperty}. If it's empty, then it still shows test1. How can I check if the myParam attribute is actually being set or not?


Solution

  • Create another custom tag with a taghandler class which checks the presence of a certain attribute in the variable mapper of the current Facelet context, and sets a boolean in the Facelet scope indicating the presence of the desired attribute. Finally make use of it in your tagfile.

    E.g.

    <my:checkAttributePresent name="myParam" var="myParamPresent" />
    <h:panelGrid columns="1">
        <p:outputLabel value="test1" rendered="#{not myParamPresent}" />
        <p:outputLabel value="test2" rendered="#{myParamPresent}" />
    </h:panelGrid>
    

    With this tag handler:

    public class CheckAttributePresentHandler extends TagHandler {
    
        private String name;
        private String var;
    
        public CheckAttributePresentHandler(TagConfig config) {
            super(config);
            name = getRequiredAttribute("name").getValue();
            var = getRequiredAttribute("var").getValue();
        }
    
        @Override
        public void apply(FaceletContext context, UIComponent parent) throws IOException {
            context.setAttribute(var, context.getVariableMapper().resolveVariable(name) != null);
        }
    
    }
    

    Which is registered as below in your .taglib.xml:

    <tag>
        <tag-name>checkAttributePresent</tag-name>
        <handler-class>com.example.CheckAttributePresentHandler</handler-class>
        <attribute>
            <name>name</name>
            <required>true</required>
            <type>java.lang.String</type>
        </attribute>
        <attribute>
            <name>var</name>
            <required>true</required>
            <type>java.lang.String</type>
        </attribute>
    </tag>