我正在尝试创建一个JSF页面,用户在两个selectOneMenu组件中选择值。然后,这些选择中的值将传递给SQL查询以更新页面上显示的表。
我已将每个选择项绑定到支持bean中的相应变量,但在更改selectOneMenu中选择的值后,支持bean中的bound属性不会更改,并且查询已执行但不会执行t返回任何结果。 (另外,当最初显示页面时,getter似乎也会被调用两次。)
我不能使用任何其他第三方组件(例如RichFaces等)来实现此实现。
对此有任何见解表示赞赏!
以下是代码:
notes.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title></title>
</head>
<body>
<f:view>
<h:form id="notelistform">
<f:subview id="loginbar">
<jsp:include page="/jsp/loginbar.jsp" />
</f:subview>
<h:outputText value="Worktype:" />
<h:selectOneMenu value="#{pc_noteListBacker.worktype}"
title="worktype" id="worktypeList" onchange="submit()">
<f:selectItems value="#{pc_noteListBacker.selectWorktypes}" />
<f:valueChangeListener
type="<package>.web.backer.note.NoteListBacker" />
</h:selectOneMenu>
<h:outputText value="Product:" />
<h:selectOneMenu value="#{pc_noteListBacker.product}" title="product"
id="productList" onchange="submit()">
<f:selectItems value="#{pc_noteListBacker.selectProducts}" />
<f:valueChangeListener
type="<package>.web.backer.note.NoteListBacker" />
</h:selectOneMenu>
<h:dataTable id="notelisttable" value="#{pc_noteListBacker.noteList}"
var="item" bgcolor="#F1F1F1" border="10" cellpadding="5"
cellspacing="3" first="0" width="80%" dir="LTR" frame="hsides"
rules="all" summary="Status and notes note table display."
binding="#{pc_noteListBacker.noteListTable}">
<h:column>
<f:facet name="header">
<h:outputText value="Note ID" />
</f:facet>
<h:outputText value="#{item.noteId}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Note Category" />
</f:facet>
<h:outputText value="#{item.noteCategory}"></h:outputText>
<f:facet name="footer">
<h:commandButton value="Add" action="#{pc_noteListBacker.insert}">
</h:commandButton>
</f:facet>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Note Subcategory" />
</f:facet>
<h:outputText value="#{item.noteSubCategory}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Note" />
</f:facet>
<h:outputText value="#{item.note}"></h:outputText>
</h:column>
<h:column>
<h:commandButton value="Edit" action="#{pc_noteListBacker.edit}">
</h:commandButton>
</h:column>
<h:column>
<h:commandButton value="Delete" action="#{pc_noteListBacker.delete}"></h:commandButton>
</h:column>
</h:dataTable>
</h:form>
NoteListBacker.java
package <package>.web.backer.note;
import java.util.List;
import java.util.ArrayList;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIData;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ValueChangeListener;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.swing.JOptionPane;
public class NoteListBacker implements ValueChangeListener {
private UIData noteListTable;
private Note note;
private NoteCategory noteCategory;
private NoteSubCategory noteSubCategory;
private NoteDao nDao;
private SybaseSqlDao sybaseDao;
private List<Note> noteList;
private List<SelectItem> selectWorktypes;
private List<SelectItem> selectProducts;
private String worktype;
private List<String> worktypeList;
private String product;
private List<Product> productList;
private int noteId;
public NoteListBacker() {
nDao = new NoteDao();
sybaseDao = new SybaseSqlDao();
selectWorktypes = new ArrayList<SelectItem>();
selectProducts = new ArrayList<SelectItem>();
noteList = new ArrayList<Note>();
note = new Note();
worktypeList = new ArrayList<String>();
productList = new ArrayList<Product>();
}
public String insert() {
return "success";
}
public String save() {
return "notes";
}
public String edit() {
return "success";
}
public String update() {
return "notes";
}
public String delete() {
Note delNote = (Note) noteListTable.getRowData();
nDao.deleteNote(delNote);
return "notes";
}
public String cancel() {
return "notes";
}
public Note getNote() {
return note;
}
public void setNote(Note note) {
this.note = note;
}
public NoteDao getNDao() {
return nDao;
}
public UIData getNoteListTable() {
return noteListTable;
}
public void setNoteListTable(UIData noteListTable) {
this.noteListTable = noteListTable;
}
public List<Note> getNoteList() {
noteList = nDao.selectNotes(worktype, product); //
return noteList;
}
public void setNoteList(List<Note> noteList) {
this.noteList = noteList;
}
public void setNDao(NoteDao dao) {
nDao = dao;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public String getWorktype() {
return worktype;
}
public void setWorktype(String worktype) {
this.worktype = worktype;
}
public NoteCategory getNoteCategory() {
return noteCategory;
}
public void setNoteCategory(NoteCategory noteCategory) {
this.noteCategory = noteCategory;
}
public NoteSubCategory getNoteSubCategory() {
return noteSubCategory;
}
public void setNoteSubCategory(NoteSubCategory noteSubCategory) {
this.noteSubCategory = noteSubCategory;
}
public int getNoteId() {
return noteId;
}
public void setNoteId(int noteId) {
this.noteId = noteId;
}
public SybaseSqlDao getSybaseDao() {
return sybaseDao;
}
public void setSybaseDao(SybaseSqlDao sybaseDao) {
this.sybaseDao = sybaseDao;
}
public List<SelectItem> getSelectWorktypes() {
selectWorktypes.clear();
worktypeList = this.getWorktypeList();
for (String strt : worktypeList) {
SelectItem si = new SelectItem();
si.setValue(strt);
si.setLabel(strt);
si.setDescription(strt);
selectWorktypes.add(si);
}
return selectWorktypes;
}
public void setSelectWorktypes(List<SelectItem> selectWorktypes) {
this.selectWorktypes = selectWorktypes;
}
public List<String> getWorktypeList() {
worktypeList = sybaseDao.selectWorktypes();
return worktypeList;
}
public void setWorktypeList(List<String> worktypeList) {
this.worktypeList = worktypeList;
}
public List<Product> getProductList() {
productList = sybaseDao.selectProducts();
return productList;
}
public void setProductList(List<Product> productList) {
this.productList = productList;
}
public List<SelectItem> getSelectProducts() {
selectProducts.clear();
productList = this.getProductList();
for (Product prod : productList) {
SelectItem si = new SelectItem();
si.setValue(prod);
si.setLabel(prod.toString());
si.setDescription(prod.toString());
selectProducts.add(si);
}
return selectProducts;
}
public void setSelectProducts(List<SelectItem> selectProducts) {
this.selectProducts = selectProducts;
}
public void processValueChange(ValueChangeEvent arg0) {
if (arg0.getComponent().getId().equalsIgnoreCase("productList")) {
this.setProduct(arg0.getNewValue().toString());
}
if (arg0.getComponent().getId().equalsIgnoreCase("worktypeList")) {
this.setWorktype(arg0.getNewValue().toString());
}
}
}
faces-config.xml中
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
<lifecycle>
<phase-listener>
<package>.utils.NoCachePhaseListener
</phase-listener>
</lifecycle>
<managed-bean>
<managed-bean-name>pc_userBacker</managed-bean-name>
<managed-bean-class>
<package>.web.backer.UserBacker
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>pc_noteCategoryListBacker</managed-bean-name>
<managed-bean-class>
<package>.web.backer.note.NoteCategoryListBacker
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>
pc_noteSubCategoryListBacker
</managed-bean-name>
<managed-bean-class>
<package>.web.backer.note.NoteSubCategoryListBacker
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>pc_noteListBacker</managed-bean-name>
<managed-bean-class>
<package>.web.backer.note.NoteListBacker
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>pc_statusListBacker</managed-bean-name>
<managed-bean-class>
<package>.web.backer.status.StatusListBacker
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>pc_statusReasonBacker</managed-bean-name>
<managed-bean-class>
<package>.web.backer.status.StatusReasonBacker
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<!-- Notes -->
<navigation-rule>
<from-view-id>/jsp/notes/notes.jsp</from-view-id>
<navigation-case>
<from-action>#{pc_noteListBacker.edit}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/notes/noteedit.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{pc_noteListBacker.insert}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/notes/notenew.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!-- Note Categories -->
<navigation-rule>
<from-view-id>/jsp/notes/notecategories.jsp</from-view-id>
<navigation-case>
<from-action>#{pc_noteCategoryListBacker.edit}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/notes/notecategoryedit.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>
#{pc_noteCategoryListBacker.insert}
</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/notes/notecategorynew.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!-- Note Subcategories -->
<navigation-rule>
<from-view-id>/jsp/notes/notesubcategories.jsp</from-view-id>
<navigation-case>
<from-action>
#{pc_noteSubCategoryListBacker.edit}
</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/notes/notesubcategoryedit.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>
#{pc_noteSubCategoryListBacker.insert}
</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/notes/notesubcategorynew.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!-- Statuses -->
<navigation-rule>
<from-view-id>/jsp/statuses/statuses.jsp</from-view-id>
<navigation-case>
<from-action>#{pc_statusListBacker.edit}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/statuses/statusedit.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{pc_statusListBacker.insert}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/statuses/statusnew.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!-- Status Reasons -->
<navigation-rule>
<from-view-id>/jsp/statuses/statusreasons.jsp</from-view-id>
<navigation-case>
<from-action>#{pc_statusReasonBacker.edit}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/statuses/statusreasonedit.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{pc_statusReasonBacker.insert}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/statuses/statusreasonnew.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<!-- static and general actions-->
<!-- what page the action is coming from doesn't matter here -->
<navigation-rule>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/login.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>menu</from-outcome>
<to-view-id>/menu.jsp</to-view-id>
</navigation-case>
<!-- Notes -->
<navigation-case>
<from-outcome>notes</from-outcome>
<to-view-id>/jsp/notes/notes.jsp</to-view-id>
</navigation-case>
<!-- Note Categories -->
<navigation-case>
<from-outcome>notecategories</from-outcome>
<to-view-id>/jsp/notes/notecategories.jsp</to-view-id>
</navigation-case>
<!-- Note Subcategories -->
<navigation-case>
<from-outcome>notesubcategories</from-outcome>
<to-view-id>/jsp/notes/notesubcategories.jsp</to-view-id>
</navigation-case>
<!-- Statuses -->
<navigation-case>
<from-outcome>statuses</from-outcome>
<to-view-id>/jsp/statuses/statuses.jsp</to-view-id>
</navigation-case>
<!-- Status Reasons -->
<navigation-case>
<from-outcome>statusreasons</from-outcome>
<to-view-id>/jsp/statuses/statusreasons.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
答案 0 :(得分:1)
我只是看了一眼代码,但我猜这部分问题可能就在这里:
public void processValueChange(ValueChangeEvent arg0) {
if (arg0.getComponent().getId().equalsIgnoreCase("productList")) {
this.setProduct(arg0.getNewValue().toString());
}
if (arg0.getComponent().getId().equalsIgnoreCase("worktypeList")) {
this.setWorktype(arg0.getNewValue().toString());
}
}
如果您阅读了valueChangeListener type
属性的文档,则说明了这一点:
要创建和注册的ValueChangeListener的完全限定Java类名。
这意味着您将至少有三个<package>.web.backer.note.NoteListBacker
实例 - 两个创建为侦听器,第三个创建为托管bean。最后一个是表绑定的唯一一个,并且侦听器中的任何状态更改都是无关紧要的。
修复:
NoteListBacker
实施ValueChangeListener
;没有意义。valueChangeListener
属性绑定到#{pc_noteListBacker.valueChange}
方法(有关详细信息,请参阅文档)或有一个单独的ValueChangeListener
使用pc_noteListBacker
直接从会话中查找FacesContext
的实现。答案 1 :(得分:1)
我经常碰到这个,直到我知道这里的问题是什么。提交页面时,JSF将在您调用processValueChange()之后运行UPDATE_MODEL阶段。因此,对BackingBean的更改将被HTTP请求中的值覆盖,并且不起作用。
要防止这种情况发生,您必须在ValueChangeListener中手动发出导航案例。您可以通过在processValueChange()的末尾插入以下行来完成此操作。
FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(
FacesContext.getCurrentInstance(), null, "stay_here");
“stay_here”是指faces-config.xml
中的导航案例<!-- Notes -->
<navigation-rule>
<from-view-id>/jsp/notes/notes.jsp</from-view-id>
<navigation-case>
<from-action>#{pc_noteListBacker.edit}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/notes/noteedit.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{pc_noteListBacker.insert}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/jsp/notes/notenew.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>stay_here</from-outcome>
<to-view-id>/jsp/notes/notes.jsp</to-view-id>
</navigation-case>
</navigation-rule>
希望这有帮助。
此致