Il valueChangeListener
verrà invocato solo quando il modulo viene inviato e il valore inviato è diverso dal valore iniziale. Non viene quindi richiamato quando viene attivato solo l' change
evento HTML DOM . Se desideri inviare il modulo durante l' change
evento HTML DOM , devi aggiungerne un altro <f:ajax/>
senza un listener (!) Al componente di input. Provocherà un invio del modulo che elabora solo il componente corrente (come in execute="@this"
).
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
Quando si utilizza <f:ajax listener>
invece di valueChangeListener
, viene eseguito per impostazione predefinita già durante l' change
evento HTML DOM . All'interno di UICommand
componenti e componenti di input che rappresentano una casella di controllo o un pulsante di opzione, verrà eseguito per impostazione predefinita solo durante l' click
evento HTML DOM .
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Un'altra importante differenza è che il valueChangeListener
metodo viene richiamato durante la fine della PROCESS_VALIDATIONS
fase. In quel momento, il valore inviato non è stato ancora aggiornato nel modello. Quindi non puoi ottenerlo accedendo semplicemente alla proprietà bean che è associata a quella del componente di input value
. Devi farcela ValueChangeEvent#getNewValue()
. Il vecchio valore è tra l'altro disponibile anche da ValueChangeEvent#getOldValue()
.
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
}
Il <f:ajax listener>
metodo viene richiamato durante la INVOKE_APPLICATION
fase. In quel momento, il valore inviato è già stato aggiornato nel modello. Puoi ottenerlo accedendo direttamente alla proprietà bean che è associata a quella del componente di input value
.
private Object value;
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value);
}
Inoltre, se fosse necessario aggiornare un'altra proprietà in base al valore inviato, non funzionerebbe quando si utilizza valueChangeListener
poiché la proprietà aggiornata può essere sovrascritta dal valore inviato durante la UPDATE_MODEL_VALUES
fase successiva . Questo è esattamente il motivo per cui nelle vecchie applicazioni / tutorial / risorse JSF 1.x si vede che a valueChangeListener
è stato utilizzato in tale costrutto in combinazione con immediate="true"
e FacesContext#renderResponse()
per evitare che ciò accada. Dopotutto, l'utilizzo di valueChangeListener
per eseguire azioni aziendali è sempre stato un trucco / soluzione alternativa.
Riepilogo: utilizzare valueChangeListener
solo se è necessario intercettare la variazione del valore effettivo stesso. Cioè sei effettivamente interessato sia al vecchio che al nuovo valore (ad esempio per registrarli).
public void changeListener(ValueChangeEvent event) {
changeLogger.log(event.getOldValue(), event.getNewValue());
}
Utilizzare <f:ajax listener>
solo se è necessario eseguire un'azione commerciale sul valore appena modificato. Cioè in realtà sei interessato solo al nuovo valore (ad esempio per popolare un secondo menu a discesa).
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
Se in realtà sei interessato anche al vecchio valore durante l'esecuzione di un'azione aziendale, ripiega su valueChangeListener
, ma mettilo in coda alla INVOKE_APPLICATION
fase.
public void changeListener(ValueChangeEvent event) {
if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
return;
}
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
System.out.println(newValue.equals(value));
}
logger.trace( "setting changeTypes from {} to {}", this.changeTypes, changeTypes );
. Sembra che potresti usare i valori vecchi e nuovi ottenuti in quel modo per fare la logica di business direttamente nel setter così come il semplice logging, ma non so se questo causerebbe effetti collaterali ...