skip to Main Content

I have a table that divides the its items per 20 lines and, above the table, a searching input to filter items that matches the written words. Both the tools works ok alone. I can navigate through the pages when there are more than 20 items and i can find the items when i type it in the inut.

The problem is: everytime i have more than one page i try to search something, the item appears in the first page and if i am in the second page i can see nothing unless i go back to the first page.

I think that the correct thing to do is to decrease the number of pages to matche the quantity of items that i found, but i don’t know how to do it.

You can take a look in the page and the code below:
In that case, the table should get only one page

The code:

    const [currentPage, setcurrentPage] = useState(1);
    const itemsPerPage = 15;

    // Calculo dos índices para exibir os itens da página atual
    const indexOfLastItem = currentPage * itemsPerPage;
    const indexOfFirstItem = indexOfLastItem - itemsPerPage;
    // const currentItems = produtos.slice(indexOfFirstItem, indexOfLastItem);

    const totalPages = Math.ceil(produtos.length / itemsPerPage);

    const changePage = (newPage) => {
        if(showDetalhes === true){
        setShowDetalhes(false);
        }
        setcurrentPage(newPage);
    };
    

    //jsx return
    <table className="table" id='table-estoque'>
                    <thead>
                        <tr>
                            <th scope="col" id="titulo-tabela-padrao">Categoria</th>
                            <th scope="col" id="titulo-tabela-padrao">Código</th>
                            <th scope="col" id="titulo-tabela-padrao" style={{ width: '40%' }}>Produto</th>
                            <th scope="col" id="titulo-tabela-padrao">Preço</th>
                            <th scope="col" id="titulo-tabela-padrao">Preço Promocional</th>
                            <th scope="col" id="titulo-tabela-padrao" style={{width:'2%', color:'#FFEA00'}}><i className="fa-solid fa-pen fa-sm"></i></th>
                            <th scope="col" id="titulo-tabela-padrao" style={{width:'2%', color:'#eb2632'}}><i className="fa-solid fa-trash fa-sm"></i></th>
                        </tr>
                    </thead>
                    <tbody>

                        {produtos
                            .filter((item) => {
                                // return search.toLowerCase() === '' || item.pro_descricao.toLowerCase().includes(search.toLowerCase()); //se digitar algo aparece na lista
                                const searchWords = search.toLowerCase().split(' '); //atribui à searchWirds tudo que foi digitado dividido por space                        
                                return searchWords.every((word) => //faz a busca para cada palavra digitada mesmo que fora de sequencia
                                item.pro_descricao.toLowerCase().includes(word)
                                ); 
                            })
                            .slice(indexOfFirstItem, indexOfLastItem) //Mudei a logica para paginacao para antes do map e nao la em cima como antes 
                            .map((produto, index) => (
                                <React.Fragment key={index}>
                                <tr>
                                    <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{produto.cat_descricao}</td>
                                    <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{produto.pro_codigo}</td>
                                    <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{produto.pro_descricao}</td>
                                    <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{new Intl.NumberFormat('pt-BR', {minimumFractionDigits: 2,maximumFractionDigits: 2}).format(produto.pro_preco1)}</td>
                                    {produto.pro_preco_promocao > 0 ? <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{new Intl.NumberFormat('pt-BR', {minimumFractionDigits: 2,maximumFractionDigits: 2}).format(produto.pro_preco_promocao)}</td>
                                    :
                                    <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">--</td>                                      
                                    }
                                    <td  className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao"><div id="a-editar" onClick={(e) => OpenModalProduto(produto.pro_id)} ><i className="fa-solid fa-pen fa-sm"></i></div></td>
                                    <td  className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao"><div id="a-excluir" onClick={(e) => confirmarExclusao(produto.pro_id)}><i className="fa-solid fa-trash fa-sm"></i></div></td>
                                </tr>
                                {showDetalhes && detalhesIndex === index && (
                                <tr>
                                    <td  className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} colSpan="12" style={{ borderBottom: '1px solid #000' }}>
                                    <div style={{ padding: '15px' }}>
                                        {
                                            jsonOpcionais?.map(item => {
                                                return <div className='row' key={item.poi_id}>
                                                        <div className='col-1 ms-auto me-3'>
                                                        {item.status === 'N' ? <span id='status-itens-op' className='badge bg-secondary ms-2'>Inativo</span> : <span id='status-itens-op' className='badge bg-success ms-2'>Ativo</span>}
                                                        </div>
                                                        <div className='col-4'>
                                                        <span>{item.poi_descricao}</span>
                                                        </div>
                                                        <div className='col-1 me-auto'>
                                                        {item.poi_valor === 0 ? <span id='span-zero'>{new Intl.NumberFormat('pt-BR', {style: 'currency', currency:'BRL'}).format(item.poi_valor)} </span> : <span id='span-maior-zero' key={index}>{new Intl.NumberFormat('pt-BR', {style: 'currency', currency:'BRL'}).format(item.poi_valor)} </span>}
                                                        </div>
                                                    </div>
                                            })
                                        }
                                    </div>
                                    </td>
                                </tr>
                                )}
                            </React.Fragment>
                            ))}
                    </tbody>
                </table>
                {totalPages > 1 && (
                    <div className="pagination">
                        <button className="btn btn-secondary btn-sm ms-auto" onClick={() => changePage(currentPage - 1)} disabled={currentPage === 1}> Anterior</button>
                            <span className="span-pagina ms-1 me-1 ">Página {currentPage} / {totalPages}</span>
                        <button className="btn btn-secondary btn-sm" onClick={() => changePage(currentPage + 1)} disabled={currentPage === totalPages}>Próxima</button>
                    </div>
                )}

2

Answers


  1. Chosen as BEST ANSWER

    i found a way:

    function Produtos() {

    // Calculo dos índices para exibir os itens da página atual
    const indexOfLastItem = currentPage * itemsPerPage;
    const indexOfFirstItem = indexOfLastItem - itemsPerPage;
    // const currentItems = produtos.slice(indexOfFirstItem, indexOfLastItem);
    
    let totalPages = Math.ceil(produtos.length / itemsPerPage);
    
    const changePage = (newPage) => {
        if(showDetalhes === true){
        setShowDetalhes(false);
        }
        setcurrentPage(newPage);
    };
    
    useEffect(() => {
        setcurrentPage(1);
    },[search]);
    
    
    return <>
    <Navbar tela='cardapio'/> 
            
    <ProdutoModal isOpen={isProdutoOpen}
                  onRequestClose={CloseModalProduto}
                  categorias={categorias}
                  dadosProduto={dadosProduto}
                  onClickSalvar={ListarCardapio}
    />
    
    <ProdutoOpcionalModal isOpen={isOpcionalOpen}
                          onRequestClose={CloseModalOpcional}
                          id_pro={id_pro}
                          pro_descricao={pro_descricao}
    />
    <LoadingScreen isLoading={isLoading} />
    
    <div className='container-fluid corpo-pagina'>
    
        <div className="d-flex table-buttons mt-4">
            <button id='style-outline-button' onClick={() => OpenModalProduto(0)} className='btn ms-2' >
                <i className='fas fa-plus'></i>Adicionar Produto
            </button>
            <button onClick={exportToExcel} className="button-exportar">Exportar</button>
    
            <div className="box-input">
                <i className="fa fa-search fa-sm" aria-hidden="true"></i>
                <input onChange={(e) => setSearch(e.target.value)} type="text" placeholder="Localizar" id="input-localizar-intern"/>
            </div>
        </div>
    
        <div className='m-2 mt-4'>
            {(() => {
                const filteredProdutos = produtos.filter((item) => {
                    const searchWords = search.toLowerCase().split(' ');
                    return searchWords.every((word) => item.pro_descricao.toLowerCase().includes(word));
                });
    
                totalPages = Math.ceil(filteredProdutos.length / 15);
    
                return (
                    <>
                        <table className="table" id='table-estoque'>
                            <thead>
                                <tr>
                                    <th scope="col" id="titulo-tabela-padrao">Categoria</th>
                                    <th scope="col" id="titulo-tabela-padrao">Código</th>
                                    <th scope="col" id="titulo-tabela-padrao" style={{ width: '40%' }}>Produto</th>
                                    <th scope="col" id="titulo-tabela-padrao">Preço</th>
                                    <th scope="col" id="titulo-tabela-padrao">Preço Promocional</th>
                                    <th scope="col" id="titulo-tabela-padrao" style={{width:'2%', color:'#FFEA00'}}>
                                        <i className="fa-solid fa-pen fa-sm"></i>
                                    </th>
                                    <th scope="col" id="titulo-tabela-padrao" style={{width:'2%', color:'#eb2632'}}>
                                        <i className="fa-solid fa-trash fa-sm"></i>
                                    </th>
                                </tr>
                            </thead>
                            <tbody>
                                {filteredProdutos
                                    .slice(indexOfFirstItem, indexOfLastItem)
                                    .map((produto, index) => (
                                        <React.Fragment key={index}>
                                            <tr>
                                                <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{produto.cat_descricao}</td>
                                                <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{produto.pro_codigo}</td>
                                                <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{produto.pro_descricao}</td>
                                                <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{new Intl.NumberFormat('pt-BR', {minimumFractionDigits: 2,maximumFractionDigits: 2}).format(produto.pro_preco1)}</td>
                                                {produto.pro_preco_promocao > 0 ? <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">{new Intl.NumberFormat('pt-BR', {minimumFractionDigits: 2,maximumFractionDigits: 2}).format(produto.pro_preco_promocao)}</td>
                                                :
                                                <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">--</td>                                      
                                                }
                                                <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">
                                                    <div id="a-editar" onClick={() => OpenModalProduto(produto.pro_id)} >
                                                        <i className="fa-solid fa-pen fa-sm"></i>
                                                    </div>
                                                </td>
                                                <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} id="item-tabela-padrao">
                                                    <div id="a-excluir" onClick={() => confirmarExclusao(produto.pro_id)}>
                                                        <i className="fa-solid fa-trash fa-sm"></i>
                                                    </div>
                                                </td>
                                            </tr>
                                            {showDetalhes && detalhesIndex === index && (
                                            <tr>
                                                <td className={index % 2 === 0 ? 'td-item-par' : 'td-item-impar'} colSpan="12" style={{ borderBottom: '1px solid #000' }}>
                                                    <div style={{ padding: '15px' }}>
                                                        {jsonOpcionais?.map(item => (
                                                            <div className='row' key={item.poi_id}>
                                                                <div className='col-1 ms-auto me-3'>
                                                                    {item.status === 'N' ? <span id='status-itens-op' className='badge bg-secondary ms-2'>Inativo</span> : <span id='status-itens-op' className='badge bg-success ms-2'>Ativo</span>}
                                                                </div>
                                                                <div className='col-4'>
                                                                    <span>{item.poi_descricao}</span>
                                                                </div>
                                                                <div className='col-1 me-auto'>
                                                                    {item.poi_valor === 0 ? <span id='span-zero'>{new Intl.NumberFormat('pt-BR', {style: 'currency', currency:'BRL'}).format(item.poi_valor)} </span> : <span id='span-maior-zero' key={index}>{new Intl.NumberFormat('pt-BR', {style: 'currency', currency:'BRL'}).format(item.poi_valor)} </span>}
                                                                </div>
                                                            </div>
                                                        ))}
                                                    </div>
                                                </td>
                                            </tr>
                                            )}
                                        </React.Fragment>
                                    ))}
                            </tbody>
                        </table>
                        {totalPages > 1 && (
                            <div className="pagination">
                                <button className="btn btn-secondary btn-sm ms-auto" onClick={() => changePage(currentPage - 1)} disabled={currentPage === 1}> Anterior</button>
                                <span className="span-pagina ms-1 me-1 ">Página {currentPage} / {totalPages}</span>
                                <button className="btn btn-secondary btn-sm" onClick={() => changePage(currentPage + 1)} disabled={currentPage === totalPages}>Próxima</button>
                            </div>
                        )}
                    </>
                );
            })()}
        </div>
    </div>
    

    Set current page as 1 everytime i type in search input and totalPages = Math.ceil(filteredProdutos.length / 15); after filtering


  2. //replace this

    const totalPages = Math.ceil(produtos.length / itemsPerPage); 
    

    //new code

     const totalPages = Math.ceil(
        produtos.filter((item) => {
          // return search.toLowerCase() === '' || item.pro_descricao.toLowerCase().includes(search.toLowerCase()); //se digitar algo aparece na lista
          const searchWords = search.toLowerCase().split(" "); //atribui à searchWirds tudo que foi digitado dividido por space
          return searchWords.every(
            (
              word //faz a busca para cada palavra digitada mesmo que fora de sequencia
            ) => item.pro_descricao.toLowerCase().includes(word)
          );
        }).length / itemsPerPage
      );
    

    secondly try to keep this in parent and pass it as props to table component

    const [currentPage, setcurrentPage] = useState(1);
        const itemsPerPage = 15;
    
        // Calculo dos índices para exibir os itens da página atual
        const indexOfLastItem = currentPage * itemsPerPage;
        const indexOfFirstItem = indexOfLastItem - itemsPerPage;
        // const currentItems = produtos.slice(indexOfFirstItem, indexOfLastItem);
    
        const totalPages = Math.ceil(produtos.length / itemsPerPage);
    

    and i assume the onChange function of search field is something like this

    const handleChange=(e)=>{
       setSearch(e.target.value);
       //add this line below
       setcurrentPage(1)   
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search