skip to Main Content

I have the following Array with Objects in my React TypeScript app for a table.

Inside this table I have grouped table rows (for each category) and in my case I have a select box with an event which should then select all items with the same category:

example table

This is my data:

[
    {
        "id": "6f16bc72-9747-4a2d-b165-14ef358762e6",
        "name": "diesel-south-ullam-photoshop",
        "version": "1.12.40",
        "visible": true,
        "category": "libraries",
        "status": "unselected",
        "searchQuery": "",
        "type": "",
        "filterStatus": {
            "status": "all",
            "category": "all"
        },
        "page": 1
    },
    {
        "id": "aaf6b8f8-0e7f-4420-87dc-fec9451d7935",
        "name": "coupe-when",
        "version": "1.14.8",
        "visible": true,
        "category": "software-components",
        "status": "unselected",
        "searchQuery": "",
        "type": "",
        "filterStatus": {
            "status": "all",
            "category": "all"
        },
        "page": 1
    },
    {
        "id": "3e8797e6-9da7-47d6-a7d6-c2828bf69989",
        "name": "wagon-not-classical",
        "version": "2.15.14",
        "visible": true,
        "category": "software-components",
        "status": "unselected",
        "searchQuery": "",
        "type": "",
        "filterStatus": {
            "status": "all",
            "category": "all"
        },
        "page": 1
    }
]

This is how a TableRow of a TableGroup is getting rendered:

<OwcTableRow
  data-testid={`table-row-${elementIndex}`}
  key={row.id + "-123"}
  selectable
  selected={row.status === "selected"}
  onSelectChange={() => {
    const selectedCategoryItems = tableGroup
      .find((group) => group.key === row.category)
      .elements.filter((singleItem) => singleItem.visible);

    // Determine if all items in the category are currently selected
    const allSelected = selectedCategoryItems.every(
      (itemCat) => itemCat.status === "selected"
    );

    // Toggle the selection status of items within the category
    const updatedData = data.map((newItem) => {
      if (newItem.category === row.category) {
        return {
          ...newItem,
          status: allSelected ? "unselected" : "selected",
        };
      }
      return newItem;
    });

    setData(updatedData);
  }}
>

Table Group is created within this function:

const tableGroup = React.useMemo(
  (): Array<any> => [
    {
      key: 'libraries',
      label: tkeys.overview.libraries.cardTitle,
      elements: getByCategory('libraries'),
    },
    {
      key: 'software-components',
      label: tkeys.overview.softwareComponents.cardTitle,
      elements: getByCategory('software-components'),
    },
  ],
  [getByCategory, i18n.language, tkeys]
);

The Problem is that I can select the Checkbox for "Libraries (0 of 1)" and it selects the tabe row.

But clicking on "Software components (0 of 2)" checkbox in the Table Group I can select both table rows but clicking on a single row also toggles the second row which is incorrect.

2

Answers


  1. Chosen as BEST ANSWER

    I kinda solved the problem that the onSelectChange selects the correct rows but unselects them immediately after it was selected with this.

    const handleSelectItemTest = (row: any) => {
      const updatedData = data.map(newItem => {
        if (newItem.category === row.category) {
          if (newItem.id === row.id) {
            // Toggle the selection status of the clicked row
            return {
              ...newItem,
              status: newItem.status === 'selected' ? 'unselected' : 'selected',
            };
          }
    
          // Update the status of category header based on selected items
          const selectedCategoryItems = tableGroup
            .find(group => group.key === row.category)
            .elements.filter(singleItem => singleItem.visible);
    
          const allSelected = selectedCategoryItems.every(itemCat => itemCat.status === 'selected');
    
          // Update category header status based on selected items
          const updatedItem = {
            ...newItem,
            status: allSelected ? 'selected' : 'unselected',
          };
    
          return updatedItem;
        }
    
        return newItem;
      });
    
      React.useEffect(() => {
        setData(updatedData);
      }, []);
    };
    
    <OwcTableRow
       data-testid={`table-row-${elementIndex}`}
       key={row.id + '-123'}
       selectable
       selected={row.status === 'selected'}
       onSelectChange={() => handleSelectItemTest(row)}
    >
    

    PROBLEM:

    It only works when I use setData inside the useEffect. But then only selecting and unselecting works but the new data is not "saved" as only the checkbox changes but the component it self is not updated or rendered again.

    If I set the data without the useEffect I have the same behaviour as before that the checkbox click selects and unselects the rows.

    Any input?

    UPDATE:

    I just figured out that I only fixed the behaviour of selecting the items and then suddenly unselecting it as I do not update the state at all.

    So the problem still remains that the function updates the items correctly and then at the last iteration it unselects them again because of unknown reasons...


  2. My React is a bit rusty, but I believe that a modification to the updateData function should do the trick.

    const updatedData = data.map((newItem) => {
      if (newItem.category === row.category) {
        if (newItem.id === row.id) {
          // Toggle the selection status of the clicked row
          return {
            ...newItem,
            status: newItem.status === "selected" ? "unselected" : "selected",
          };
        }
    
        // Update the status of category header based on selected items
        const selectedCategoryItems = tableGroup
          .find((group) => group.key === row.category)
          .elements.filter((singleItem) => singleItem.visible);
    
        const allSelected = selectedCategoryItems.every(
          (itemCat) => itemCat.status === "selected"
        );
    
        // Update category header status based on selected items
        const updatedItem = {
          ...newItem,
          status: allSelected ? "selected" : "unselected",
        };
    
        return updatedItem;
      }
    
      return newItem;
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search