简体   繁体   English

PrimeFaces DataTable在过滤时不会更新

[英]PrimeFaces DataTable doesn't update when filtered

I'm new to PrimeFaces and to JSF. 我是PrimeFaces和JSF的新手。

I need to filter a table with "contains" match mode. 我需要使用“包含”匹配模式过滤表格。 It works fine when the data is static, but when data changes the view doesn't update, and it still shows the old data. 当数据是静态时,它可以正常工作,但是当数据发生更改时,视图不会更新,并且它仍然显示旧数据。 It updates when the user changes the filter. 它会在用户更改过滤器时更新。 If no filter is applied it works fine. 如果没有应用过滤器,它可以正常工作。

Have you got any suggestions? 你有什么建议吗?

I post the code, inspired from the PrimeFaces 6 showcase. 我发布了代码,灵感来自PrimeFaces 6展示。 It is a page that displays a two columns table and a button that loads a new data for the table 它是一个页面,显示两列表和一个加载表的新数据的按钮

Thank you, any help will be appreciated 谢谢,任何帮助将不胜感激

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:p="http://primefaces.org/ui">
<h:head >
Primefaces Data Table Test
</h:head>
<h:body>
    <h:form>
        <p:dataTable var="car" value="#{dtCar.cars}" widgetVar="carsTable"
            emptyMessage="No cars found with given criteria"
            filteredValue="#{dtCar.filteredCars}">


            <p:column filterBy="#{car.model}" headerText="Model"
                footerText="contains" filterMatchMode="contains">
                <h:outputText value="#{car.model}" />
            </p:column>
            <p:column filterBy="#{car.color}" headerText="Color"
                footerText="contains" filterMatchMode="contains">
                <h:outputText value="#{car.color}" />
            </p:column>

        </p:dataTable>
        <h:commandButton id="myButton" value="Load" action="#{dtCar.loadNewCars()}"/>
    </h:form>

</h:body>
</html>

Here is the CarBean.java 这是CarBean.java

package it.caditech.testtable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean(name = "dtCar")
@ViewScoped
public class CarBean {

  private List<Car> cars;

  private List<Car> filteredCars;

  public CarBean() {
    setCars(new ArrayList<Car>());
    getCars().add(new Car("myModel", "blu"));
    getCars().add(new Car("punto", "blu"));
    getCars().add(new Car("doblo", "grigio"));
    getCars().add(new Car("smart", "blu"));
    getCars().add(new Car("twingo", "rosso"));
    getCars().add(new Car("twingo", "bianco"));
    getCars().add(new Car("doblo", "blu"));
    // add more cars
  }

  // getter setter
  public List<Car> getCars() {
    return cars;
  }

  public void setCars(List<Car> cars) {
    this.cars = cars;
  }

  public List<Car> getFilteredCars() {
    return filteredCars;
  }

  public void setFilteredCars(List<Car> filteredCars) {
    this.filteredCars = filteredCars;
  }

  public String loadNewCars() {
    if (getCars().get(0).getModel().equals("myModel")) {
      getCars().clear();
      getCars().add(new Car("gt", "giallo"));
      getCars().add(new Car("scirocco", "azzurro"));
      getCars().add(new Car("duna", "giallo"));
      getCars().add(new Car("diablo", "griggio"));
      getCars().add(new Car("cayenne", "rosso"));
      getCars().add(new Car("aygo", "azzurro"));
      setFilteredCars(null);
    }
    else {
      getCars().clear();
      getCars().add(new Car("myModel", "blu"));
      getCars().add(new Car("punto", "blu"));
      getCars().add(new Car("doblo", "grigio"));
      getCars().add(new Car("smart", "blu"));
      getCars().add(new Car("twingo", "rosso"));
      getCars().add(new Car("twingo", "bianco"));
      getCars().add(new Car("doblo", "blu"));
      setFilteredCars(null);
    }
    return null;
  }
}

And here is the Car.java 这是Car.java

package it.caditech.testtable;
public class Car {
  private String model;

  private String color;

  public Car(String m, String c) {
    model = m;
    color = c;
  }

  public String getModel() {
    return model;
  }

  public void setModel(String model) {
    this.model = model;
  }

  public String getColor() {
    return color;
  }

  public void setColor(String color) {
    this.color = color;
  }
}

As suggested by @Kukeltje I switch to lazyModel and it works very fine. 正如@Kukeltje建议我切换到lazyModel并且它工作得非常好。 I followed the example in Primefaces Showcase https://www.primefaces.org/showcase/ui/data/datatable/lazy.xhtml With lazy model I guess that paginator must be set to true, or else my example doesn't work. 我按照Primefaces Showcase中的示例https://www.primefaces.org/showcase/ui/data/datatable/lazy.xhtml使用懒惰模型我想包装器必须设置为true,否则我的示例不起作用。

Here's the new version of pagina1.xhtml 这是pagina1.xhtml的新版本

    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:p="http://primefaces.org/ui">
<h:head >
Primefaces Data Table Test
</h:head>
<h:body>
    <h:form id="form">
        <p:dataTable id="dt" var="car" value="#{dtCar.lazyModel}" lazy="true" paginator="true" rows="2">
            <p:column headerText="Id">
                <h:outputText value="#{car.id}" />
            </p:column>

            <p:column filterBy="#{car.model}" headerText="Model">
                <h:outputText value="#{car.model}" />
            </p:column>
            <p:column filterBy="#{car.color}" headerText="Color">
                <h:outputText value="#{car.color}"/>
            </p:column>
        </p:dataTable>
        <h:commandButton id="myButton" value="Load" action="#{dtCar.loadNewCars()}"/>
    </h:form>

</h:body>
</html>

Here is CarBean.java 这是CarBean.java

package it.caditech.testtable;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import org.primefaces.model.LazyDataModel;

@ManagedBean(name = "dtCar")
@ViewScoped
public class CarBean {

  private LazyDataModel<Car> lazyModel;

  @PostConstruct
  public void init() {
    lazyModel = new LazyCarDataModel();
  }

  public LazyDataModel<Car> getLazyModel() {
    return lazyModel;
  }

  public String loadNewCars() {
    ((LazyCarDataModel) lazyModel).loadNewCars();
    return null;
  }

}

Here is the most important part, LazyCarDataModel 这是最重要的部分,LazyCarDataModel

package it.caditech.testtable;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

public class LazyCarDataModel extends LazyDataModel<Car> {

  private List<Car> datasource = new ArrayList<>();

  public LazyCarDataModel() {
    loadNewCars();
  }

  @Override
  public Car getRowData(String rowKey) {
    for (Car car : datasource) {
      if (car.getId().equals(rowKey)) {
        return car;
      }
    }

    return null;
  }

  @Override
  public Object getRowKey(Car car) {
    return car.getId();
  }

  @Override
  public List<Car> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
    List<Car> data = new ArrayList<Car>();

    // filter
    for (Car car : datasource) {
      boolean match = true;

      if (filters != null) {
        for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
          try {
            String filterProperty = it.next();
            Object filterValue = filters.get(filterProperty);
            BeanInfo info = Introspector.getBeanInfo(Car.class);
            String fieldValue = null;
            for (PropertyDescriptor p : info.getPropertyDescriptors()) {
              if (p.getName().equals(filterProperty)) {
                fieldValue = (String) p.getReadMethod().invoke(car, new Object[0]);
              }
            }
            // String fieldValue = String.valueOf(car.getClass().getField(filterProperty).get(car));
            if (filterValue == null || fieldValue.contains(filterValue.toString())) {
              match = true;
            }
            else {
              match = false;
              break;
            }
          }
          catch (Exception e) {
            match = false;
          }
        }
      }

      if (match) {
        data.add(car);
      }
    }

    // rowCount
    int dataSize = data.size();
    setRowCount(dataSize);

    // paginate
    if (dataSize > pageSize) {
      try {
        return data.subList(first, first + pageSize);
      }
      catch (IndexOutOfBoundsException e) {
        return data.subList(first, first + dataSize % pageSize);
      }
    }
    else {
      return data;
    }
  }

  protected void loadNewCars() {
    if (datasource.isEmpty() || datasource.get(0).getModel().equals("myModel")) {
      datasource.clear();
      datasource.add(new Car("1", "gt", "giallo"));
      datasource.add(new Car("2", "scirocco", "azzurro"));
      datasource.add(new Car("3", "duna", "giallo"));
      datasource.add(new Car("4", "diablo", "griggio"));
      datasource.add(new Car("5", "cayenne", "rosso"));
      datasource.add(new Car("6", "aygo", "azzurro"));
    }
    else {
      datasource.clear();
      datasource.add(new Car("7", "myModel", "blu"));
      datasource.add(new Car("8", "punto", "blu"));
      datasource.add(new Car("9", "doblo", "grigio"));
      datasource.add(new Car("10", "smart", "blu"));
      datasource.add(new Car("11", "twingo", "rosso"));
      datasource.add(new Car("12", "twingo", "bianco"));
      datasource.add(new Car("13", "twing", "rosa"));
      datasource.add(new Car("14", "twist", "frizzante"));
      datasource.add(new Car("15", "twelf", "rose"));
      datasource.add(new Car("16", "twang", "riga"));
      datasource.add(new Car("17", "doblo", "blu"));
    }
  }
}

I guess that the car Id property and the method getRowData() and getRowKey() can be omitted, for I don't need selection handling in this case. 我想汽车Id属性和方法getRowData()和getRowKey()可以省略,因为在这种情况下我不需要选择处理。

Try this: 尝试这个:

<p:dataTable id="yourDataTable" var="car"...
<p:poll interval="3" update="yourDataTable" />

I think you are mixing two different features, filter data and show updated data all the time. 我认为您正在混合两种不同的功能,过滤数据并始终显示更新的数据。 For the second case, you have some options to choice. 对于第二种情况,您可以选择一些选项。 You can listen for some event and then update you data or maybe you can ask all the time for the incoming new data, like jMarcel`s example. 您可以收听某些事件然后更新数据,也可以随时询问传入的新数据,例如jMarcel的示例。

check your transaction is concurrent. 检查您的交易是否并发。 use the same transaction. 使用相同的交易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM