Telerik Forums
KendoReact Forum
1 answer
56 views

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 

Konstantin Dikov
Telerik team
 answered on 10 Jul 2024
1 answer
57 views

Hi.

In your PDFProcessing component you have the possibility as shown on this page, to add manual page breaks using CSS classes. 

I am using the drawDOM and exportPDF functionalities similar to what is shown here to generate a Base64String of my pages and then push that string directly to a PDFViewer instance so I can generate a PDF on the fly and show it in the viewer. The question is if there is a simliar functionality to add manual page breaks as with the PDFProcessing component if I generate the PDF on the fly?

To show what I've done, I have put my code here.

Thanks for any help.

Greetings,

Bernd

Bernd
Top achievements
Rank 5
Bronze
Bronze
Bronze
 answered on 10 Jul 2024
1 answer
83 views

I have two events, event 1 ends at 08.34 and event 2 starts at 08.34, but are not stacking vertically.

If i change the duration of the events to fill a "slotDuration" then i renders correctly. 

How to get the events to stack vertically for shorter events?

 

 

Konstantin Dikov
Telerik team
 answered on 10 Jul 2024
1 answer
113 views
For unit testing automation, it would be really convenient if we could set the aria-label (as opposed to the aria-described-by or the aria-labelled-by) attribute to the ComboBox component. I noticed that the ComboBoxProps doesn't have this option available. Is there a way to circumvent the props and manually add it?
Vessy
Telerik team
 answered on 04 Jul 2024
5 answers
70 views

How do we use our custom icons in Kendo?

How to set an icon to the form error message?

Yanko
Telerik team
 answered on 03 Jul 2024
1 answer
151 views
I have 2 tabs in my page. Based on some Boolean condition i have to show the tabs with custom title on each tab on hover. Kindly help
Yanko
Telerik team
 answered on 03 Jul 2024
1 answer
208 views

Hi Kendo team,

I'm exploring ways to convert Figma component designs directly into code. Has your component been convertable and what tools or methods would you recommend? I'm particularly interested in solutions that support React or other modern frameworks.

Nick Iliev
Telerik team
 answered on 03 Jul 2024
0 answers
79 views
I have a grid with in-cell editing & i have custom cells for each column. I am showing a tooltip on hover when there is a error in each cell. The default position of the tooltip is bottom.  My requirement is only for the last row of the grid, i have to change the tooltip position on the top. Please help.
Abhishek
Top achievements
Rank 2
Iron
Iron
Iron
 asked on 03 Jul 2024
1 answer
57 views
How can I integrate our internal design token repository with Telerik Kendo UI to create a custom theme and publish it as a project?
Nick Iliev
Telerik team
 answered on 01 Jul 2024
1 answer
169 views

Problem summary: When including the ability to reorder columns and toggle column visibility on a grid ColumnMenu, the column order gets corrupted despite the correct order being stored and retrieved from session storage.

Detailed description: We want our users to be able to persist their grid column order and visibility. We also want the column order to be updated in the column menu. The column menu context keeps track of the order with a list of GridColumnProps. We save the column menu filter context and the column order into session storage. 

Grid

ColumnMenuContext



Session storage


Because GridColumnProps doesn't contain an order index parameter, on our  'onColumnsReorder' event, I take the the GridColumnProps lists and order them based on the orderIndex of the columns passed to the events. This works as expected for when I only reorder the columns or I only toggle column visibility. However, if I reorder the columns and then toggle visibility without refreshing, I lose the original column order. I have verified multiple times in the console that the order being saved to session storage is correct. When I refresh after the column order is lost, it then loads the columns with the correct order. 

I've seen this same behavior on other Telerik demos where you set reorderable={true} on a grid with a column menu. Easy steps to reproduce are always to switch the first two columns in the grid, and then toggle the first column's visibility to off. I've included text files (originally tsx files) with our data-grid component implementation and its component dependencies for reference. 'data-grid.tsx' contains the logic for saving the filter order and column order/visibility in the 'onColumnsChange' and the 'onColumnsReorder' event handlers.

If this can't be done with GridColumnProps, is there a different object we could save to the ColumnMenu's lists that would enable direct index tracking?

Konstantin Dikov
Telerik team
 answered on 28 Jun 2024
Narrow your results
Selected tags
Tags
+? more
Top users last month
Will
Top achievements
Rank 2
Iron
Motti
Top achievements
Rank 1
Iron
Hester
Top achievements
Rank 1
Iron
Bob
Top achievements
Rank 3
Iron
Iron
Veteran
Thomas
Top achievements
Rank 2
Iron
Want to show your ninja superpower to fellow developers?
Top users last month
Will
Top achievements
Rank 2
Iron
Motti
Top achievements
Rank 1
Iron
Hester
Top achievements
Rank 1
Iron
Bob
Top achievements
Rank 3
Iron
Iron
Veteran
Thomas
Top achievements
Rank 2
Iron
Want to show your ninja superpower to fellow developers?
Want to show your ninja superpower to fellow developers?