1.3.1 • Published 17 hours ago

@clavisco/table v1.3.1

Weekly downloads
-
License
-
Repository
-
Last release
17 hours ago

Acerca de @clavisco/table

Token: Table

Permite mostrar una tabla dinámica de material, con campos de tipo texto, seleccionables y desplegables, ademas, cuenta con paginadores automáticos o manuales segun las necesidades de implementación.

¿Qué resuelve?

Estandariza el formato y arquitectura de las tablas de datos, al mismo tiempo que, reduce considerablemente el tiempo de implementación.

Dependencias

Resumen de version

Caracteristicas (Features)

  • Soporte para paginación de consultas a base de datos de aplicación.

Correcciones (Fixes)

  • Ahora la tabla en vista móvil se visualiza de forma vertical.

Table

Está compuesta por un módulo y su respectivo componente visual cl-table a continuacion se detalla sus diferentes atributos:

  • Id: string(Requerido): Este identificador debe ser único para evitar cruce de registros cuando se use en el componente en una misma vista n cantidad de veces
  • HasStandardHeaders: boolean(Opcional): Indica que las columnas de la tabla van a tener el formato "Nombre de columna" Por defecto se inicializa en falso
  • ShouldSplitPascal: boolean(Opcional): Indica que el componente usará como nombre en las cabeceras las variables de algun modelo de datos que se envia en la lista. Por defecto se inicializa en verdadero
  • MappedColumns: MappedColumns(Requerido): objeto generado mediante la función MapDisplayColumns(...) que permite mapear las columnas renombradas e ignoradas de la tabla o definirlas como columnas de icono, ademas de configurar la condición que se usara para marcar las columnas automaticamente con la propieda "ItemsToMarkAsChecked"
  this.mappedColumns = MapDisplayColumns(
    { 
      dataSource: FULL_RECORDS_LIST,
      renameColumns: { email: 'Correo electrónico', other: 'Otros' },  
      ignoreColumns: ['id', 'name'],
    }
  );

Donde dataSource corresponde a todos los elementos o un segmento de estos, renameColumns se define mediante un clave/valor (object literal) de las columnas a renombrar y además representa el orden de las columnas, asi como sus valores en caso de no existir datos disponibles, ignoreColumns es una lista de las columnas a ignorar

  • Records: Object[] (Requerido): Es la lista de objetos que se desea mostrar en la tabla, debe enviarse al menos una lista vacía en caso de que no se encuentren registros En caso de no suministar ningún nombre el componente le asignará uno por defecto un arrary vacío
  • RecordsCount: number (Requerido): Total de registros que devuelve la consulta, este valor es usado para dar la funcionalidad de paginación.
  • PageSizeOptions: number[] (Opcional): Es el rango de la cantidad de items por página que se pueden seleccionar Por defecto tiene el valor de 5, 10, 20
  • ItemsPeerPage: number (Opcional): Cantidad de registros a mostrar por página. Es importante tomar en cuenta que este valor debe estar contenido en el arrary de PageSizeOptions para mantener consitencia en entre los registros Por defecto tiene el valor de 10 items por página
  • Buttons: ICLTableButton[] (Opcional): permite ejecutar opciones sobre cada registro de la tabla
  • HasItemsSelection: boolean (Opcional): permite agrega una columna de seleccion de fila. Por defecto se inicializa en falso
  • ShouldEmitRows: boolean (Opcional): habilita la emision de las lineas seleccionadas en cada seleccion. Por defecto se inicializa en falso
  • HasPaginator: boolean (Opcional): habilita o no el paginador Por defecto se inicializa en verdadero
  • ScrollHeight: string (Opcional): indica la altura que ocupan los demas componentes en la vista donde se despliega la tabla, con este valor se realiza el siguiente cálculo para determinar la altura de la tabla dentro de la que se activa el scroll: calc(100vh - ScrollHeight). Por defecto se asigna el valor "auto", puede utilizar cualquier tamaño o valor asociado a la propiedad "max-heignt" con CSS (px, %, em, vh).
  • CheckboxColumns: string[] (Opcional): lista de columnas que seran de tipo checkbox, los valores en el data source deben ser booleanos
  • DropdownColumns: string[] (Opcional): lista de columnas que seran de tipo dropdown, los valores en el data source deben corresponder con lo indicados en DropdownList o DropdownDiffList en caso de ser diferentes para cada fila
  • DropdownMultiColumns: string[] (Opcional): lista de columnas que seran de tipo dropdown opcion multiple, los valores en el data source deben corresponder con un arreglo de los valores indicados en DropdownList o DropdownDiffList en caso de ser diferentes para cada fila
  • DropdownList: DropdownList (Opcional): objeto con las columnas y los valores para cada dropdown segun columna
  • DropdownDiffList: DropdownList (Opcional): objeto con las columnas y los valores para cada dropdown segun columna y segun la fila definida mediante el parametro by del elemento
  • DropdownDiffBy: string (Opcional): llave utilizada para buscar el punto de anclaje by en las filas del data source
  • ShouldPaginateRequest: boolean (Opcional): Indica si se deben setear los valores de paginación, su valor por defecto es verdadero
  • ItemsSelectionType: radio | checkbox (Opcional): Indica que tipo de boton se mostrara al activar el HasItemsSelection. Por defecto es checkbox
  • PageSizeEditable: boolean (Opcional): Indica si el tamaño de la página es editable. El valor por defecto es false
  • PagintaionType: dba | sl (Opcional): Representa el tipo de paginación que se va a aplicar si ShouldPaginateRequest esta activo, el valor por defecto es sl.

¿Cómo se usa?

  1. Primero debemos cumplir las depencias mencionadas al inicio de este documento
  2. Ejecutar el comando npm i @clavisco/table en el directorio root del proyecto
  3. Importar el módulo TableModule en el app.module.ts o en el módulo donde desea utilizar la tabla.
  4. Inyectar el servicio de Linker en el controlador para realizar la comunicación con el componente constructor(@Inject('LinkerService') private linkerervice: LinkerService)
  5. Ejemplo de implementacion del componente en el template html
<cl-table 
 [Id]="tableId"
 [HasStandardHeaders]="isStandarHeaders"
 [ShouldSplitPascal]="shouldSplitPascal"
 [MappedColumns]="mappedColumns"
 [CheckboxColumns]="checkboxColumns"
 [DropdownMultiColumns]="dropdownMultiColumns"
 [DropdownDiffList]="dropdownDiffList"
 [DropdownDiffBy]="dropdownDiffBy"
 [Records]="dataSource"
 [PageSizeOptions]="pageSizeOptions"
 [ItemsPeerPage]="itemsPeerPage"
 [RecordsCount]="recordsCount"
 [HasItemsSelection]="hasItemSelection"
 [ShouldEmitRows]="emitRows"
 [HasPaginator]="hasPaginator"
 ScrollHeight="150px"
 [Buttons]="buttons"
 [ItemsToMarkAsChecked]="ItemsToMarkAsChecked">
</cl-table>
  1. Para el seteo de los datos de las columnas al inicia el componente debe utilizar la función MapDisplayColumns(...) de la siguiente forma:
 this.mappedColumns = MapDisplayColumns(
   { 
     dataSource: FULL_RECORDS_LIST,
     renameColumns: { email: 'Correo electrónico', other: 'Otros' },  
     ignoreColumns: ['id', 'name'],
   }
 );
  1. Para setear o actualizar los datos de forma dinámica, puede publicar un evento de Linker de la siguiente manera:
const NEXT_TABLE_STATE = {
  CurrentPage: this.currentPage,
  ItemsPeerPage: this.itemsPeerPage,
  Records: FULL_OR_SLICE_SOURCE_LIST,
  RecordsCount: this.fullSourceRecordsCount,
  ItemsToMarkAsChecked: this.ItemsToMarkAsChecked
}

this.linkerService.Publish({
  CallBack: CL_CHANNEL.INFLATE,
  Target: this.tableId,
  Data: JSON.stringify(NEXT_TABLE_STATE)
} as ICLEvent);
  1. Para actualizar los registros de la tabla al moverse entre páginas, puede registrar un evento de tipo INPUT asignando la siguiente función
ngOnInit(): void {
  Register<CL_CHANNEL>(this.tableId, CL_CHANNEL.INPUT, this.UpdateElementsRecordsOnNext, this.callbacks);
}
UpdateElementsRecordsOnNext = (_event: ICLEvent): void => {
   if (_event) {
     const INCOMMING_TABLE_STATE = JSON.parse(_event.Data);
     const CURRENT_TABLE_STATE = {
       CurrentPage: INCOMMING_TABLE_STATE.CurrentPage,
       ItemsPeerPage: INCOMMING_TABLE_STATE.ItemsPeerPage,
       Records: ELEMENT_DATA.slice(INCOMMING_TABLE_STATE.SLStart, INCOMMING_TABLE_STATE.SLEnd),
       RecordsCount: ELEMENT_DATA.length,
       ItemsToMarkAsChecked: this.ItemsToMarkAsChecked
     } as ICLTableState<any>;

     this.linkerService.Publish({
       CallBack: CL_CHANNEL.INFLATE,
       Target: this.tableId,
       Data: JSON.stringify(CURRENT_TABLE_STATE)
     } as ICLEvent);
   }
 }
  1. Para definir los eventos resultantes para los botones de la tabla registrar un evento de tipo OUTPUT asignando la siguiente función
ngOnInit(): void {
  Register<CL_CHANNEL>(this.tableId, CL_CHANNEL.OUTPUT, this.ButtonsEvent, this.callbacks);
}

ButtonsEvent = (_event: ICLEvent): void => {
  if (_event.Data) {
    const BUTTON_EVENT = JSON.parse(_event.Data);
    const ELEMENT = JSON.parse(BUTTON_EVENT.Data);

    switch (BUTTON_EVENT.Action) {
      case Structures.Enums.CL_ACTIONS.UPDATE:
          this.UpdateRecord(ELEMENT);
        break;
      case Structures.Enums.CL_ACTIONS.DELETE:
        this.DeleteRecord(ELEMENT);
        break;
    }
  }
}
  1. Para obtener todos los elementos de la tabla puede publicar un evento de tipo DATA_LINE_4 y registrar uno tipo OUTPUT_2 asignando las siguientes funciones
 RequestAllRecords = (): void => {
   try {
     const EVENT = {
       CallBack: CL_CHANNEL.DATA_LINE_4,
       Target: this.tableId,
     } as ICLEvent;

     this.linkerService.Publish(EVENT);
   } catch (error) {
     console.log(GetError(error));
   }
 }

 GetAllRecords = (_event: ICLEvent): void => {
   try {
     const ALL_RECORDS = JSON.parse(_event.Data);
     this.ProcessRecords(ALL_RECORDS);
   }
   catch (error) {
     console.log(GetError(error));
   }
 }
  1. Para obtener los elemento seleccionados de la tabla puede publicar un evento de tipo DATA_LINE_2 y registrar uno tipo DATA_LINE_1 asignando las siguientes funciones:
 RequestSelectedItems = (): void => {
   try {
     const EVENT = {
       CallBack: CL_CHANNEL.DATA_LINE_2,
       Target: this.tableId,
     } as ICLEvent;

     this.linkerService.Publish(EVENT);
   } catch (error) {
   }
 }

 GetSelectedRecords = (_event: ICLEvent): void => {
   try {
     const SELECTED_RECORDS = JSON.parse(_event.Data);
     this.ProcessSelectedRecords(SELECTED_RECORDS);
   }
   catch (error) {
     console.log(GetError(error));
   }
  }
  • Nota: Para utilizar esta opcion es necesario tener activa la selección mediante el atributo HasItemsSelection
  1. Ya con esto tenemos una implementación básica del componente tabla
  2. Video explicativo sobre el uso de @clavisco/table

Agregar columnas de icono

Para agregar columnas que tengan iconos se debe hacer lo siguiente:

Donde se realice el mapeado de las columnas de la tabla agregar la propiedad iconColumns con la columnas que seran iconos

this.mappedColumns = MapDisplayColumns(
  {
    //...more propierties
    iconColumns: ['ActiveIcon']
  }
);

Las propiedades del modelo indicadas en iconColumns deben ser de tipo IconColumn que seria una interfaz proporcionada por @clavisco/table.

let activeIcon = {
  icon: 'done',
  color: '#58D68D',
  iconText: 'Lista'
} as IconColumn;

let notActiveIcon = {
  icon: 'close',
  color: '#EC7063',
  iconText: 'No lista'
} as IconColumn;

this.records = this.records.map(x => ({...x,
    ActiveIcon: this.completedTodos.some(t => t.id === x.id) ? activeIcon : notActiveIcon,
  })
);

const NEW_TABLE_STATE = {
  Records: this.records,
  RecordsCount: this.records.length,
};

this.linkerService.Publish({
  Data: JSON.stringify(NEW_TABLE_STATE),
  Target: this.tableId,
  CallBack: CL_CHANNEL.INFLATE
});

En este ejemplo se realiza un mapeo de los registros para establecerle un valor a la propiedad ActiveIcon dependiendo de si el registro esta en una lista.


Paginación de consultas

Tipos de paginación

Hay dos tipos de paginación: la paginación de consultas a base de datos de aplicación y la paginación de consultas a bases de datos de SAP mediante Service Layer. Para indicarle a la tabla qué tipo de paginación va a realizar, hay que establecer un valor a la propiedad PaginationType, la cual permite los valores dba y sl.

Establecer valores para headers de paginación en primera consulta

Emita un evento con linker mediante el canal PRE_REQ_RECORDS de la siguiente manera:

this.linkerService.Publish({
  CallBack: CL_CHANNEL.PRE_REQ_RECORDS,
  Target: this.tableId,
  Data: ''
});

Al hacer eso los datos de paginación se estableceran y asi el interceptor podra tomarlos y enviarlos en los headers.

Una vez echo eso, se emitirá un evento mediante el canal REQUEST_RECORDS que lo podremos escuchar de la siguiente manera:

ngOnInit(): void {
    Register<CL_CHANNEL>(this.tableId, CL_CHANNEL.REQUEST_RECORDS, this.GetRecords, this.callbacks);
    //...linker configuration
}

//...more code

GetRecords = ()=>
{
  this.overlayService.OnGet();
  this.myService.GetRecords().pipe(
    finalize(() => this.overlayService.Drop())
  )
    .subscribe(
      {
        next: (callback) => {
          this.myRecords = callback.Data;

          const NEW_TABLE_STATE = {
            Records: this.myRecords
          };
          this.linkerService.Publish({
            CallBack: CL_CHANNEL.INFLATE,
            Target: this.tableId,
            Data: JSON.stringify(NEW_TABLE_STATE)
          });
        },
        error: (err) => {
          this.alertsService.ShowAlert({HttpErrorResponse: err});
        }
      }
    );
}

Ahora al navegar entre las paginas de la tabla se ejecutar el evento REQUEST_RECORDS y realizara la consulta de manera automatica.

Para más información sobre esta funcionalidad consulte @clavisco/core

Nota!!! Si se require paginar los registros desde el UI, se tiene que enviar el valor de la propiedad "ShouldPaginateRequest" en "false".



Drag and Drop

Habilitar funcionalidad

Para habilitar esta funcionalidad se tiene que enviar en "false" el valor de la propiedad "DisableDragAndDrop":

<cl-table
  <!--...more attributes-->
  [DisableDragAndDrop]="false">
</cl-table>

Escuchar cambios de Drag and drop

Se tiene que registrar el canal "OUTPUT_3" (Se da por hecho que ya se tiene @clavisco/linker implementado):

ngOnInit(): void
{
  Register<CL_CHANNEL>(this.pagedTableId, CL_CHANNEL.OUTPUT_3, this.OnRowEventEmitted, this.callbacks);
}

OnRowEventEmitted = (_event: ICLEvent): void =>
{
  let data = JSON.parse(_event.Data) as IRowByEvent<any>;
  console.log(data);
}

Emitirá el evento Dropped (Se puede verificar que evento se emitió revisando la propiedad "EventName" de IRowByEvent objeto).



Sticky Columns

Al llamar el metodo MapDisplayColumns se debe setear la propiedad stickyColumns donde se debera indicar que columnas se van a fijar y en que lado de la tabla.

this.mappedColumns = MapDisplayColumns<ITodo, string>(
  {
    //...more properties
    stickyColumns: [
      {Name: 'select', FixOn: 'left'},
      {Name: 'title', FixOn: 'left'},
      {Name: 'userId', FixOn: 'left'},
      {Name: 'Options', FixOn: 'right'}
    ]
  }
);

Una vez hecho eso ya se deberian fija las columnas indicadas en el lado indicado.



Preseleccionar filas de la tabla

Primero que nada, la tabla debe tener la propiedad HasItemsSelection en true, de la siguiente manera:

<cl-table 
  ...more properties
  [HasItemsSelection]="true">
</cl-table>

Una vez hecho eso, lo que sigue es indicar que propiedad del objeto que se cargará en la tabla se va a vincular con la columna "select" (Esta columna se habilita al establecer en HasItemsSelections en true), de esta manera:

this.mappedColumns = MapDisplayColumns(
  {
    //..more properties
    propToLinkWithSelectColumn: 'IsActive'
  }
);

IMPORTANTE!!! La propiedad que se va a vincular con la columna "select" debe ser de tipo boolean.

Una vez hecho eso, ya se deberian seleccionar las columnas automaticamente al realizar un INFLATE a la tabla.



Tooltips en celdas y filas

Para agregar esta funcionalidad lo que se debe hacer es lo siguiente:

Tooltips de filas

Se debe agregar la propiedad "RowMessage" en el modelo de fila de la tabla, esta propiedad es de tipo string

this.tableRows = [
  {
      //..more properties
      RowMessage: "Esta es mi fila numero 1"
  },
  //..more items
]

Tooltips de celdas

Se debe agregar la propiedad "CellsMessages" en el modelo de fila de la tabla, esta propiedad es de tipo {key:string:string}

this.tableRows = [
  {
      //..more properties
      Prop1: 'prop1',
      Prop2: 'prop2',
      CellsMessages: {Prop1: 'Esta es mi propiedad 1', Prop2: "Esta es mi propiedad 2"}
  },
  //..more items
]

El nombre de la propiedad indicado en CellsMessages debe ser una propiedad del modelo (tambien pueden ser el nombre de la columna de seleccion multiple (select) o la de opciones (Options)) y tambien esas propiedades excepto (select y Options) deben estar en los renameColumns propiedad de MapDisplayColumns.

Configurar posición de tooltips

Para configurar la posicion de los tooltips se debe agregar la propiedad "tooltipsPosition" en el metodo "MapDisplayColumns", de la siguiente manera:

this.mappedColumns = MapDisplayColumns(
 {
 //...more properties
  tooltipsPosition: {rows: 'left', cells: 'right'}
 }
);

Por defecto los tooltips se muestran el parte superior del elemento, es decir, por defecto usan "above"

Teniendo eso ya deberia funcionar el mostrar tooltips en las filas y celdas de la tabla.

Importante:

  • Solamente puede establecer una propiedad CellsMessages o RowMessage por fila.


Coloreo de filas

Para colorear una fila se debe agregar la siguiente propiedad en el modelo de la fila "RowColor" y establecerle un valor del enum "RowColors".

import {RowColors} from '@clavisco/table';
//...more code
ngOnInit(): void 
{
    this.tableRows = [{/*...more properties*/, RowColor: RowColors.Beige}, /*...more items*/];
    const NEW_TABLE_STATE = {
        Records: this.tableRows,
        RecordsCount: this.tableRows.length
    };
    this.linkerService.Publish({
      CallBack: CL_CHANNEL.INFLATE,
      Data: JSON.stringify(NEW_TABLE_STATE),
      Target: this.myTableComponentId
    });
}

Habilitar selección de una sola fila

Para indicarle a la tabla que solamente queremos que el usuario seleccione una fila, debemos enviarle las siguientes propiedades:

<cl-table
  ...more properties
  [HasItemsSelection]="true"
  ItemsSelectionType="radio">
</cl-table>

Habilitar edición de tamaño de página

Para habilitar la edición del tamaño de página se debe enviar lo siguiente al componente tabla:

<cl-table 
    ...more properties
    [PageSizeEditable]="true"
></cl-table>

Esta propiedad habilitara un checkbox en el paginador el cual cambiará el select con los tamaños de página pre-definidos por un input editable.


Navegar a página específica

Establecer página actual con consultas paginadas, al emitir evento indicar número de página a navegar de la siguiente manera:

 this.linkerService.Publish({
    CallBack: CL_CHANNEL.PRE_REQ_RECORDS,
    Target: this.tableId,
    Data: '0'// Especifica aquí la página a la que se desea navegar, por ejemplo, '0' para la primera página.
});

Establecer página actual con consultas no paginadas, al emitir evento indicar si debe cambiar número de pagina actual y número de página a navegar de la siguiente manera:

const NEXT_TABLE_STATE = {
    CurrentPage: this.currentPage,   
    Records: FULL_OR_SLICE_SOURCE_LIST,
    RecordsCount: this.fullSourceRecordsCount,
    ChangeCurrentPage: true
}

this.linkerService.Publish({
    CallBack: CL_CHANNEL.INFLATE,
    Target: this.tableId,
    Data: JSON.stringify(NEXT_TABLE_STATE)
    } as ICLEvent);

Solución de problemas (Troubleshooting)

  • Existe un posible error cuando se implementa el uso de drag and drop en conjunto con la detección de eventos de línea de la tabla, es importante validar que el tipo del evento corresponda con la funcionalidad que se esta desarrollando, puede consultar el siguiente ejmeplo de implementación
private EventColumn = (_event: ICLEvent) => {
    try {
    
      let ALL_RECORDS = JSON.parse(_event.Data) as IRowByEvent<IDocumentLine>;
    
      if (ALL_RECORDS.EventName === 'Dropdown') {
       ...
      } else if (ALL_RECORDS.EventName === 'InputField') {
       ...
      } else if (ALL_RECORDS.EventName === 'Checkbox') {
       ...
      } else if (ALL_RECORDS.EventName === 'Dropped') {
       ...
      }
    } catch (error) {
     ...
    }
}

Recomendaciones

Visitar @clavisco/core para conocer la amplia gama de funcionalidades que se nos ofrecen para facilitarnos el proceso de desarrollo

Visitar @clavisco/linker con el fin de entender los procesos de comunicacion entre componentes y hacia los componentes

Clavis Consultores ©

1.3.1

17 hours ago

1.3.1-beta.2

15 days ago

1.3.1-beta.1

20 days ago

1.3.0

2 months ago

1.3.1-beta.0

2 months ago

1.2.0

5 months ago

1.2.0-beta.3

5 months ago

1.2.0-beta.2

5 months ago

1.2.0-beta.1

5 months ago

1.2.0-beta.0

5 months ago

1.1.0

5 months ago

1.0.0

7 months ago

0.0.35

10 months ago

1.1.0-beta.2

6 months ago

1.1.0-beta.1

6 months ago

1.1.0-beta.0

7 months ago

0.0.36-beta.0

8 months ago

1.1.0-beta.5

6 months ago

0.0.36-beta.1

8 months ago

1.1.0-beta.4

6 months ago

0.0.36-beta.2

8 months ago

1.1.0-beta.3

6 months ago

0.0.36-beta.3

7 months ago

0.0.35-beta.1

10 months ago

0.0.35-beta.2

10 months ago

0.0.34

11 months ago

0.0.35-beta.0

11 months ago

0.0.34-beta.5

12 months ago

0.0.34-beta.4

1 year ago

0.0.34-beta.8

12 months ago

0.0.34-beta.7

12 months ago

0.0.34-beta.6

12 months ago

0.0.34-beta.3

1 year ago

0.0.34-beta.2

1 year ago

0.0.34-beta.1

1 year ago

0.0.34-beta.0

1 year ago

0.0.32

1 year ago

0.0.33

1 year ago

0.0.30

1 year ago

0.0.31

1 year ago

0.0.29

1 year ago

0.0.27

1 year ago

0.0.26

1 year ago

0.0.25

1 year ago

0.0.24

1 year ago

0.0.23

1 year ago

0.0.22

1 year ago

0.0.21

1 year ago

0.0.20

1 year ago

0.0.19

1 year ago

0.0.18

1 year ago

0.0.17

2 years ago

0.0.16

2 years ago

0.0.15

2 years ago

0.0.14

2 years ago

0.0.13

2 years ago

0.0.12

2 years ago

0.0.11

2 years ago

0.0.10

2 years ago

0.0.9

2 years ago

0.0.7

2 years ago

0.0.6

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago