Ini valueChangeListener
hanya akan dipanggil ketika formulir dikirimkan dan nilai yang dikirimkan berbeda dari nilai awal. Oleh karena itu, ini tidak dipanggil ketika hanyachange
event HTML DOM yang diaktifkan. Jika Anda ingin mengirimkan formulir selama change
acara DOM HTML , Anda harus menambahkan <f:ajax/>
formulir lain tanpa listener (!) Ke komponen input. Ini akan menyebabkan pengiriman formulir yang hanya memproses komponen saat ini (seperti di execute="@this"
).
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
Saat menggunakan, <f:ajax listener>
bukan valueChangeListener
, secara default akan dieksekusi selama change
peristiwa DOM HTML . Di dalam UICommand
komponen dan komponen masukan yang mewakili kotak centang atau tombol radio, ini akan dijalankan secara default selama click
peristiwa DOM HTML saja.
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Perbedaan utama lainnya adalah bahwa valueChangeListener
metode tersebut dipanggil selama akhir PROCESS_VALIDATIONS
fase. Saat itu, nilai yang dikirimkan belum diperbarui dalam model. Jadi Anda tidak bisa mendapatkannya hanya dengan mengakses properti kacang yang terikat ke komponen masukan value
. Anda harus melakukannya ValueChangeEvent#getNewValue()
. Nilai lama dengan cara juga tersedia oleh ValueChangeEvent#getOldValue()
.
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
}
The <f:ajax listener>
Metode dipanggil selama INVOKE_APPLICATION
fase. Saat itu, nilai yang dikirimkan sudah diperbarui dalam model. Anda bisa mendapatkannya dengan langsung mengakses properti kacang yang terikat ke komponen masukan value
.
private Object value;
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value);
}
Selain itu, jika Anda perlu memperbarui properti lain berdasarkan nilai yang dikirimkan, maka itu akan gagal saat Anda menggunakan valueChangeListener
karena properti yang diperbarui dapat diganti dengan nilai yang dikirimkan selama UPDATE_MODEL_VALUES
fase berikutnya . Itulah mengapa Anda melihat di aplikasi / tutorial / sumber JSF 1.x lama bahwa a valueChangeListener
dalam konstruksi seperti itu telah digunakan dalam kombinasi dengan immediate="true"
dan FacesContext#renderResponse()
untuk mencegah hal itu terjadi. Bagaimanapun, menggunakan valueChangeListener
untuk mengeksekusi tindakan bisnis sebenarnya selalu merupakan peretasan / solusi.
Diringkas: Gunakan valueChangeListener
hanya jika Anda perlu menghentikan perubahan nilai aktual itu sendiri. Yaitu Anda benar-benar tertarik baik yang lama dan nilai baru (misalnya untuk login mereka).
public void changeListener(ValueChangeEvent event) {
changeLogger.log(event.getOldValue(), event.getNewValue());
}
Gunakan <f:ajax listener>
hanya jika Anda perlu melakukan tindakan bisnis pada nilai yang baru diubah. Yaitu Anda sebenarnya hanya tertarik pada nilai baru (misalnya untuk mengisi dropdown kedua).
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
Jika Anda sebenarnya juga tertarik dengan nilai lama saat menjalankan tindakan bisnis, kembali ke valueChangeListener
, tetapi antrekan ke 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 );
. Sepertinya Anda dapat menggunakan nilai lama dan baru yang diperoleh dengan cara itu untuk melakukan logika bisnis secara langsung di setter serta logging sederhana, tetapi saya tidak tahu apakah ini akan menyebabkan efek samping ...