I have a TreeDataGrid with a renderer on column “isEnabled” like this (simplified):
@Supply(to = "treeDataGrid.isEnabled", subject = "renderer")
private Renderer<Entity> treeDataGridIsEnabledRenderer() {
return createEnabledCheckBox();
}
private ComponentRenderer<JmixCheckbox, Entity> createEnabledCheckBox() {
return new ComponentRenderer<>(entity -> {
JmixCheckbox checkbox = uiComponents.create(JmixCheckbox.class);
checkbox.setValue(Boolean.TRUE.equals(entity.getIsEnabled()));
// Value change listener to update isEnabled when the checkbox state changes
checkbox.addValueChangeListener(e -> {
// Update the entity's enabled property when checkbox value changes
entity.setIsEnabled(e.getValue()); //-->Error is here
formatDc.replaceItem(entity);
if (e.getValue()) {
// Check the parent if the child is selected
checkParentRecursive(entity);
} else {
// Uncheck all children if the parent is unchecked
uncheckAllDescendants(entity);
}
// Refresh the grid to ensure UI updates
// treeDataGrid.getDataProvider().refreshItem(entity);
});
return checkbox;
});
}
private void checkParentRecursive(Entity child) {
Entity parent = child.getParent();
if (parent != null) {
parent.setIsEnabled(true);
// Update the parent entity in the data container
// and refresh the parent component
formatDc.replaceItem(parent);
// treeDataGrid.getDataProvider().refreshItem(parent);
// Recursively check the parent's parent
checkParentRecursive(parent);
}
}
private void uncheckAllDescendants(Entity parent) {
// Retrieve the parent entity using the hierarchy property
List<Entity> children = parent.getChildren();
if (null != children && !children.isEmpty()) {
log.info("Child size: {}", children.size());
for (Entity child : children) {
if (Boolean.TRUE.equals(child.getIsEnabled())) {
child.setIsEnabled(false);
// Update the child entity in the data container
// and refresh the child component
formatDc.replaceItem(child);
// treeDataGrid.getDataProvider().refreshItem(child);
}
// Recursively uncheck the child’s children
uncheckAllDescendants(child);
}
}
}
Everything works fine if I check a last node of the element (childless), it will tick its parent up to root. However, if I check a node that have child, it will popup an error. Refer to the gif below:
What should I do to be able to check/uncheck the parent without error? Thanks
Edit:
this is the error log
java.lang.NullPointerException: Cannot invoke "com.vaadin.flow.component.Component.getElement()" because "recreatedComponent" is null
at com.vaadin.flow.data.provider.AbstractComponentDataGenerator.refreshData(AbstractComponentDataGenerator.java:51) ~[flow-data-24.3.10.jar:24.3.10]
at com.vaadin.flow.data.provider.CompositeDataGenerator.lambda$refreshData$2(CompositeDataGenerator.java:62) ~[flow-data-24.3.10.jar:24.3.10]
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
at com.vaadin.flow.data.provider.CompositeDataGenerator.refreshData(CompositeDataGenerator.java:62) ~[flow-data-24.3.10.jar:24.3.10]
at com.vaadin.flow.data.provider.CompositeDataGenerator.lambda$refreshData$2(CompositeDataGenerator.java:62) ~[flow-data-24.3.10.jar:24.3.10]
at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
at com.vaadin.flow.data.provider.CompositeDataGenerator.refreshData(CompositeDataGenerator.java:62) ~[flow-data-24.3.10.jar:24.3.10]
at com.vaadin.flow.data.provider.DataCommunicator.refresh(DataCommunicator.java:405) ~[flow-data-24.3.10.jar:24.3.10]
at io.jmix.flowui.component.delegate.AbstractGridDelegate.itemsValueChanged(AbstractGridDelegate.java:273) ~[jmix-flowui-2.3.1.jar:na]
at io.jmix.flowui.kit.event.EventBus.fireEvent(EventBus.java:82) ~[jmix-flowui-kit-2.3.1.jar:na]
at io.jmix.flowui.data.grid.ContainerDataGridItems.containerItemPropertyChanged(ContainerDataGridItems.java:76) ~[jmix-flowui-2.3.1.jar:na]
at io.jmix.core.common.event.EventHub.publish(EventHub.java:172) ~[jmix-core-2.3.1.jar:na]
at io.jmix.flowui.model.impl.InstanceContainerImpl.itemPropertyChanged(InstanceContainerImpl.java:182) ~[jmix-flowui-2.3.1.jar:na]
at io.jmix.flowui.model.impl.CollectionContainerImpl.itemPropertyChanged(CollectionContainerImpl.java:228) ~[jmix-flowui-2.3.1.jar:na]
at io.jmix.core.entity.BaseEntityEntry.firePropertyChanged(BaseEntityEntry.java:198) ~[jmix-core-2.3.1.jar:na]
at io.jmix.core.impl.EntityInternals.fireListeners(EntityInternals.java:90) ~[jmix-core-2.3.1.jar:na]
at com.inf.ph.entity.MsgSubStructFormat.setIsEnabled(MsgSubStructFormat.java:214) ~[main/:na]
at com.inf.ph.view.gtwtemp.GtwTempDetailView.lambda$createEnabledCheckBox$196ab55b$1(GtwTempDetailView.java:401) ~[main/:na]