Reputation: 53
I have a composite (X) like this:
<composite:interface>
<composite:attribute name="textValue" />
<composite:attribute name="textValueChangeListner"
method-signature="void valueChanged(javax.faces.event.ValueChangeEvent)" />
<composite:implementation>
<ice:inputText
value="#{cc.attrs.textValue}"
valueChangeListener="#{cc.attrs.textValueChangeListner}"/>
In the JSF page I have something like:
<X:iText
textValue="#{cardBean.getCardValue}"
textValueChangeListner="#{cardHandler.cardValueChanged}" />
The above code works fine. But it does not work when NO "textValueChangeListner" is passed to the composite from JFace page; i.e:
<X:iText
textValue="#{cardBean.getCardValue}" />
Error I got: [javax.enterprise.resource.webcontainer.jsf.lifecycle] Unable to resolve composite component from using page using EL expression '#{cc.attrs.textValueChangeListner}': javax.faces.FacesException: Unable to resolve composite component from using page using EL expression '#{cc.attrs.textValueChangeListner}'
In my scenario it is necessary that page developer may or may not supply the "textValueChangeListner" to the composite component. How can I achieve that ?
Upvotes: 1
Views: 2972
Reputation: 7920
You have two options here: First one is the easy way, just render another input text without having a valueChangeListener if the user didn't supply Value Change listener.
<ice:inputText
value="#{cc.attrs.textValue}"
valueChangeListener="#{cc.attrs.textValueChangeListener}"
rendered="#{!empty cc.attrs.textValueChangeListener}"/>
If you need to have a valueChangeListener in any case then apply an default value for the attribute:
<composite:attribute name="textValueChangeListener"
method-signature="void valueChanged(javax.faces.event.ValueChangeEvent)"
required="false"
default="#{cc.valueChangedListener}" />
For doing this you need to bind your composite component to a backing bean. And you need to define components' backing bean type through its interface declaration like this:
<composite:interface componentType="yourComponentBean">
<composite:attribute name="textValueChangeListener"
method-signature="void valueChanged(javax.faces.event.ValueChangeEvent)"
required="false"
default="#{cc.valueChangedListener}" />
</composite:interface>
And here is yourComponentBean which implements the default ValueChangedListener.
@FacesComponent("yourComponentBean")
public class YourComponentCC extends UINamingContainer
{
public void valueChangedListener(ValueChangeEvent ev)
{
....
}
}
Btw cc
is a shortcut in EL to access backing bean that is defined as the componentType in your component. so cc.valueChangedListener
will call valueChangedListener
method defined in YourComponentCC
class.
Upvotes: 2
Reputation: 1108782
Rename the attribute to valueChangeListener
and use targets
attribute,
<composite:attribute name="valueChangeListner"
method-signature="void valueChanged(javax.faces.event.ValueChangeEvent)"
targets="text" />
where text
is the ID of the target input component,
<ice:inputText id="text" ... />
and remove the valueChangeListener
from it.
Upvotes: 2