p:commandLink 在 p:datatable 中无法使用第 1 页后的分页
p:commandLink not working in p:datatable with pagination after page 1
我在我的 JSF 应用程序中使用 PrimeFaces 5.1。在此应用程序的列表页面上,我使用带分页的 Primefaces Datatable。 table 中一列的值是一个 primefaces commandLink,单击时定义为调用具有 SessionScope 的 JSF ManagedBean class 中定义的操作方法。此数据table 本身在使用已定义h:form 的模板XHTML 的XHTML 页面中定义。因此,此数据table 嵌套在h:form.
中
我面临的问题是 ManagedBean 中定义的方法仅从数据第一页上呈现的 commandLinks 调用 table,而从后续页面上的 commandLinks 操作方法未被调用。我还注意到,由于总记录少于 100,因此当我将 XHTML 中数据 table 的 'rows' 属性的值设置为每页 100 行时,只会呈现一个页面并且然后,当我从列表页面的分页下拉列表中 select 每页 10 或 50 行选项时,会显示多个页面,但 link 工作正常。但是,从代码来看,如果我在 XHTML 代码中将行值设置为每页 50 或 10 行,问题似乎就会发生。
我检查了 firebug JS 以及 Chrome JS 控制台,没有错误,tomcat 日志文件也没有显示任何日志错误,即使我设置了 javax.faces.PROJECT_STAGE
web.xml
到 Development
中的上下文参数。出现这种行为的原因是什么?我该如何解决?
下面是我的 JSF 数据片段table:
<p:dataTable id="data" widgetVar="dataTable" var="customer" value="#{customerServicePortaltBacking.customers}"
paginator="true"
rows="50"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="10,50,100">
<p:column style="width: 14%">
<f:facet name="header">
<p:outputLabel value="#{msg['customerId']}" styleClass="covFont"/>
</f:facet>
<h:outputText value="#{customer.customerId}" styleClass="covFont"/>
</p:column>
<p:column style="width: 66%">
<f:facet name="header">
<p:outputLabel value="#{msg['name']}" styleClass="covFont"/>
</f:facet>
<h:outputText value="#{customer.name}" styleClass="covFont"/>
</p:column>
<p:column style="width: 10%">
<f:facet name="header">
<p:outputLabel value="#{msg['deptId']}" styleClass="covFont"/>
</f:facet>
<h:outputText value="#{customer.deptId}" styleClass="covFont"/>
</p:column>
<p:column style="width: 10%">
<f:facet name="header">
<p:outputLabel value="#{msg['view']}" styleClass="covFont"/>
</f:facet>
<p:commandLink id="invoiceButton" value="#{msg['customers.invoices']}" action="#{customerServicePortaltBacking.goInvoiceCategories(customer)}"
></p:commandLink>
</p:column>
</p:dataTable>
下面是托管 Bean 中的代码 class:
package com.assetworks.csportal;
import com.assetworks.csportal.orm.*;
import org.apache.commons.lang.StringUtils;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Logger;
@ManagedBean
@SessionScoped
public class CustomerServicePortaltBacking {
private static final Logger LOGGER =
Logger.getLogger(CustomerServicePortaltBacking.class.getName());
private List<Customer> customers = null;
private Stack<Screens> screensStack = new Stack<>();
//Screen
private Screens screen = Screens.CustomerBrowse;
private String customerName;
private Customer customer;
public String getCustomerName() {
if(customerName == null){
String name = new DataAccess().getCustomerName(getContactId());
if(name == null)
name = "";
customerName = name;
}
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public List<Customer> getCustomers() {
if(customers == null){
customers = new DataAccess().getCustomers(getContactId());
}
List<Customer> filteredCustomers = new LinkedList<>();
if(hasValue(this.getSearch())) {
String search = getSearch().toUpperCase();
for (Customer customer : customers) {
if(customer.getCustomerId().indexOf(search) != -1 || customer.getName().toUpperCase().indexOf(search) != -1 || customer.getDeptId().indexOf(search) != -1){
filteredCustomers.add(customer);
}
}
}
else{
filteredCustomers = customers;
}
return filteredCustomers;
}
public String goCusomerList(){
screensStack.clear();
DataTable dataTable = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent("form:data");
if(dataTable != null) {
dataTable.resetValue();
dataTable.processUpdates(FacesContext.getCurrentInstance());
}
setScreen(Screens.CustomerBrowse);
return Screens.CustomerBrowse.getId();
}
public String goHome(){
search = null;
return goCusomerList();
}
public String goInvoiceCategories(Customer customer){
categories = null;
this.customer = customer;
this.setScreen(Screens.CustomerServiceCategory);
return Screens.CustomerServiceCategory.getId();
}
public String goBack() {
this.screen = screensStack.pop();
return getScreen().getId();
}
public boolean hasValue(String str){
return str != null && str.length() > 0;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String authenticateUser() {
isUserAuthenticated = true;
return goCusomerList();
}
public void setScreen(Screens screen) {
screensStack.push(getScreen());
this.screen = screen;
}
public Screens getScreen() {
return this.screen;
}
public String getMessage(String key, Object[] args){
String result = "[Key " + key + " not found in messages.properties]";
try {
FacesContext context = FacesContext.getCurrentInstance();
ResourceBundle bundle =
ResourceBundle.getBundle("messages",
context.getViewRoot().getLocale());
result = new MessageFormat(bundle.getString(key)).format(args);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public String getVersion(){
return Application.VERSION;
}
public String getScreenlabel() {
return getMessage(screen.getId(), new Object[0]);
}
public Customer getCustomer() {
return customer;
}
public void setCustomers(List<Customer> customers) {
this.customers = customers;
}
public boolean isCustomerExternal(){
return customer.getDeptId().toUpperCase().startsWith("UFL");
}
}
我终于得到了可以根据需要使用分页的数据表。 Primefaces 数据表上有两个属性,即 rows
和 first
,我使用它们来使链接正常工作。我在我的 Backing Bean class CustomerServicePortaltBacking
中定义了两个新属性 rows
和 first
以及 getter 和 setter,如下所示。
private Integer rows = 50;
private Integer first = 0;
public Integer getRows() {
return rows;
}
public void setRows(Integer rows) {
this.rows = rows;
}
public Integer getFirst() {
return first;
}
public void setFirst(Integer first) {
this.first = first;
}
接下来,我将 first
属性添加到 xhtml 中定义的数据表并将其指向 first
属性 并更新数据表中的 row
属性以指向row
属性 在支持 bean 中定义如下
<p:dataTable id="data" widgetVar="dataTable" var="customer" value="#{customerServicePortaltBacking.customers}"
paginator="true"
first="#{customerServicePortaltBacking.first}"
rows="#{customerServicePortaltBacking.rows}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="10,50,100,200,500" >
这使数据表可以很好地处理分页。
我在我的 JSF 应用程序中使用 PrimeFaces 5.1。在此应用程序的列表页面上,我使用带分页的 Primefaces Datatable。 table 中一列的值是一个 primefaces commandLink,单击时定义为调用具有 SessionScope 的 JSF ManagedBean class 中定义的操作方法。此数据table 本身在使用已定义h:form 的模板XHTML 的XHTML 页面中定义。因此,此数据table 嵌套在h:form.
中我面临的问题是 ManagedBean 中定义的方法仅从数据第一页上呈现的 commandLinks 调用 table,而从后续页面上的 commandLinks 操作方法未被调用。我还注意到,由于总记录少于 100,因此当我将 XHTML 中数据 table 的 'rows' 属性的值设置为每页 100 行时,只会呈现一个页面并且然后,当我从列表页面的分页下拉列表中 select 每页 10 或 50 行选项时,会显示多个页面,但 link 工作正常。但是,从代码来看,如果我在 XHTML 代码中将行值设置为每页 50 或 10 行,问题似乎就会发生。
我检查了 firebug JS 以及 Chrome JS 控制台,没有错误,tomcat 日志文件也没有显示任何日志错误,即使我设置了 javax.faces.PROJECT_STAGE
web.xml
到 Development
中的上下文参数。出现这种行为的原因是什么?我该如何解决?
下面是我的 JSF 数据片段table:
<p:dataTable id="data" widgetVar="dataTable" var="customer" value="#{customerServicePortaltBacking.customers}"
paginator="true"
rows="50"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="10,50,100">
<p:column style="width: 14%">
<f:facet name="header">
<p:outputLabel value="#{msg['customerId']}" styleClass="covFont"/>
</f:facet>
<h:outputText value="#{customer.customerId}" styleClass="covFont"/>
</p:column>
<p:column style="width: 66%">
<f:facet name="header">
<p:outputLabel value="#{msg['name']}" styleClass="covFont"/>
</f:facet>
<h:outputText value="#{customer.name}" styleClass="covFont"/>
</p:column>
<p:column style="width: 10%">
<f:facet name="header">
<p:outputLabel value="#{msg['deptId']}" styleClass="covFont"/>
</f:facet>
<h:outputText value="#{customer.deptId}" styleClass="covFont"/>
</p:column>
<p:column style="width: 10%">
<f:facet name="header">
<p:outputLabel value="#{msg['view']}" styleClass="covFont"/>
</f:facet>
<p:commandLink id="invoiceButton" value="#{msg['customers.invoices']}" action="#{customerServicePortaltBacking.goInvoiceCategories(customer)}"
></p:commandLink>
</p:column>
</p:dataTable>
下面是托管 Bean 中的代码 class:
package com.assetworks.csportal;
import com.assetworks.csportal.orm.*;
import org.apache.commons.lang.StringUtils;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Logger;
@ManagedBean
@SessionScoped
public class CustomerServicePortaltBacking {
private static final Logger LOGGER =
Logger.getLogger(CustomerServicePortaltBacking.class.getName());
private List<Customer> customers = null;
private Stack<Screens> screensStack = new Stack<>();
//Screen
private Screens screen = Screens.CustomerBrowse;
private String customerName;
private Customer customer;
public String getCustomerName() {
if(customerName == null){
String name = new DataAccess().getCustomerName(getContactId());
if(name == null)
name = "";
customerName = name;
}
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public List<Customer> getCustomers() {
if(customers == null){
customers = new DataAccess().getCustomers(getContactId());
}
List<Customer> filteredCustomers = new LinkedList<>();
if(hasValue(this.getSearch())) {
String search = getSearch().toUpperCase();
for (Customer customer : customers) {
if(customer.getCustomerId().indexOf(search) != -1 || customer.getName().toUpperCase().indexOf(search) != -1 || customer.getDeptId().indexOf(search) != -1){
filteredCustomers.add(customer);
}
}
}
else{
filteredCustomers = customers;
}
return filteredCustomers;
}
public String goCusomerList(){
screensStack.clear();
DataTable dataTable = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent("form:data");
if(dataTable != null) {
dataTable.resetValue();
dataTable.processUpdates(FacesContext.getCurrentInstance());
}
setScreen(Screens.CustomerBrowse);
return Screens.CustomerBrowse.getId();
}
public String goHome(){
search = null;
return goCusomerList();
}
public String goInvoiceCategories(Customer customer){
categories = null;
this.customer = customer;
this.setScreen(Screens.CustomerServiceCategory);
return Screens.CustomerServiceCategory.getId();
}
public String goBack() {
this.screen = screensStack.pop();
return getScreen().getId();
}
public boolean hasValue(String str){
return str != null && str.length() > 0;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String authenticateUser() {
isUserAuthenticated = true;
return goCusomerList();
}
public void setScreen(Screens screen) {
screensStack.push(getScreen());
this.screen = screen;
}
public Screens getScreen() {
return this.screen;
}
public String getMessage(String key, Object[] args){
String result = "[Key " + key + " not found in messages.properties]";
try {
FacesContext context = FacesContext.getCurrentInstance();
ResourceBundle bundle =
ResourceBundle.getBundle("messages",
context.getViewRoot().getLocale());
result = new MessageFormat(bundle.getString(key)).format(args);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public String getVersion(){
return Application.VERSION;
}
public String getScreenlabel() {
return getMessage(screen.getId(), new Object[0]);
}
public Customer getCustomer() {
return customer;
}
public void setCustomers(List<Customer> customers) {
this.customers = customers;
}
public boolean isCustomerExternal(){
return customer.getDeptId().toUpperCase().startsWith("UFL");
}
}
我终于得到了可以根据需要使用分页的数据表。 Primefaces 数据表上有两个属性,即 rows
和 first
,我使用它们来使链接正常工作。我在我的 Backing Bean class CustomerServicePortaltBacking
中定义了两个新属性 rows
和 first
以及 getter 和 setter,如下所示。
private Integer rows = 50;
private Integer first = 0;
public Integer getRows() {
return rows;
}
public void setRows(Integer rows) {
this.rows = rows;
}
public Integer getFirst() {
return first;
}
public void setFirst(Integer first) {
this.first = first;
}
接下来,我将 first
属性添加到 xhtml 中定义的数据表并将其指向 first
属性 并更新数据表中的 row
属性以指向row
属性 在支持 bean 中定义如下
<p:dataTable id="data" widgetVar="dataTable" var="customer" value="#{customerServicePortaltBacking.customers}"
paginator="true"
first="#{customerServicePortaltBacking.first}"
rows="#{customerServicePortaltBacking.rows}"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="10,50,100,200,500" >
这使数据表可以很好地处理分页。