Filtro de pesquisa de grade React

    O recurso Ignite UI for React Filtro de Busca no React Grid permite o processo de encontrar valores na coleta de dados. Facilitamos a configuração dessa funcionalidade e ela pode ser implementada com uma caixa de busca de entrada, botões, navegação por teclado e outros recursos úteis para uma experiência de usuário ainda melhor. Embora os navegadores ofereçam funcionalidade nativa de busca de conteúdo, na maioria das vezes elesIgrGrid virtualizam suas colunas e linhas que estão fora de vista. Nesses casos, a busca nativa do navegador não consegue buscar dados nas células virtualizadas, pois elas não fazem parte do DOM. Estendemos a grade baseada em tabelas do React Material com uma API de busca que permite que você pesquise pelo conteúdo virtualizado doIgrGrid.

    React Search Example

    O exemplo a seguir representaIgrGrid uma caixa de entrada de busca que permite buscar em todas as colunas e linhas, bem como opções específicas de filtragem para cada coluna.

    React Search Usage

    Grid Setup

    Vamos começar criando nossa grade e vinculando-a aos nossos dados. Também adicionaremos alguns estilos personalizados para os componentes que usaremos!

    .gridSize {
        --ig-size: var(--ig-size-small);
    }
    
    <IgrGrid ref={gridRef} className="gridSize" autoGenerate={false} allowFiltering={true} data={data}>
        <IgrColumn field="IndustrySector" dataType="string" sortable={true}></IgrColumn>
        <IgrColumn field="IndustryGroup" dataType="string" sortable={true}></IgrColumn>
        <IgrColumn field="SectorType" dataType="string" sortable={true}></IgrColumn>
        <IgrColumn field="KRD" dataType="number" sortable={true}></IgrColumn>
        <IgrColumn field="MarketNotion" dataType="number" sortable={true}></IgrColumn>
    </IgrGrid>
    

    Ótimo, e agora vamos nos preparar para a nossaIgrGrid API de busca! Podemos criar algumas propriedades, que podem ser usadas para armazenar o texto pesquisado atualmente e se a busca é sensível a maiúsculas minúsculas e/ou por uma correspondência exata.

    const gridRef = useRef<IgrGrid>(null);
    const [caseSensitiveSelected, setCaseSensitiveSelected] = useState<boolean>(false);
    const [exactMatchSelected, setExactMatchSelected] = useState<boolean>(false);
    const [searchText, setSearchText] = useState('');
    

    React Search Box Input

    Agora vamos criar nossa entrada de busca! Ao vincularsearchText nossa àvalue propriedade da nossa entrada recém-criada e assinar oinputOccured evento, podemos detectar cada modificaçãosearchText feita pelo usuário. Isso nos permitirá usar osIgrGridfindNext métodosfindPrev e os para destacar todas as ocorrências dosearchText e rolar para o próximo/anterior (dependendo do método invocado).

    Tanto os métodos comofindNext osfindPrev têm três argumentos:

    • Text: string (o texto que estamos procurando)
    • (opcional)CaseSensitive: booleano (deve a busca ser sensível a maiúsculas minúsculas ou não, valor padrão é falso)
    • (opcional)ExactMatch: booleano (se a busca for por uma correspondência exata ou não, o valor padrão é falso)

    Ao buscar por uma correspondência exata, a API de busca destaca como resultados apenas os valores das células que correspondem inteiramente aSearchText, levando também em consideração a sensibilidade entre maiúsculas minúsculas. Por exemplo, as strings 'software' e 'Software' são uma correspondência exata, sem considerar a sensibilidade maiúscula.

    Os métodos acima retornam um valor numérico (o número de vezes que contémIgrGrid a cadeia dada).

    const handleOnSearchChange = (event: IgrComponentValueChangedEventArgs) => {
        setSearchText(event.detail);
        nextSearch(event.detail, caseSensitiveSelected, exactMatchSelected);
    }
    
    <IgrInput name="searchBox" value={searchText} onInput={handleOnSearchChange}>
    </IgrInput>
    

    Add Search Buttons

    Para pesquisar e navegar livremente entre nossos resultados, vamos criar alguns botões invocando osfindNext métodos efindPrev dentro dos respectivos manipuladores de eventos de clique dos botões.

    const prevSearch = (text: string, caseSensitive: boolean, exactMatch: boolean) => {
        gridRef.current.findPrev(text, caseSensitive, exactMatch);
    }
    
    const nextSearch = (text: string, caseSensitive: boolean, exactMatch: boolean) => {
        gridRef.current.findNext(text, caseSensitive, exactMatch);
    }
    
    <IgrIconButton variant="flat" name="prev" collection="material" onClick={() => prevSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
    </IgrIconButton>
    <IgrIconButton variant="flat" name="next" collection="material" onClick={() => nextSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
    </IgrIconButton>
    

    Também podemos permitir que os usuários naveguem pelos resultados usando as setas do teclado e a ENTER tecla. Para alcançar isso, podemos lidar com o evento keydown da nossa entrada de busca impedindo o movimento padrão do caret da entrada com oPreventDefault método e invocar ofindNext /findPrev métodos dependendo da tecla que o usuário pressionou.

    const searchKeyDown = (e: KeyboardEvent<HTMLElement>) => {
        if (e.key === 'Enter') {
            e.preventDefault();
            nextSearch(searchText, caseSensitiveSelected, exactMatchSelected);
        } else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
            e.preventDefault();
            prevSearch(searchText, caseSensitiveSelected, exactMatchSelected);
        }
    }
    
     <div onKeyDown={searchKeyDown}>
        <IgrInput name="searchBox" value={searchText} onInput={handleOnSearchChange}></IgrInput>
    </div>
    

    Case Sensitive and Exact Match

    Agora vamos permitir que o usuário escolha se a busca deve ser sensível de maiúsculas e minúsculas e/ou com uma correspondência exata. Para isso, podemos usar oIgrChip componente junto com uma variável de estado booleana para indicar se o IgrChip está selecionado.

    const [caseSensitiveSelected, setCaseSensitiveSelected] = useState<boolean>(false);
    const [exactMatchSelected, setExactMatchSelected] = useState<boolean>(false);
    
    const handleCaseSensitiveChange = (event: IgrComponentBoolValueChangedEventArgs) => {
        setCaseSensitiveSelected(event.detail);
        nextSearch(searchText, event.detail, exactMatchSelected);
    }
    
    const handleExactMatchChange = (event: IgrComponentBoolValueChangedEventArgs) => {
        setExactMatchSelected(event.detail);
        nextSearch(searchText, caseSensitiveSelected, event.detail);
    }
    
    <IgrChip selectable={true} onSelect={handleCaseSensitiveChange}>
        <span>Case Sensitive</span>
    </IgrChip>
    <IgrChip selectable={true} onSelect={handleExactMatchChange}>
        <span>Exact Match</span>
    </IgrChip>
    

    Persistence

    E se quisermos filtrar e ordenar nossosIgrGrid registros ou até mesmo adicionar e remover registros? Após essas operações, os destaques da nossa busca atual são automaticamente atualizados e persistem sobre qualquer texto que corresponda aoSearchText! Além disso, a busca funcionará com paginação e manterá os destaques durante as alterações daIgrGridPerPage propriedade.

    Adding icons

    Usando alguns de nossos outros componentes, podemos criar uma interface de usuário enriquecida e melhorar o design geral de toda a nossa barra de pesquisa! Podemos ter um bom ícone de pesquisa ou exclusão à esquerda da entrada de pesquisa, alguns chips para nossas opções de pesquisa e alguns ícones de design de material combinados com belos botões de estilo ondulado para nossa navegação à direita.

    Vamos começar criando os botões de navegação de busca à direita da entrada, adicionando dois botões no estilo ripple com ícones de material. Os manipuladores dos eventos de clique permanecem os mesmos - invocando ofindNext /findPrev métodos.

    • Para exibir alguns chips que alternam asCaseSensitive propriedades eExactMatch e Substituímos as caixas de seleção por duas fichas elegantes. Sempre que um chip é clicado, invocamos seu respectivo manipulador.
    const prevSearch = (text: string, caseSensitive: boolean, exactMatch: boolean) => {
        gridRef.current.findPrev(text, caseSensitive, exactMatch);
    }
    
    const nextSearch = (text: string, caseSensitive: boolean, exactMatch: boolean) => {
        gridRef.current.findNext(text, caseSensitive, exactMatch);
    }
    
    <div slot="suffix">
        <IgrIconButton variant="flat" name="prev" collection="material" onClick={() => prevSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
            <IgrRipple></IgrRipple>
        </IgrIconButton>
        <IgrIconButton variant="flat" name="next" collection="material" onClick={() => nextSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
            <IgrRipple></IgrRipple>
        </IgrIconButton>
    </div>
    

    Agora vamos adicionar os ícones de pesquisa e limpeza à esquerda da entrada:

    const clearSearch = () => {
        setSearchText('');
        gridRef.current.clearSearch();
    }
    
    <div slot="prefix">
        {searchText.length === 0 ? (
            <IgrIconButton variant="flat" name="search"  collection="material">
            </IgrIconButton>
            ) : (
            <IgrIconButton variant="flat" name="clear" collection="material" onClick={clearSearch}>
            </IgrIconButton>
        )}
    </div>
    

    Finalmente, este é o resultado final quando combinamos tudo:

    useEffect(() => {
        registerIconFromText("search", searchIconText, "material");
        registerIconFromText("clear", clearIconText, "material");
        registerIconFromText("prev", prevIconText, "material");
        registerIconFromText("next", nextIconText, "material");
    }, []);
    
    <IgrInput name="searchBox" value={searchText} onInput={handleOnSearchChange}>
        <div slot="prefix">
            {searchText.length === 0 ? (
                <IgrIconButton variant="flat" name="search"  collection="material">
                </IgrIconButton>
                ) : (
                <IgrIconButton variant="flat" name="clear" collection="material" onClick={clearSearch}>
                </IgrIconButton>
            )}
        </div>
        <div slot="suffix">
            <IgrIconButton variant="flat" name="prev" collection="material" onClick={() => prevSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
                <IgrRipple></IgrRipple>
            </IgrIconButton>
            <IgrIconButton variant="flat" name="next" collection="material" onClick={() => nextSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
                <IgrRipple></IgrRipple>
            </IgrIconButton>
        </div>
    </IgrInput>
    

    Known Limitations

    Limitação Descrição
    Pesquisando em células com um modelo Os destaques da funcionalidade de pesquisa funcionam apenas para os modelos de célula padrão. Se você tiver uma coluna com modelo de célula personalizado, os destaques não funcionarão, então você deve usar abordagens alternativas, como um formatador de coluna, ou definir osearchable propriedade na coluna como falsa.
    Virtualização Remota A pesquisa não funcionará corretamente ao usar virtualização remota
    Células com texto cortado Quando o texto na célula é muito grande para caber e o texto que estamos procurando é cortado pelas reticências, ainda rolaremos até a célula e a incluiremos na contagem de correspondências, mas nada será destacado

    API References

    Neste artigo, implementamos nossa própria barra deIgrGrid busca, com algumas funcionalidades adicionais para navegar entre os resultados de busca. Também usamos alguns componentes adicionais Ignite UI for React como ícones, chips e entradas. A API de busca está listada abaixo.

    IgrGrid methods:

    IgrColumn properties:

    Componentes adicionais com APIs relativas que foram usadas:

    Additional Resources

    Nossa comunidade é ativa e sempre acolhedora para novas ideias.