ระบบvalueChangeListener
จะเรียกใช้เมื่อมีการส่งแบบฟอร์มและค่าที่ส่งจะแตกต่างจากค่าเริ่มต้นเท่านั้น ดังนั้นจึงไม่ถูกเรียกใช้เมื่อมีการเริ่มต้นchange
เหตุการณ์HTML DOM เท่านั้น หากคุณต้องการส่งแบบฟอร์มระหว่างchange
เหตุการณ์HTML DOM คุณจะต้องเพิ่มแบบฟอร์มอื่น<f:ajax/>
โดยไม่ต้องมี Listener (!) จะทำให้เกิดการส่งแบบฟอร์มซึ่งประมวลผลเฉพาะองค์ประกอบปัจจุบัน (ตามที่อยู่ในexecute="@this"
)
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
เมื่อใช้<f:ajax listener>
แทนvalueChangeListener
โดยค่าเริ่มต้นจะดำเนินการในระหว่างchange
เหตุการณ์HTML DOM อยู่แล้ว UICommand
ส่วนประกอบภายในและส่วนประกอบอินพุตที่แสดงถึงช่องทำเครื่องหมายหรือปุ่มเรดิโอโดยค่าเริ่มต้นจะถูกเรียกใช้โดยค่าเริ่มต้นในระหว่างclick
เหตุการณ์HTML DOM เท่านั้น
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
ความแตกต่างที่สำคัญอีกประการหนึ่งคือvalueChangeListener
วิธีการถูกเรียกใช้ในช่วงท้ายของPROCESS_VALIDATIONS
เฟส ในขณะนั้นค่าที่ส่งยังไม่ได้รับการอัปเดตในแบบจำลอง value
ดังนั้นคุณจึงไม่สามารถรับมันได้โดยเพียงแค่การเข้าถึงคุณสมบัติถั่วที่ถูกผูกไว้กับองค์ประกอบของการป้อนข้อมูล ValueChangeEvent#getNewValue()
คุณต้องได้รับมันด้วย ValueChangeEvent#getOldValue()
ค่าเดิมคือโดยวิธีการนี้ยังมีการ
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
}
<f:ajax listener>
วิธีการถูกเรียกในระหว่างINVOKE_APPLICATION
ขั้นตอนการ ในขณะนั้นค่าที่ส่งได้รับการอัปเดตแล้วในโมเดล value
คุณก็สามารถได้รับมันโดยการเข้าถึงโดยตรงคุณสมบัติถั่วที่ถูกผูกไว้กับองค์ประกอบของการป้อนข้อมูล
private Object value;
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value);
}
นอกจากนี้หากคุณต้องการอัปเดตคุณสมบัติอื่นตามมูลค่าที่ส่งมาก็จะล้มเหลวเมื่อคุณใช้valueChangeListener
เนื่องจากคุณสมบัติที่อัปเดตสามารถทำได้ถูกแทนที่ด้วยค่าที่ส่งในช่วงถัดUPDATE_MODEL_VALUES
ไป นั่นเป็นเหตุผลว่าทำไมคุณเห็นในเก่า JSF 1.x / โปรแกรมบทเรียน / ทรัพยากรที่valueChangeListener
อยู่ในโครงสร้างดังกล่าวถูกนำมาใช้ร่วมกับimmediate="true"
และFacesContext#renderResponse()
เพื่อป้องกันไม่ให้เกิดขึ้น ท้ายที่สุดแล้วvalueChangeListener
การใช้คำสั่งเพื่อดำเนินการทางธุรกิจถือเป็นการแฮ็ก / วิธีแก้ปัญหาเสมอ
สรุป: ใช้ไฟล์ valueChangeListener
เฉพาะในกรณีที่คุณต้องการสกัดกั้นการเปลี่ยนแปลงค่าจริง กล่าวคือคุณสนใจทั้งค่าเก่าและค่าใหม่ (เช่นเพื่อบันทึก)
public void changeListener(ValueChangeEvent event) {
changeLogger.log(event.getOldValue(), event.getNewValue());
}
ใช้ <f:ajax listener>
เฉพาะเมื่อคุณต้องการดำเนินการทางธุรกิจกับมูลค่าที่เปลี่ยนแปลงใหม่ กล่าวคือคุณสนใจเฉพาะค่าใหม่เท่านั้น (เช่นเพื่อเติมข้อมูลแบบเลื่อนลงที่สอง)
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
หากคุณสนใจคุณค่าเก่า ๆ ในขณะที่ดำเนินการทางธุรกิจให้ถอยกลับไปvalueChangeListener
แต่จัดคิวไว้ที่INVOKE_APPLICATION
เฟส
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 );
. ดูเหมือนว่าคุณสามารถใช้ค่าเก่าและใหม่ที่ได้รับในรูปแบบนั้นเพื่อทำตรรกะทางธุรกิจได้โดยตรงใน setter เช่นเดียวกับการบันทึกแบบง่ายๆ แต่ฉันไม่รู้ว่าสิ่งนี้จะทำให้เกิดผลข้างเคียงหรือไม่ ...