Colecciones

Las Colecciones son clases que extienden ReactiveModel y representan grupos reactivos de items. Permiten cargar, filtrar, ordenar y gestionar múltiples instancias de un Item definido, asegurando sincronización con un registro compartido y soporte para actualizaciones dinámicas desde fuentes de datos externas.

🎯 ¿Qué es una Colección?

Una Collection es una clase reactiva que:

  • Gestiona múltiples instancias de un tipo de Item

  • Carga datos desde proveedores externos

  • Filtra y ordena items según criterios específicos

  • Soporta paginación automática

  • Se sincroniza automáticamente con cambios en el registro

  • Agrega nuevos items automáticamente si coinciden con los filtros

🧩 Herencia

Collection<T, P> extends ReactiveModel<Collection<T, P>>
  • T: Clase del item que extiende Item<any>

  • P: Clase del proveedor que implementa ICollectionProvider

📦 Constructor

Parámetros

  • entity: (requerido) Identificador del tipo de colección (ej: 'users')

  • provider: (opcional) Clase que implementa ICollectionProvider

  • item: (requerido) La clase Item a instanciar al cargar datos

  • defaultLimit: (opcional) Número máximo de items a cargar por defecto (por defecto: 15)

  • nextParamName: (opcional) Nombre del parámetro de paginación enviado al proveedor (por defecto: "next")

🔑 Propiedades Principales

Propiedad
Tipo
Descripción

entity

string

Nombre de la entidad

provider

P

Instancia del proveedor de datos

Item

class

Clase del item usado en la colección

items

T[]

Array de items en la colección

map

Map<ItemId, T>

Mapa interno de items indexados por ID

isCollection

boolean

Siempre true (identificador de tipo)

total

number

Total de items disponibles (si lo proporciona el proveedor)

next

unknown | null

Valor del cursor de paginación (si existe)

⚙️ Métodos Principales

load(args?): Promise<T[]>

Carga items desde el proveedor configurado. Si se omite limit, se usa el defaultLimit de la colección.

La paginación se maneja internamente: si la colección tiene un cursor de paginación ("next"), se agregará automáticamente a la solicitud usando el nombre de parámetro definido por nextParamName.

Ejemplo básico:

Con filtros:

Con paginación:

Especificación completa:

Parámetros (ILoadSpecs<T>):

  • where: Objeto con filtros a aplicar

  • orderBy: Objeto con criterios de ordenamiento

  • limit: Número máximo de items a cargar

  • update: Si es true, agrega items sin reemplazar los existentes

Retorna:

  • Promise<T[]>: Array de items cargados

Errores:

  • Lanza un error si el proveedor no está definido o no implementa list()

  • Lanza un error si list() no retorna un array o un objeto con items

Operadores de Filtro

La colección soporta varios operadores para filtrar datos:

Operador
Descripción
Ejemplo

equals

Coincidencia exacta

{ name: { equals: 'Juan' } }

not

Diferente del valor

{ age: { not: 18 } }

in

El valor está en el array

{ status: { in: ['active', 'pending'] } }

notIn

El valor no está en el array

{ role: { notIn: ['admin'] } }

contains

Contiene la subcadena (solo strings)

{ name: { contains: 'Juan' } }

startsWith

Comienza con (solo strings)

{ email: { startsWith: 'juan' } }

endsWith

Termina con (solo strings)

{ email: { endsWith: '.com' } }

gt

Mayor que

{ age: { gt: 18 } }

gte

Mayor o igual que

{ age: { gte: 18 } }

lt

Menor que

{ age: { lt: 65 } }

lte

Menor o igual que

{ age: { lte: 65 } }

Ejemplo con múltiples filtros:

Operadores Lógicos (AND/OR)

Puedes combinar condiciones usando operadores lógicos:

AND (todas las condiciones deben cumplirse):

OR (al menos una condición debe cumplirse):

Combinando AND y OR:

Ordenamiento

Usa orderBy para ordenar los resultados:

getTotal(): number

Retorna el número total de items disponibles (si fue proporcionado por el proveedor).

getNext(): unknown | null

Retorna el valor del cursor de paginación (si existe).

addItems(data: T[]): void

Agrega items manualmente a la colección sin cargar desde el proveedor.

delete(ids: ItemId | ItemId[]): Promise<boolean[]>

Elimina uno o múltiples items de la colección.

🔄 Eventos

Las colecciones emiten varios eventos:

Evento
Se dispara cuando

load

Después de cargar items exitosamente

change

Cuando la colección cambia

items.changed

Cuando se agregan, modifican o eliminan items

Ejemplo de uso de eventos:

🛠 Proveedor (Provider)

Para habilitar la carga de datos, debes pasar una clase que implemente ICollectionProvider:

Ejemplo de Proveedor de Colección

Formato de respuesta del proveedor:

El método list() puede retornar:

  • Un array directamente: Promise<any[]>

  • Un objeto con estructura: Promise<{ items: any[], total?: number, next?: any }>

📝 Ejemplo Completo

🔍 Características Avanzadas

Sincronización Automática con el Registro

Las colecciones se sincronizan automáticamente con el sistema de registro. Cuando un item se publica o elimina en otra parte de la aplicación:

  1. Si el item coincide con los filtros de la colección, se agrega automáticamente

  2. Si un item se elimina, se remueve automáticamente de la colección

  3. Los cambios en items existentes se reflejan automáticamente

Paginación Automática

La colección maneja la paginación automáticamente:

  • Si el proveedor retorna un cursor next, se almacena internamente

  • En la próxima llamada a load(), se envía automáticamente el cursor

  • No necesitas manejar manualmente el parámetro de paginación

Filtros Persistentes

Los filtros se almacenan internamente y se usan para validar nuevos items del registro. Si un nuevo item coincide con los filtros, se agrega automáticamente a la colección.

🔗 Propiedades Anidadas

Las Collections pueden ser usadas como propiedades anidadas en Items u otros ReactiveModels. Esto permite modelar relaciones complejas donde un Item tiene una Collection de items relacionados.

Ejemplo rápido:

Para más información sobre cómo implementar propiedades anidadas con Collections, consulta la documentación completa de Propiedades Anidadas.

🎓 Mejores Prácticas

  1. Define un límite por defecto razonable: Usa defaultLimit para evitar cargar demasiados items de una vez

  2. Usa update: true para paginación: Cuando cargas más páginas, usa update: true para agregar items sin reemplazar los existentes

  3. Maneja errores: Siempre envuelve las llamadas a load() en try/catch

  4. Optimiza filtros: Los filtros se evalúan en el proveedor, pero también localmente para nuevos items del registro

  5. Reutiliza colecciones: Crea instancias de colecciones y reutilízalas en lugar de crear nuevas constantemente

⚠️ Errores Comunes

Error: "DataProvider is not defined or does not implement the list() method"

Error: "DataProvider.list() must return an array or an object with an 'items' array"

No se cargan más páginas

Last updated