contentful / forma-36

A design system by Contentful

Home Page:https://f36.contentful.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

πŸ› Bug - Autocomplete onSelectItem is not executed when an item is selected a second time

cmatthews-uwhealth opened this issue Β· comments

Forma 36 bug report

Summary

As reported earlier in this issue report, repeated clicks on an autocomplete item only trigger onSelectItem with the first click, and clicks afterwards do not trigger onSelectItem.

Environment

Microsoft Edge and Google Chrome, both when running locally and when used as an embedded field in a Contentful App.

Steps to reproduce

The behavior described below can be seen here: https://deploy-preview-61--uwhealth-contentful-ui-extensions.netlify.app/content-feed. Select a "Content Types" value to enable the "Filter Fields" Autocomplete component, then follow the steps below.

  1. Using an <Autocomplete> component with isGrouped applied, click on the input box to deploy the dropdown menu of autocomplete items.
  2. Click one of the options, the onSelectItem function will execute at this time.
  3. Click the same option a second time. The onSelectItem function will not execute.
    Note that the onSelectItem function can be made to execute by clicking a different item and then clicking the original item again.

Expected results

The onSelectItem function should execute every time an item is clicked, even on repeat clicks.

Actual results

The onSelectItem function executes once when an item is clicked, but will not execute again no matter how many times the item is clicked. This bug is "reset" by clicking a different item.

Marking issue as stale since there was no activity for 30 days

Hey, thank you for reporting the issue. But could you provide a minimal example of your implementation? Because if you use a React State to handle your current selection it should work as I tried to reproduce the issue here in our playground but for me it toggles the selection.

In worst case you can reset the internal-form selectedItem of the Autocomplete by reset the selectedItem property

<Autocomplete 
  {...args} 
  selectedItem={mySelectedState} 
  onSelectItem= {(item) => { 
    // do something with your selection
    setMySelectedState('');
 }
} />

Marking issue as stale since there was no activity for 30 days

edit: Actually I think we can ignore this – it is now working, and I think it may have something to do with using objects as items, but then using == or === equality checks, which require the same reference. Using some function that provides an equality check fixed it for me.

Just to comment that I am also running into this issue, it's a bit hard to work out exactly what is going on, but I am seeing that subsequent clicks on the same item do not trigger a subsequent call to the onSelectItem/renderItem.

Can we reopen this?

Screen.Recording.2024-07-17.at.13.11.18.mp4
import { Autocomplete, Stack } from '@contentful/f36-components';
import { SearchIcon } from '@contentful/f36-icons';
import { getStringMatch } from '@contentful/f36-utils';

import { useState } from 'react';

export const DropDownGroupedMinimal = () => {
  const groupedItems = [
    {
      groupTitle: 'Group 1',
      options: [
        {
          name: '1A',
        },
        {
          name: '1B',
        },
        {
          name: '1C',
        },
      ],
    },
    {
      groupTitle: 'Group 2',
      options: [
        {
          name: '2A',
        },
        {
          name: '2B',
        },
        {
          name: '2C',
        },
      ],
    },
  ];
  const [filteredItems, setFilteredItems] = useState(groupedItems);
  const [selectedItems, setSelectedItems] = useState<{ name: string }[]>([]);

  const handleInputValueChange = (value: string) => {
    const newFilteredItems = groupedItems.map((group) => ({
      groupTitle: group.groupTitle,
      options: group.options.filter((option) => option.name.toLowerCase().includes(value.toLowerCase())),
    }));

    setFilteredItems(newFilteredItems);
  };

  const handleSelectItem = (item: { name: string }) => {
    console.log(`Clicked on ${item.name} with [${selectedItems.map((item) => item.name).join(',')}]`);
    setSelectedItems((prevItems) => {
      if (prevItems.some((i) => item === item)) {
        console.log(`Removing ${item.name}`);
        return prevItems.filter((prevItem) => prevItem.name !== item.name);
      } else {
        console.log(`Adding ${item.name}`);
        return [...prevItems, item];
      }
    });
  };

  return (
    <Stack flexDirection="column" alignItems="start">
      <Autocomplete
        isGrouped={true}
        items={filteredItems}
        onInputValueChange={handleInputValueChange}
        onSelectItem={handleSelectItem}
        itemToString={(item) => item.name}
        textOnAfterSelect="clear"
        closeAfterSelect={false}
        icon={<SearchIcon variant="muted" />}
        renderItem={(item, inputValue) => {
          const { before, match, after } = getStringMatch(item.name, inputValue);
          return (
            <>
              {before}
              <b>{match}</b>
              {after}
              {selectedItems.some((i) => i.name === item.name) ? ' (selected)' : ''}
            </>
          );
        }}
      />
    </Stack>
  );
};

Actually, I think we can close this – see edit above!