2017-08-03 77 views
0

我需要根據列過濾樹狀網格。我遵循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

你調試你拉姆達?這應該給你的洞察力。也許沒有根元素符合你的標準? –

回答

1

你的問題是最有可能

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