es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

reactstrap, menú desplegable con entrada de búsqueda

Con el fin de beneficiar el diseño del desplegable de reacciones, quiero utilizarlo como una barra de búsqueda con los resultados mostrados en el menú desplegable. Pero el oyente de teclas por defecto que permite navegar por los resultados mediante el teclado (teclas de flecha arriba/abajo), sólo es capturado por Input, y no puede propagarlo al padre o lo que sea que esté escuchando los eventos de teclas cuando el resultado es visible.

Ahora viendo este sandbox, estoy buscando dos enfoques, ya sea agregar oyentes de eventos de teclado como comportamiento de desplegable por defecto, o personalizar el <Input type=" search"/>.

Ahora la pregunta es cómo hacerlo. Supongo que manejar el oyente de teclas podría ser mejor.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Utilizando Eventos de Teclado para Mejorar el Diseño del Dropdown de Reactstrap

    Para capturar los eventos de las teclas de flecha en el Dropdown de Reactstrap y habilitar la navegación a través de los resultados por teclado, podemos agregar eventos de teclado a la función de Dropdown por defecto.

    1. Para hacer esto, necesitamos hacer referencia al elemento de menú desplegable y agregar los eventos para las teclas de flecha hacia arriba y hacia abajo.
    2. Usaremos el gancho de useEffect para adjuntar y retirar los eventos cuando el Dropdown se abra y cierre respectivamente.
    3. También tendremos en cuenta el artículo activo actual del dropdown utilizando la variable de estado de activeIndex.
    4. Luego, podemos actualizar la variable de estado de activeIndex basándonos en los eventos de teclado y mover el enfoque al artículo de desplazamiento correspondiente.

    Aquí está el código actualizado:

    import { useState, useEffect, useRef } from "react";
    import {
      Dropdown,
      DropdownToggle,
      DropdownMenu,
      DropdownItem,
      Input
    } from "reactstrap";
    
    export default function App() {
      const [isOpen, setIsOpen] = useState(false); // estado Dropdown
      const [query, setQuery] = useState(""); // consulta de búsqueda
      const [fetchedItems, setFetchedItems] = useState([]); // ítems recogidos
      const [activeIndex, setActiveIndex] = useState(-1); // índice del activo dropdown
    
      const dropdownRef = useRef(null); // ref del dropdown
    
      // Recogemos los ítems de la API
      useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/posts")
          .then((response) => response.json())
          .then((data) => setFetchedItems(data.map((item) => item.title)))
          .catch((error) => console.error(error));
      }, []);
    
      // Manejamos los eventos de las teclas de flechas hacia arriba y hacia abajo
      useEffect(() => {
        const handleKeyDown = (event) => {
          const dropdownMenu = dropdownRef.current.querySelector(
            ".dropdown-menu.show"
          );
          if (!dropdownMenu) return;
    
          switch (event.key) {
            case "ArrowUp":
              event.preventDefault();
              setActiveIndex((prevIndex) =>
                prevIndex > 0 ? prevIndex - 1 : fetchedItems.length - 1
              );
              break;
            case "ArrowDown":
              event.preventDefault();
              setActiveIndex((prevIndex) =>
                prevIndex < fetchedItems.length - 1 ? prevIndex + 1 : 0
              );
              break;
            case "Enter":
              event.preventDefault();
              const activeItem = dropdownMenu.children[activeIndex];
              if (activeItem) activeItem.click();
              break;
            default:
              break;
          }
        };
    
        document.addEventListener("keydown", handleKeyDown);
        return () => document.removeEventListener("keydown", handleKeyDown);
      }, [isOpen, activeIndex, fetchedItems]);
    
      return (
        <dropdown toggle="{()" ==""> setIsOpen(!isOpen)} isOpen={isOpen} innerRef={dropdownRef}>
          <dropdowntoggle>
            <input type="search" onchange="{(e)" ==""> setQuery(e.target.value)}
              placeholder="Buscar Placeholder"
            />
          </dropdowntoggle>
          <dropdownmenu>
            {fetchedItems
              .filter((item) => item.toLowerCase().includes(query.toLowerCase()))
              .map((item, index) => (
                <dropdownitem key="{item}" active="{activeIndex" =="=" index}="" onclick="{()" ==""> alert(`Clickeado: ${item}`)}
                >
                  {item}
                </dropdownitem>
              ))}
          </dropdownmenu>
        </dropdown>
      );
    }
    

    Con estos cambios, el Dropdown de Reactstrap ahora es completamente funcional como una barra de búsqueda con resultados mostrados en el menú desplegable. Uno puede navegar a través de los resultados usando las teclas de flecha hacia arriba y hacia abajo y seleccionar el ítem activo usando la tecla Enter.

Comments are closed.