1

Currently I am trying to build 2 dropdown select option component that only shows columns, but the point is that it should not display the already selected value in other dropdown select option. So each value can only be selected once. So how can I fix that in the code.

Click here to go to Codesandbox

Parent component

    return (
        <div>
            <TableDropdownFilter
                columns={columns}
                onSelect={setHiddenCol1}
            />
            <TableDropdownFilter
                columns={columns}
                onSelect={setHiddenCol2}
            />
            <Table
                columns={columns}
                data={data}
                hiddenColumnsOne={hiddenCol1}
                hiddenColumnsTwo={hiddenCol2}
            />
        </div>
    )

Child component

interface TableDropdownProps {
    columns: any;
    onSelect: any;
    firstFilter?: string;
    secondFilter?: string;
}

export const TableDropdownFilter: FC<TableDropdownProps> = ({
    columns,
    onSelect,
    firstFilter,
    secondFilter
}) => {
    const [columnShow, setColumnShow] = useState<string>("");
    const [openDropdown, setOpenDropdown] = useState(false);
    const wrapperRef = useRef(null);

    const useOutsideAlerter = (ref: any) => {
        useEffect(() => {
            const handleClickOutside = (event: MouseEvent) => {
                if (ref.current && !ref.current.contains(event.target)) {
                    setOpenDropdown(false)
                }
            }

            document.addEventListener("mousedown", handleClickOutside);
            return () => {
                document.removeEventListener("mousedown", handleClickOutside);
            };
        }, [ref]);
    }

    useOutsideAlerter(wrapperRef)

    const dropdownFilter = (selectedColumn: string) => {
        setColumnShow(selectedColumn);
        setOpenDropdown(false);
        onSelect(selectedColumn);
    }

    const toggleDropdownOpen = () => setOpenDropdown(!openDropdown);
    console.log(firstFilter, secondFilter);
    return (
        <TableFilter>
            <TableFilterBlock ref={wrapperRef}>
                <TableFilterInput onClick={() => toggleDropdownOpen()}>
                    {columnShow.length > 0 ? columnShow : "Select"}</TableFilterInput>
                {typeof columnShow}
                <TableFilterDropdown toggleDropdown={openDropdown}>
                    {columns.slice(1).map((item: any, index: number) => (

                        <TableDropdownList key={index}>
                            <div onClick={() => dropdownFilter(item.id)}>
                                {item.id}
                            </div>
                        </TableDropdownList>
                    ))}
                </TableFilterDropdown>
            </TableFilterBlock>
        </TableFilter>
    )
}

1 Answer 1

2

You only need to pass a single value to filter by to the TableDropdownFilter component. Use the passed filter prop to do an inline filtering of the columns options.

TableDropdownFilter

interface TableDropdownProps {
  columns: any;
  onSelect: any;
  filter?: string; // <-- single filter by value
}

export const TableDropdownFilter: FC<TableDropdownProps> = ({
  columns,
  onSelect,
  filter // <-- destructure filter prop
}) => {
  const [columnShow, setColumnShow] = useState<string>("");
  const [openDropdown, setOpenDropdown] = useState(false);
  const wrapperRef = useRef(null);

  ...

  return (
    <TableFilter>
      <TableFilterBlock ref={wrapperRef}>
        <TableFilterInput onClick={() => toggleDropdownOpen()}>
          {columnShow.length > 0 ? columnShow : "Select"}
        </TableFilterInput>
        {typeof columnShow}
        <TableFilterDropdown toggleDropdown={openDropdown}>
          {columns
            .slice(1)
            .filter((item: any) => item.id !== filter) // <-- filter by item is
            .map((item: any, index: number) => (
              <TableDropdownList key={index}>
                <div onClick={() => dropdownFilter(item.id)}>{item.id}</div>
              </TableDropdownList>
            ))}
        </TableFilterDropdown>
      </TableFilterBlock>
    </TableFilter>
  );
};

TableComponent

Pass the appropriate filter value for the "other" select input.

export const TableComponent: FC<TableComponentProps> = ({ columns }) => {
  const [hiddenCol1, setHiddenCol1] = useState<string>("");
  const [hiddenCol2, setHiddenCol2] = useState<string>("");
  const data = useMemo(() => TableContent, []);

  return (
    <div>
      <TableDropdownFilter
        columns={columns}
        onSelect={setHiddenCol1}
        filter={hiddenCol2} // <-- filter by dropdown 2 value
      />
      <TableDropdownFilter
        columns={columns}
        onSelect={setHiddenCol2}
        filter={hiddenCol1} // <-- filter by dropdown 1 value
      />
      <Table
        columns={columns}
        data={data}
        hiddenColumnsOne={hiddenCol1}
        hiddenColumnsTwo={hiddenCol2}
      />
    </div>
  );
};

Edit 2-dropdown-select-option-iterating-through-same-array-but-should-not-be-able-to

Sign up to request clarification or add additional context in comments.

1 Comment

Wow I was pretty close, but the point is that you reversed the props, which is nice tho.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.