Hi.
I use the TreeView to display my data and I have added some logic to load the "branches" of the tree dynamically every time the user clicks on the little triangle. That works perfectly. But now I have an addition to solve and I'm a little stuck regarding the "checked" state.
I use the checkboxes infront of the branches to make the branches checkable and I use the onCheckChange event to trigger the handleTreeViewCheckChange function with the checkChildren and checkParents Options both set to true. So far so good. But if I check a parent before I dynamically load the children, the children do not get checked automatically too. I have added to screenshots so you see the status before and after loading the children so you can better see what I mean. So before clicking on the little triangle infront of "Frankfurt" I check the checkbox for Frankfurt. Then I click the triangle to expand Frankfurt and I would like to achieve the children of Frankfurt are checked too after dynamically loading them.
I thought aoubt running the handleTreeViewCheckChange function again after the loading of the children is done, but of course then the TreeViewExpandChangeEvent is not present anymore, so I can't run it. Also I tried to manually create a new itemHierarchicalIndex and add it to the check state but somehow that did not work either. For your reference I have also attached my script.
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as React from 'react';
import { ENVIRONMENT, LOCATION } from '@iconag/general-types';
// import { LocationSelectionContext } from '@iconag/context';
import { GLOBALS } from '@iconag/globals';
import {
handleTreeViewCheckChange,
processTreeViewItems,
TreeView,
TreeViewCheckDescriptor,
TreeViewExpandChangeEvent,
} from '@progress/kendo-react-treeview';
import {
parseLocationChildren,
parseLocationData,
useReadLocationChildren,
useReadSingleLocationHandler,
} from '@iconag/dataHandlers';
import { convertLocationDataToTreeData } from '@iconag/scripts';
import { mapTree } from '@progress/kendo-react-common';
import Loading from '../../Loading/Loading';
const textField = 'text';
type CheckedLocationIds = { id: string; itemHierarchicalIndex: string };
type LocalizationTreeSelectorProps = {
environment: ENVIRONMENT.environment;
locationURL: string;
};
const LocalizationTreeSelector = (props: LocalizationTreeSelectorProps) => {
const { environment, locationURL } = props;
const { LOCATION_ROOT } = GLOBALS;
const [expanded, setExpanded] = React.useState<string[]>([]);
const [check, setCheck] = React.useState<
| any[]
| (TreeViewCheckDescriptor & {
ids: any[];
})
>({
ids: [],
applyCheckIndeterminate: true,
});
// const { selectedLocations, setSelectedLocations } = React.useContext(
// LocationSelectionContext
// );
const [treeData, setTreeData] = React.useState<
LOCATION.LocationTreeDataItem[]
>([]);
const { readSingleLocation, readSingleLocationService, locationData } =
useReadSingleLocationHandler(parseLocationData);
const { readLocationChildren, locationChildren } = useReadLocationChildren(
parseLocationChildren
);
const [currentParent, setCurrentParent] = React.useState<string | null>(null);
const [checkedLocations, setCheckedLocations] = React.useState<
CheckedLocationIds[]
>([]);
const copyDataAndLocation = (locationIndex: string) => {
const data = treeData.slice();
let location: any;
mapTree(data, 'items', (item) => {
if (item.id === locationIndex) location = item;
});
return { data, location };
};
React.useEffect(() => {
if (readSingleLocationService.status === 'init' && locationData === null) {
readSingleLocation(environment, 'Region', LOCATION_ROOT, locationURL);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useEffect(() => {
if (locationData !== null) {
const treeItem: LOCATION.LocationTreeDataItem =
convertLocationDataToTreeData(locationData, true);
if (treeData.length === 0) {
setTreeData([treeItem]);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [locationData]);
React.useEffect(() => {
if (locationChildren !== null && currentParent !== null) {
const { data, location } = copyDataAndLocation(currentParent);
location.items = locationChildren.map((childItem, idx) => {
const parentLocationIsChecked = checkedLocations.find(
(loc) => loc.id === location.id
);
if (parentLocationIsChecked) {
const newId =
parentLocationIsChecked.itemHierarchicalIndex + '_' + idx;
}
return convertLocationDataToTreeData(childItem, false);
});
setTreeData(data);
setCurrentParent(null);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [locationChildren]);
const onExpandChange = (event: TreeViewExpandChangeEvent) => {
const parentId = event.item.id;
setCurrentParent(parentId);
const expand = expanded.slice();
const index = expand.indexOf(event.itemHierarchicalIndex);
if (index === -1) {
expand.push(event.itemHierarchicalIndex);
} else {
expand.splice(index, 1);
}
setExpanded(expand);
if (event.item.hasChildren && !event.item.items) {
readLocationChildren(
event.item.type,
event.item.id,
environment,
locationURL
);
}
};
const onCheckChange = (event: TreeViewExpandChangeEvent) => {
const newCheckedData = handleTreeViewCheckChange(event, check, treeData, {
checkChildren: true,
checkParents: true,
singleMode: false,
});
if (checkedLocations.find((locIds) => locIds.id === event.item.id)) {
setCheckedLocations((checkedLocations) =>
checkedLocations.filter((loc) => loc.id !== event.item.id)
);
} else {
const newCheckedLocation: CheckedLocationIds = {
id: event.item.id,
itemHierarchicalIndex: event.itemHierarchicalIndex,
};
setCheckedLocations((checkedLocations) => [
...checkedLocations,
newCheckedLocation,
]);
}
setCheck(newCheckedData);
};
if (readSingleLocationService.status === 'loading') {
return <Loading spinnerSize="medium" />;
}
return (
<TreeView
data={processTreeViewItems(treeData, { expand: expanded, check: check })}
onExpandChange={onExpandChange}
onCheckChange={onCheckChange}
expandIcons={true}
textField={textField}
checkboxes={true}
animate={false}
/>
);
};
export default LocalizationTreeSelector;
The useEffect in line 89 is where the children have been loaded and where I then tried to manipulate the check state. I removed my trials though because they did not work at all.
Any help would be greatly appreciated.
Thanks,
Bernd