Mostrar más de 100 mil registros en una galería con paginación

Para ejemplo crearemos un screen con la siguiente estructura:


Tendremos la lista de SharePoint llama inventarios con los siguientes campos:

  • Folio
  • Articulo 
  • Tipo
  • Serie
  • Proveedor
  • Orden_Compra

En OnVisible del screen agregamos lo siguiente:

UpdateContext({
    varPageSize: 50, // Cada página tendra 50 registros a visualizar
    varCurrentPage: 1, // Comenzara en el botón 1 de la paginación
   
    // Obtiene el ID más reciente creado en la lista de SharePoint
    varTotalRecords: First(Sort(inventarios, ID, SortOrder.Descending)).ID
});

// Calcula el no. de páginas a mostrar
UpdateContext({
    varTotalPages: RoundUp(varTotalRecords / varPageSize, 0)
});
// varTotalRecords / varPageSize: Divide el número total de registros existentes entre
//la cantidad máxima de elementos que caben en una sola página, por ejemplo:
Si el ID más reciente es 100,000 se realiza la operación (100,000 / 50) y muestra los no. de paginación.



En Gallery_registro  agregamos :
TemplateSize: 38
Item: With(
    {
        TextoBuscado: Trim(txtBusqueda.Text)
    },
    If(IsBlank(TextoBuscado),
       // Si esta vacio TextoBuscado crea las variables
        With(
            {
                // Calcula el número de folio inicial de la página actual
                MinID: ((varCurrentPage - 1) * varPageSize) + 1,
                // Calcula el número de folio final
                MaxID: varCurrentPage * varPageSize
            },
            // Filtra de inventarios los registros que esten entre MinID y MaxID
            Filter(
                inventarios,
                Folio >= MinID And Folio <= MaxID
            )
        ),

        // De lo contrario
        With(
            {
                // Crea la variable FirstRecords, filtra los datos tomando el contenido
//de txtBusqueda.Text en todos los campos de la lista de SharePoint.
                // Con FirstN(..., varCurrentPage * varPageSize) toma los registros que
//coincidan en un bloque del primer registro al final.
                FirstRecords: FirstN(
                    Filter(
                        inventarios,
                        StartsWith(Foliotext, Trim(txtBusqueda.Text)) ||
                        StartsWith(Articulo, Trim(txtBusqueda.Text)) ||
                        StartsWith(Tipo, Trim(txtBusqueda.Text)) ||
                        StartsWith(Serie, Trim(txtBusqueda.Text)) ||
                        StartsWith(Proveedor, Trim(txtBusqueda.Text))
                    ),
                    varCurrentPage * varPageSize
                )
            },
            // Recorte para quedarse solo con n cantidad de registros
            LastN(FirstRecords, varPageSize)
        )
    )
)

En Gallery_registros, agregamos Label para llamar los campos:

En el Button_ant, agregamos los cambios:


DisplayMode: If(varCurrentPage = 1, DisplayMode.Disabled, DisplayMode.Edit)
Icon: "ArrowLeft"
OnSelect: UpdateContext({varCurrentPage: Max(1, varCurrentPage - 1)})
Text: "Ant"

En el Button_sig agregamos los cambios:

DisplayMode: If(varCurrentPage = varTotalPages, DisplayMode.Disabled, DisplayMode.Edit)
Icon: "ArrowRight"
Layout: ButtonLayout.IconAfter
OnSelect: UpdateContext({varCurrentPage: Min(varTotalPages, varCurrentPage + 1)})
Text: "Sig"

Dentro de Gallery_paginacion, agregamos un Label para mostrar los botones de paginación.

Realizamos los siguientes cambios en el Label:
Align: Align.Center
Height: 32
OnSelect: If(
    ThisItem.LabelText <> "...",
    UpdateContext({varCurrentPage: ThisItem.PageVal})
)

En Gallery_paginacion, realizamos los siguientes cambios:


AlignInContainer: AlignInContainer.Stretch
FillPortions: 1
Height: Parent.Height
Item: //Genera un barra de paginación de 7 elementos, apareceran los 3 puntos cuando se llegue al máximo y mínimo valor
With(
    {
        TotalP: varTotalPages,
        CurrP: varCurrentPage
    },
    Table(
        // Elemento 1 (Inicio): Siempre muestra la primera página (1).
        { Index: 1, PageVal: 1, LabelText: "1" },
        {
            //Elemento 2 (Separador izquierdo): Si estás en las primeras páginas (CurrP <= 4),
//muestra el número 2. Si ya avanzaste, muestra puntos suspensivos (...).
            Index: 2,
            PageVal: If(CurrP <= 4, 2, 0),
            LabelText: If(CurrP <= 4, "2", "...")
        },
        //Elementos 3, 4 y 5 (Bloque central deslizante): Se ajustan dinámicamente para mostrar
//los números de página que rodean a la página actual (el centro exacto de la barra siempre
//es la página en la que estás).
        {
            Index: 3,
            PageVal: If(CurrP <= 4, 3, If(CurrP >= TotalP - 3, TotalP - 4, CurrP - 1)),
            LabelText: Text(If(CurrP <= 4, 3, If(CurrP >= TotalP - 3, TotalP - 4, CurrP - 1)))
        },
        {
            Index: 4,
            PageVal: If(CurrP <= 4, 4, If(CurrP >= TotalP - 3, TotalP - 3, CurrP)),
            LabelText: Text(If(CurrP <= 4, 4, If(CurrP >= TotalP - 3, TotalP - 3, CurrP)))
        },
        {
            Index: 5,
            PageVal: If(CurrP <= 4, 5, If(CurrP >= TotalP - 3, TotalP - 2, CurrP + 1)),
            LabelText: Text(If(CurrP <= 4, 5, If(CurrP >= TotalP - 3, TotalP - 2, CurrP + 1)))
        },
        {
            //Elemento 6 (Separador derecho): Si estás cerca del final (CurrP >= TotalP - 3),
//muestra la penúltima página (TotalP - 1). Si estás al inicio o en el medio,
//muestra puntos suspensivos (...).
            Index: 6,
            PageVal: If(CurrP >= TotalP - 3, TotalP - 1, 0),
            LabelText: If(CurrP >= TotalP - 3, Text(TotalP - 1), "...")
        },
        //Elemento 7 (Final): Siempre muestra la última página (TotalP).
        { Index: 7, PageVal: TotalP, LabelText: Text(TotalP) }
    )
)
LayoutMinHeight: 32
LayoutMinWidth: 300
TemplatePadding: 0
TemplateSize: 100

En txtBusqueda agregamos los siguientes cambios:

OnChange:  If(IsBlank(Trim(txtBusqueda.Text)),
   
    // Si se borra el texto, se limpia la colección y resetea a la vista normal por ID
    Clear(colInventariosFiltrados);
    UpdateContext({
        varCurrentPage: 1,
        varTotalRecords: First(Sort(inventarios, ID, SortOrder.Descending)).ID
    }),

    // Si se escribe un texto, filtra tomando los campos de la lista de SharePoint,
//como utilizamosm StartsWith la busqueda es exacta, no podemos hacer busqueda intermedia
    ClearCollect(
        colInventariosFiltrados,
        Filter(
            inventarios,
            StartsWith(Foliotext, Trim(txtBusqueda.Text)) ||
            StartsWith(Articulo, Trim(txtBusqueda.Text)) ||
            StartsWith(Tipo, Trim(txtBusqueda.Text)) ||
            StartsWith(Serie, Trim(txtBusqueda.Text)) ||
            StartsWith(Proveedor, Trim(txtBusqueda.Text))
        )
    );
    UpdateContext({
        varCurrentPage: 1,
        varTotalRecords: CountRows(colInventariosFiltrados)
    })
);

// Se actualiza los botones de la barra de paginación dependiendo la busqueda
UpdateContext({
    varTotalPages: Max(1, RoundUp(varTotalRecords / varPageSize, 0))
});

Ejecutamos la app.

Para el ejemplo tengo 3,323 registros (3323/50) = 64.46 pero como hacer un RoundUP = 65
RoundUp(varTotalRecords / varPageSize, 0)

Con esto podemos mostrar grandes cantidades de registro sin que perdamos información, ya que la paginación solo mostrara 50 registros.



Publicar un comentario

Artículo Anterior Artículo Siguiente