"The valueChangeListener will
only be invoked when the form is submitted and the submitted value is different from the initial value"
- BalusC
In this
post, you can see several use cases for valueChangeListener attribute
and ValueChangeListener
interface:
·
use the valueChangeListener attribute to point a
bean’s method directly when a radio is selected
<h:form>
<h:selectOneRadio
value="#{playerBean.player}" onchange="submit()"
valueChangeListener="#{playerBean.playerChangeValueMethod}">
<f:selectItems
value="#{playerBean.players}" />
</h:selectOneRadio>
</h:form>
·
use the valueChangeListener attribute to point a
bean’s method directly when a boolean checkbox is clicked
<h:form>
<h:selectBooleanCheckbox
value="#{playerBean.player}" onclick="submit()" valueChangeListener="#{playerBean.playerChangeValueMethod}"/>
</h:form>
</h:form>
·
use the valueChangeListener attribute to point a
bean’s method directly when an item is selected
<h:form>
<h:selectOneMenu value="#{playerBean.player}"
onchange="submit()"
valueChangeListener="#{playerBean.playerChangeValueMethod}">
<f:selectItems
value="#{playerBean.players}" />
</h:selectOneMenu>
</h:form>
·
use the valueChangeListener attribute to point a
bean’s method directly at every
key press - not practical, but it works as inspiration source (<f:ajax listener="..."/> is better is this case)
<h:form>
<h:inputText
value="#{playerBean.player}" onkeyup="submit()"
valueChangeListener="#{playerBean.playerChangeValueMethod}"/>
</h:form>
For these
three use cases, the PlayerBean is:
@Named
@SessionScoped
public class
PlayerBean implements Serializable {
private List<String> players = new
ArrayList<>();
private String player;
public PlayerBean() {
players.add("Rafael Nadal");
players.add("Novak Djokovic");
players.add("Roger Federer");
players.add("Andy Murray");
players.add("David Ferrer");
}
public void
playerChangeValueMethod(ValueChangeEvent e) {
System.out.println("PlayerBean: [PLAYER
CHANGE]" + " " + e.getOldValue()
+ " IN " + e.getNewValue());
}
public List<String> getPlayers() {
return
players;
}
public void setPlayers(List<String>
players) {
this.players = players;
}
public String getPlayer() {
return
player;
}
public void setPlayer(String player) {
this.player = player;
}
}
·
use the ValueChangeListener interface instead of
valueChangeListener
attribute
<h:form>
<h:selectOneMenu
value="#{playerBean.player}" onchange="submit()">
<f:valueChangeListener
type="beans.PlayerChangeValueListener" />
<f:selectItems
value="#{playerBean.players}" />
</h:selectOneMenu>
</h:form>
The PlayerChangeValueListener
is:
public class
PlayerChangeValueListener implements ValueChangeListener {
@Override
public void processValueChange(ValueChangeEvent
event) throws AbortProcessingException {
System.out.println("PlayerChangeValueListener:
[PLAYER CHANGE]" + " " +
event.getOldValue() + " IN " + event.getNewValue());
}
}
Note You
can use both, <f:valueChangeListener>
and valueChangeListener
attribute, but you have to be aware that the bean's method will be invoked
first.
In some
situations, you will prefer <f:ajax listener="..."/>
instead of <f:valueChangeListener>
or valueChangeListener.
Per example, we have adapted the example with <h:selectOneMenu>, as
below:
<h:form>
<h:selectOneMenu id="myPlayersId"
value="#{playerBean.player}">
<f:selectItems
value="#{playerBean.players}" />
<f:ajax execute="@form" render=":selectedPlayerId"
listener="#{playerBean.playerChangeValueMethod}" />
</h:selectOneMenu>
</h:form>
In this
case, you have to add the below method in PlayerBean. This time, you
will not have access to the old value, so maybe is not a good idea to replace the valueChangeListener with <f:ajax listener="..."/>.
Do you need the old value ? This is
the question!
public void
playerChangeValueMethod(AjaxBehaviorEvent e) {
System.out.println("PlayerBean: [PLAYER
CHANGE]" + " " + player);
}
But, in case
that we need to invoke a method at every key press in a text box (see example above),
is more proper to use <f:ajax listener="..."/>. Well, in this
case, you can "calculate" the old
value as a substring of current value:
<h:form>
<h:inputText
value="#{playerBean.player}">
<f:ajax event="keyup" execute="@form"
render=":selectedPlayerId"
listener="#{playerBean.playerChangeValueMethod}" />
</h:inputText>
</h:form>
Let's have a
quick and handy guide about ValueChangeListener:
·
Don't forget to attach a onevent="submit()" JavaScript to the input
component. Novices usually forget this golden rule, and no event will be fired.
·
The bean's method must have an argument of type ValueChangeEvent.
·
The ValueChangeListener will only be called
when the form is submitted (this is why we need, onevent="submit()"), not when the value of the input
is changed. Moreover, the submitted
value should be different from the initial
value.
·
The ValueChangeListener allows us to
manipulate in bean the old value (event.getOldValue())
and the new value (event.getNewValue()).
When you don't need the old value
maybe the <f:ajax
listener="..."/> will be a better choice.
Complete
code on GitHub.
Niciun comentariu :
Trimiteți un comentariu