Dave
Dave

Reputation: 19110

How do I allow option selection in IonSelect to be triggered by typing a letter on the keyboard?

I'm using Ionic 7 and React 18. I have this IonSelect component for selecting a state from an alphabetized list

    <IonSelect
      interface='popover'
      aria-label='State'
      value={contactInfo?.mailingAddress.region?.id}
      placeholder='Select State'
      onIonChange={(e) =>
        setContactInfo((prevInfo) => {
          const selectedRegionId = e.detail.value
          return {
            ...prevInfo,
            mailingAddress: {
              ...prevInfo.mailingAddress,
              region: regions.find((region) => region.id === selectedRegionId) || null
            }
          }
        })
      }
    >
      {regions.map((stateOption) => (
        <IonSelectOption key={stateOption.id} value={stateOption.id}>
          {stateOption.name}
        </IonSelectOption>
      ))}
    </IonSelect>

I would like this to behave like the HTML select menus, whereby when you type a letter the list scrolls to the options starting with that letter. How do I adjust what I have to accommodate this?

Upvotes: 0

Views: 146

Answers (1)

Akalanka Dissanayake
Akalanka Dissanayake

Reputation: 596

Please follow this example. you can use this as a base code for your requirements.

  1. The idea is when you render select add an identifier for each option.
  2. When the select popup opens add a key-down event listener by hook.
  3. Capture the key-down event key, and find the select option by identifier.
  4. Scroll to the item.

import React, { useEffect, useState } from "react";
import { IonItem, IonList, IonSelect, IonSelectOption } from "@ionic/react";

function Example() {
  const [st, setSt] = useState("");
  const [items, setItems] = useState([
    "Abc", "Bcd", "Def", "Ghijk", "HIdada", "ppp", "zrrr", "xrrr", "crrr", "vrrr",
    "brrr", "nrrr", "mrrr", "arrr", "srrr", "drrr", "frrr", "gqqq", "zxs", "qwe", "ert", "trg",
  ]);

  useEffect(() => {
    let content = document.getElementsByClassName("alert-radio-group");

    const handleKeyDown = (e) => {
      const key = e.key;
      var filteredItems = items.filter((item) =>
        item.toLocaleLowerCase().startsWith(e.key)
      );
      console.log(filteredItems);
      if (filteredItems && filteredItems.length > 0) {
        var filteredItem = filteredItems[0];
        let elements = document?.getElementsByClassName(
          filteredItem.toLocaleLowerCase()
        );
        console.log(elements);
        const y = document?.getElementById(elements[1].id)?.offsetTop;
        console.log(y);
        y && content[0]?.scrollTo(0, y);
      }
      console.log(e.key);
    };

    document.addEventListener("keydown", handleKeyDown, true);

    return () => {
      document.removeEventListener("keydown", handleKeyDown);
    };
  }, [st]);

  return (
    <IonList>
      <IonItem>
        <IonSelect
          className="wrapper"
          aria-label="Fruit"
          placeholder="Select fruit"
          onIonChange={() => {
            setSt("X");
          }}
          onIonCancel={() => {
            setSt("X");
          }}
          onIonDismiss={() => {
            setSt("X");
          }}
          onClick={() => {
            setSt("L");
          }}
        >
          {items.map((item) => (
            <IonSelectOption
              key={item}
              value={item}
              className={item.toLocaleLowerCase()}
            >
              {item}
            </IonSelectOption>
          ))}
        </IonSelect>
      </IonItem>
    </IonList>
  );
}

export default Example;

Upvotes: 1

Related Questions