1

I want to create my custom composite component in JSF (with primefaces) that shows a label in front of an input an adds a message at the end.

In order to do that here is my source code:

The composite:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:composite="http://java.sun.com/jsf/composite">
    <composite:interface componentType="customInput">
        <composite:attribute name="label" />
        <composite:attribute name="value" />
    </composite:interface>

    <composite:implementation>
        <h:panelGrid columns="3">
            <h:outputText value="#{cc.attrs.label}:" />
            <p:inputText id="abcde" value="#{cc.attrs.value}" />
            <p:message for="abcde" />
        </h:panelGrid>
    </composite:implementation>
</html>

The backing bean:

@FacesComponent(value = "customInput")
public class CustomInput extends InputText implements NamingContainer {
    @Override
    public String getFamily() {
        return UINamingContainer.COMPONENT_FAMILY;
    }
}

So far, so good. Now I want to use the events inherited by the p:inputText component. Like for example:

<pch2:PchInputText2 label="Name" id="test2" value="#{testBean.test}">
    <p:ajax event="blur" listener="#{chantierFormBean.updateMap()}" />
    <p:ajax event="change" listener="#{chantierFormBean.updateMap()}" />
</pch2:PchInputText2>

I know that I could pass these events by adding

<composite:clientBehavior name="change" event="change" targets="abcde" />

to the composite:interface part, but then I have to add one client behavior for every event (in the future). Isn't there a method to pass all events inherited by the primefaces inputtext?

Thanks in advance

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555

1 Answers1

2

That's not possible.

A composite is in first place not the right tool for this job. It's not primarily intented to DRY out and refactor repeated XHTML code. It's intented to create a whole new (input) component tied to a single model value. For example, a <p:fileUpload> and <p:imageCropper> togeher which is tied to a single com.example.Image property. Or three <p:selectOneMenu> together which is tied to a single java.time.LocalDate property.

Use a tagfile instead.

<ui:composition ...>
    <h:outputLabel for="#{id}" value="#{label}:" />
    <p:inputText id="#{id}" value="#{value}">
        <ui:insert />
    </p:inputText>
    <p:message for="#{id}" />
</ui:composition>

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks for your answer. I will try to make it work with a tagfile. Does anyone knows if it possible to keep the funktionality of primefaces inputtext with this method? I will keep the attributes of p:inputtext without redefining them (like "rendered", "disbled", ...). – user2423989 Aug 29 '16 at 12:47
  • You don't need to explicitly define attributes in taglib.xml. Only the IDE autocomplete will suffer from this. – BalusC Aug 29 '16 at 12:56
  • What I meant is when I use your sample composition code and want to use it like this: I can not add a "rendered=false" attribute without specifing it in the composition. Is there a way I can "pass" all attributes that already specifies? – user2423989 Aug 29 '16 at 13:40
  • No, just use `rendered="#{rendered ne false}"`. It's not different in composites, only tagfile doesn't require ``-like boilerplate. – BalusC Aug 29 '16 at 13:49
  • Yes, but then I have to do that for every attribute I want to use. I hoped that there would be a simpler method to inherite all attributes. I guess I have to redefine all attributes then. Thank you for your help – user2423989 Aug 29 '16 at 13:52