如何解决TreeGrid 是否支持没有父/子关系的对象?
我正在尝试编写一个应用程序,该应用程序将使用 Vaadin TreeGrid
呈现“任务”树。
需要注意的一件非常重要的事情是树节点类型不包含对父节点或任何子节点的引用。相反,一个单独的类型包含父/子关系,引用树节点类型的项目的唯一 ID。
这两种类型分别存储在各自的数据库表中。数据本身是从 MS Excel 文件中提取的(不要问为什么)并插入到数据库中,应用程序利用该数据库来访问数据。
为了更直观地呈现这一点:
TaskMaster(树节点类型):
@Entity
public class TaskMaster extends AbstractEntity {
private String internalTaskID;
private String name;
private TaskType type;
// other fields
...
}
TaskRelationship(父/子关系):
@Entity
public class TaskRelationship extends AbstractEntity {
private String taskView;
private String parentTaskID;
private String childTaskID;
// other fields
...
}
我编写了 @Repository
和 @Service
类以方便根据需要检索信息。
我无法弄清楚如何让网格加载和显示代表任务树的节点层次结构。我查看了 Vaadin 示例,并创建了一个数据提供程序来尝试加载此数据,但无济于事。它只加载根节点,不加载其他任何东西。
我想知道当节点对象包含对父子对象的引用时,树形网格是否只知道如何处理层次关系。 我的对象不这样做。相反,我尝试在服务和数据提供程序类中设置逻辑以“获取”所需的内容。显然这是行不通的。要么是这样,要么我错过了一些非常微妙的东西。
这里是一些代表我努力的代码。
TaskMasterDataProvider:
public class TaskMasterDataProvider
extends AbstractBackEndHierarchicalDataProvider<TaskMaster,Void> {
...
@Override
public int getChildCount(HierarchicalQuery<TaskMaster,Void> query) {
logger.info("parent: {}",query.getParent());
if (query.getParent() != null) {
int count = service.getChildCount(query.getParent());
logger.info("child count: {}",count);
}
return service.getChildCount(query.getParent());
}
@Override
public boolean hasChildren(TaskMaster item) {
logger.info("item: {}",item);
return service.hasChildren(item);
}
@Override
protected Stream<TaskMaster> fetchChildrenFromBackEnd(HierarchicalQuery<TaskMaster,query.getParent());
return service.getChildren(query.getParent()).stream();
}
}
TaskMasterService:
@Service
@Transactional
public class TaskMasterService {
...
public List<TaskMaster> getTopLevelTasks() {
List<TaskMaster> result = new ArrayList<>();
List<String> topLevelIDs = taskRelationService.getTopLevelParentTaskIDs();
topLevelIDs.forEach(id -> {
TaskMaster task = taskMasterRepo.findByInternalTaskID(id);
if (task != null) {
result.add(task);
}
});
return result;
}
public int getChildCount(TaskMaster parent) {
logger.info("parent: {}",parent);
return parent != null
? taskRelationService.getChildRelationsForParent(parent.getInternalTaskID()).size()
: 0;
}
public boolean hasChildren(TaskMaster parent) {
logger.info("parent: {}",parent);
return parent != null
? !taskRelationService.getChildRelationsForParent(parent.getInternalTaskID()).isEmpty()
: false;
}
public List<TaskMaster> getChildren(TaskMaster parent) {
logger.info("parent: {}",parent);
List<TaskMaster> result = new ArrayList<>();
if (parent != null) {
List<TaskRelationship> childRelations = taskRelationService
.getChildRelationsForParent(parent.getInternalTaskID());
childRelations.forEach(relation -> {
result.add(taskMasterRepo.findByInternalTaskID(relation.getChildTaskID()));
});
}
return result;
}
}
任务树视图:
@Route("tree")
@CssImport("./styles/shared-styles.css")
public class TaskTreeView extends VerticalLayout {
...
private TreeGrid<TaskMaster> taskGrid;
private TaskMasterDataProvider provider;
private TaskMasterService taskService;
public TaskTreeView(TaskMasterService taskService) {
this.taskService = taskService;
setSizeFull();
addClassName("task-tree-grid");
configureView();
}
private void configureView() {
taskGrid = new TreeGrid<>();
taskGrid.addHierarchyColumn(TaskMaster::getName).setHeader("Name");
taskGrid.addColumn(TaskMaster::getType).setHeader("Type");
taskGrid.getColumns().forEach(col -> {
col.setAutoWidth(true);
col.setResizable(true);
});
provider = new TaskMasterDataProvider(taskService);
taskGrid.setDataProvider(provider);
taskGrid.asSingleSelect().addValueChangeListener(event -> {
if (event.getValue() != null) {
provider.refreshItem(event.getValue(),true);
}
});
add(taskGrid);
taskGrid.setItems(taskService.getTopLevelTasks());
}
}
这不是全部,但我认为这是最重要的。如果需要,我可以添加更多。
如果有人知道我的理论是否有任何价值,或者我做错了什么,请告诉我。
解决方法
您为 treeGrid 设置了两次数据提供者 一次在这里
taskGrid.setDataProvider(provider);
这里还有一个
taskGrid.setItems(taskService.getTopLevelTasks());
我认为您应该删除 setItems 指令,fetchChildrenFromBackEnd 的实现应该类似于
@Override
protected Stream<TaskMaster> fetchChildrenFromBackEnd(HierarchicalQuery<TaskMaster,Void> query) {
logger.info("parent: {}",query.getParent());
if (null == query.getParent()) {
return taskService.getTopLevelTasks().stream();
}
return service.getChildren(query.getParent()).stream();
}
,
感谢@tremendous7 给了我导致解决方案的想法。除了给出的想法之外,我还遗漏了数据提供者 getChildCount() 方法中的一个关键逻辑:
@Override
public int getChildCount(HierarchicalQuery<TaskMaster,Void> query) {
logger.info("parent: {}",query.getParent());
int count = 0;
if (query.getParent() == null) {
count = service.getTopLevelTasks().size();
} else {
count = service.getChildCount(query.getParent());
}
logger.info("child count: {}",count);
return count;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。