Vaadin 8.1树状网格基于列的过滤

问题描述:

我需要根据列过滤树状网格。我遵循this问题中提出的解决方案。我已经尝试了下面的代码片段进行过滤,但它不显示任何数据。Vaadin 8.1树状网格基于列的过滤

TreeDataProvider<Project> dataProvider = new TreeDataProvider<>(treeGrid.getTreeData()); 
dataProvider.setFilter(Project -> (Project.getStatus() != null && Project.getStatus().equals(Project.Status.PASS))); 
treeGrid.setDataProvider(dataProvider); 
treeGrid.getDataProvider().refreshAll(); 

是否有另一种方法来过滤数据与vaadin 8.1树网格。

+0

你调试你拉姆达?这应该给你的洞察力。也许没有根元素符合你的标准? –

你的问题是最有可能

dataProvider.setFilter(Project -> (Project.getStatus() != null && Project.getStatus().equals(Project.Status.PASS))); 

我假设你的根和中间节点有一个空的状态,所以它们不匹配过滤器,并因此他们的孩子将不会被显示出来。


为简单起见,你可以允许与状态空,或符合过滤条件的项目,但有时你可能最终与空的中间节点,因为没有孩子会匹配滤波器:

dataProvider.setFilter(Project -> (Project.getStatus() == null || Project.getStatus().equals(Project.Status.PASS))); 

tree grid empty nodes on filtering


防弹解决方案是有点麻烦,因为你需要允许至少有一个孩子相匹配的层次结构节点过滤。这可能是矫枉过正,但这是我可以考虑在内存数据中使用的最快方法,所以任何有改进建议的人都请分享一下。如果数据是从数据库查询中过滤的,那么您可能不需要这样做。

无论如何,我已将flatten方法添加到Project,很明显,它将项目层次结构变为可快速遍历的项目流,并查看它们是否与您的过滤器匹配。贝娄完全实施,基于the other question you linked。我也改变了数据在刚进入树网格,这样你就不必做黑客new TreeDataProvider<>(treeGrid.getTreeData());

import com.vaadin.data.TreeData; 
import com.vaadin.data.provider.TreeDataProvider; 
import com.vaadin.ui.ComboBox; 
import com.vaadin.ui.Notification; 
import com.vaadin.ui.TreeGrid; 
import com.vaadin.ui.VerticalLayout; 

import java.util.*; 
import java.util.stream.Stream; 

public class BasicTreeGrid extends VerticalLayout { 

    // used to generate some random data 
    private final Random random = new Random(); 

    public BasicTreeGrid() { 
     // basic setup 
     setSizeFull(); 
     TreeGrid<Project> treeGrid = new TreeGrid<>(); 
     treeGrid.setSizeFull(); 
     addComponent(treeGrid); 
     treeGrid.addColumn(Project::getName).setCaption("Project Name").setId("name-column"); 
     treeGrid.addColumn(Project::getHoursDone).setCaption("Hours Done").setId("hour-column"); 
     treeGrid.addColumn(Project::getLastModified).setCaption("Last Modified").setId("date-column"); 
     treeGrid.addColumn(Project::getStatus).setCaption("Status").setId("status-column"); 

     // some listeners for interaction 
     treeGrid.addCollapseListener(event -> Notification 
       .show("Project '" + event.getCollapsedItem().getName() + "' collapsed.", Notification.Type.TRAY_NOTIFICATION)); 
     treeGrid.addExpandListener(event -> Notification 
       .show("Project '" + event.getExpandedItem().getName() + "' expanded.", Notification.Type.TRAY_NOTIFICATION)); 


     // add the list of root projects and specify a provider of sub-projects 
     TreeData<Project> data = new TreeData<>(); 
     data.addItems(generateProjectsForYears(2010, 2016), Project::getSubProjects); 
     TreeDataProvider<Project> dataProvider = new TreeDataProvider<>(data); 
     treeGrid.setDataProvider(dataProvider); 

     // filter combo setup 
     ComboBox<Status> statusFilter = new ComboBox<>(); 
     statusFilter.setItems(Status.values()); 
     statusFilter.setEmptySelectionCaption("ALL"); 
     statusFilter.addValueChangeListener(event -> { 
      if (event.getValue() == null) { 
       dataProvider.clearFilters(); 
      } else { 
       dataProvider.setFilter(project -> { 
        if (project.getSubProjects() == null | project.getSubProjects().isEmpty()) { 
         // include final nodes matching the filter 
         return project.getStatus() == null || project.getStatus() == event.getValue(); 
        } else { 
         // include root and intermediate nodes that have children matching the filter 
         return project.flatten().anyMatch(subProject -> subProject.getStatus() == event.getValue()); 
        } 
       }); 
      } 
     }); 

     // add filter combo to header 
     treeGrid.appendHeaderRow().getCell("status-column").setComponent(statusFilter); 
    } 

    // generate some random projects 
    private List<Project> generateProjectsForYears(int startYear, int endYear) { 
     List<Project> projects = new ArrayList<>(); 

     for (int year = startYear; year <= endYear; year++) { 
      Project yearProject = new Project("Year " + year); 

      for (int i = 1; i < 2 + random.nextInt(5); i++) { 
       Project customerProject = new Project("Customer Project " + i); 
       customerProject.setSubProjects(Arrays.asList(
         new LeafProject("Implementation", random.nextInt(100), year, Status.values()[random.nextInt(3)]), 
         new LeafProject("Planning", random.nextInt(10), year, Status.values()[random.nextInt(3)]), 
         new LeafProject("Prototyping", random.nextInt(20), year, Status.values()[random.nextInt(3)]))); 
       yearProject.addSubProject(customerProject); 
      } 
      projects.add(yearProject); 
     } 
     return projects; 
    } 

    // project status 
    enum Status { 
     NOT_STARTED, IN_PROGRESS, DONE 
    } 

    // basic parent (or intermediate child) bean used for easy binding 
    class Project { 
     private List<Project> subProjects = new ArrayList<>(); 
     private String name; 
     private Status status; 

     public Project(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return name; 
     } 

     public List<Project> getSubProjects() { 
      return subProjects; 
     } 

     public void setSubProjects(List<Project> subProjects) { 
      this.subProjects = subProjects; 
     } 

     public void addSubProject(Project subProject) { 
      subProjects.add(subProject); 
     } 

     public int getHoursDone() { 
      return getSubProjects().stream().map(project -> project.getHoursDone()).reduce(0, Integer::sum); 
     } 

     public Date getLastModified() { 
      return getSubProjects().stream().map(project -> project.getLastModified()).max(Date::compareTo).orElse(null); 
     } 

     public Status getStatus() { 
      return status; 
     } 

     public void setStatus(Status status) { 
      this.status = status; 
     } 

     // flatten the project hierarchy into a stream of items 
     public Stream<Project> flatten() { 
      return Stream.concat(
        Stream.of(this), 
        subProjects.stream().flatMap(Project::flatten)); 
     } 
    } 


    // basic final child (can not have other children) bean used for easy binding 
    class LeafProject extends Project { 
     private int hoursDone; 
     private Date lastModified; 

     public LeafProject(String name, int hoursDone, int year, Status status) { 
      super(name); 
      setStatus(status); 
      this.hoursDone = hoursDone; 
      lastModified = new Date(year - 1900, random.nextInt(12), random.nextInt(10)); 
     } 

     @Override 
     public int getHoursDone() { 
      return hoursDone; 
     } 

     @Override 
     public Date getLastModified() { 
      return lastModified; 
     } 
    } 
} 

结果:

tree grid filtering