Il valueChangeListenerverrà invocato solo quando il modulo viene inviato e il valore inviato è diverso dal valore iniziale. Non viene quindi richiamato quando viene attivato solo l' changeevento HTML DOM . Se desideri inviare il modulo durante l' changeevento 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' changeevento HTML DOM . All'interno di UICommandcomponenti e componenti di input che rappresentano una casella di controllo o un pulsante di opzione, verrà eseguito per impostazione predefinita solo durante l' clickevento HTML DOM .
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Un'altra importante differenza è che il valueChangeListenermetodo viene richiamato durante la fine della PROCESS_VALIDATIONSfase. 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_APPLICATIONfase. 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 valueChangeListenerpoiché la proprietà aggiornata può essere sovrascritta dal valore inviato durante la UPDATE_MODEL_VALUESfase 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 valueChangeListenerper eseguire azioni aziendali è sempre stato un trucco / soluzione alternativa.
Riepilogo: utilizzare valueChangeListenersolo 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_APPLICATIONfase.
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 ...