Skip to main content

Command Palette

Search for a command to run...

Cómo limitar filas en una Interactive Grid

Updated
3 min read
Cómo limitar filas en una Interactive Grid
O
Soy desarrollador de software y cuento con una trayectoria cargada de aprendizajes, las ganas de aprender cosas nuevas y lograr buenos resultados me han llevado a superar las expectativas y a alcanzar los objetivos propuestos. Me encanta la tecnología y disfruto inmensamente descubriendo innovaciones y compartiendo mis hallazgos con la comunidad.

Introducción

Seguro te ha tocado algún requerimiento donde el usuario no debe ingresar más de N registros en un detalle (por ejemplo, un máximo de 5 registros, etc.). Aunque se puede validar en el backend con PL/SQL antes de procesar, la experiencia de usuario (UX) mejora drásticamente si lo frenamos directamente en el cliente.

Les comparto una forma limpia y reutilizable de lograrlo utilizando las APIs nativas de JavaScript de Oracle APEX, manipulando el Toolbar de la IG sin meter código de más.

1. La lógica centralizada (Function and Global Variable Declaration)

En lugar de repetir código en cada grilla, creamos una función global en la página. Esta lee el modelo, cuenta los registros activos usando getTotalRecords() y oculta o muestra las acciones del widget dinámicamente:

function limitarRegistrosIG(regionId, maxLimite) {
    var region = apex.region(regionId);
    var widget = region.widget();
    var model = widget.interactiveGrid("getViews", "grid").model;
    
    // Obtenemos las acciones nativas de la IG
    var actions = widget.interactiveGrid("getActions");

    // Conteo de registros en memoria
    var rowCount = model.getTotalRecords();

    // Controlar la visibilidad de los botones de agregar (Toolbar y Menú)
    if (rowCount >= maxLimite) {
        actions.hide("selection-add-row");
        actions.hide("row-add-row");
    } else {
        actions.show("selection-add-row");
        actions.show("row-add-row");
    }
}

2. La ejecución (Acción Dinámica)

Para que esto reaccione en tiempo real cada vez que el usuario interactúa, debemos crear una Dynamic Action con las siguientes configuraciones:

  • Evento: Row Initialization (en la región de la IG).

  • Acción: Execute JavaScript Code.

Y la llamada queda tan limpia como esto (pasando el límite desde un ítem de APEX de forma dinámica):

// Obtenemos el límite desde un Page Item y ejecutamos
var limite = apex.item("P10_MAX_REGISTROS").getValue();
limitarRegistrosIG("tu_static_id_ig", limite);

3. Configuración de la Grilla (Asegurando el control)

Como paso final, debemos aplicar una pequeña configuración a la grilla para evitar que otras funcionalidades nativas (como la duplicación de filas) se salten este control.

Colocaremos el siguiente código en los atributos de la Interactive Grid, específicamente en la propiedad Attributes -> Advanced -> Initialization JavaScript Function. Esto removerá las opciones de duplicar filas y el borrado masivo por selección para mantener la integridad del conteo:

function( options ) {
    options.initActions = function( actions ) {
        actions.remove("selection-delete");
        actions.remove("selection-duplicate");
        actions.remove("row-duplicate");
    };
    return options;
}

Acceso a la Demo

Limitar Cantidad de Registros en un IG

💡 ¿Por qué este enfoque?

  • UX Limpia: El botón "Add Row" desaparece por completo o puedes cambiar .hide() por .disable() en caso de que prefieras deshabilitarlo en lugar de ocultarlo cuando se alcanza el tope, evitando que el usuario intente clicks innecesarios.

  • Flexibilidad: Al pasar el límite por un parámetro basado en un ítem de APEX, se puede parametrizar el comportamiento desde la base de datos fácilmente.

  • Cero sobrecargas: Usamos los métodos del framework (getActions), manteniendo el código limpio y alineado con las buenas prácticas de la arquitectura de APEX.

¿Cómo suelen manejar este tipo de límites en sus proyectos?

¿Prefieren validaciones al vuelo en JS o directo en las validaciones nativas de APEX al hacer Submit?

¡Los leo! ¡No olvides seguirme en redes sociales para enterarte de nuevos posts!

¡Saludos!