npm package: @guajiritos/data-table
Description: Guajiritos Data Table es una librería para Angular desarrollada desde febrero, 2023 con el fin de optimizar el trabajo con las tablas. Para ellos se crearon un conjunto de acciones personalizadas: filtros, botones, títulos - encabezados.
Author: Guajiritos SRL
Latest version: 19.0.44

# [Guajiritos Data Table](https://www.npmjs.com/package/@guajiritos/data-table)

Guajiritos Data Table es una librería para Angular desarrollada desde febrero, 2023
con el fin de optimizar el trabajo con las tablas.
Para ellos se crearon un conjunto de acciones personalizadas:
filtros, botones, títulos - encabezados.

Pero dejaremos que usted solo descubra y explore las bondades de esta librería.😌😊️🙂

## Instalación:

### npm:

```shell
npm i @guajiritos/data-table
```

### yarn:

```shell
yarn add @guajiritos/data-table
```

### pnpm:

```shell
pnpm add @guajiritos/data-table
```

## Uso

### Dependencias:

1. Instalar dependencias
   {} package.json

 ```json
 "dependencies": {
"@angular/cdk": "^16.0.0 || >=16.0.0",
"@angular/common": "^16.0.0 || >=16.0.0",
"@angular/core": "^16.0.0 || >=16.0.0",
"@angular/material": "^16.0.0 || >=16.0.0",
"@ngx-translate/core": "^15.0.0 || >=15.0.0",
"ngx-toastr": "^17.0.0 || >=17.0.0",
"@guajiritos/general-autocomplete": "^0.1.0 || >= 1.0.0",
"@guajiritos/rest-full-service": "^0.0.10 || >=0.0.10"
}
   ```

2. Añadir al módulo donde se declara el componente que lo va a usar

```ts
 import { GuajiritosGeneralAutocomplete } from '@guajiritos/general-autocomplete';
import { GuajiritosDatatable } from './guachos-datatable.component';

@NgModule({
  declarations: [AgencyComponent],
  imports: [GuajiritosDatatable, GuajiritosGeneralAutocomplete],
})
```

* Nota: La librería será usada en el componente: AgencyComponent

3. Añadir tema del data-table al archivo mixin del proyecto

```scss
@import "@guajiritos/data-table/theme";

@mixin mixin-theme($theme) {
  @include theme-guajiritos-data-table($theme);
}
```

4. Declarar y usar selector de la librería en el html del componente
   <> agency.component.html

```html

<guajiritos-data-table
    (add)="onAdd()"
    (delete)="onDelete($event)"
    (detail)="onEdit($event)"
    (edit)="onEdit($event)"
    (customAction)="onCustomAction($event)"
    *ngIf="dataTableOption" [options]="dataTableOption"
    [refresh]="refreshData$"
    (searchFinalized)="searchFinalized()"
    (searchStarted)="searchStarted()">
</guajiritos-data-table>
```

5. En el hock AfterViewInit del componente declarar las opciones y configuraciones de los datos que serán mostrados
   siempre y cuando no se necesiten cargar componentes dentro de la table, para este caso **es mejor usar el
   ngAfterContentInit**, pues se espera a que se carguen todos los componentes y luego se pinta el dataTable

```ts
ngAfterViewInit()
:
void {
  this.dataTableOption
:
DataTableOptions = { ... }
}
```

## Descripción

### Interfaz

```ts
export interface DataTableOptions {
  bodyRequest?: ApiFormData;
  title?: string;
  id?: string;
  order?: string;
  service: any;
  listMethod: string;
  showFooter?: boolean;
  permissions?: CrudOptions;
  selection: SelectionOptions;
  customOptions?: CustomOptions;
  pageSizeOptions: number[];
  customActions?: CustomAction[];
  basicActions?: BasicActions;
  staticFilters?: StaticFilter[];
  staticFiltersOut?: StaticFiltersOut[];
  staticToggleOptions?: ToggleOptions[];
  displayedColumns: ColumnOptions[];
  displayedColumnsFilters?: ColumnFilterOptions[];
}
```

### Datos

* Los datos de las columnas pueden ser de tipo:
  - texto > ColumnOptionsType.SIMPLE
  - número > ColumnOptionsType.NUMBER
  - objeto > ColumnOptionsType.TEMPLATE_REF
* Un texto personalizado que se configura en el atributo *label*

Se muestran y configuran en la tabla a partir del atributo nombrado displayedColumns
que implementa la interfaz ColumnOptions.

```ts
export interface ColumnOptions {
  name: string;
  label: string;
  secondaryLabel?: string;
  forFilters?: string;
  notOrder?: boolean;
  useTranslation?: boolean;
  footerOptions?: FooterOption;
  width?: boolean;
  thWidth?: string;
  type: ColumnOptionsType.NUMBER | ColumnOptionsType.SIMPLE | ColumnOptionsType.TEMPLATE_REF;
  customPipe?: string;
  path?: any;
  templateRef?: TemplateRef<any>;
  templateData?: TemplateData;
  multipleData?: boolean;
  propertyValue?: any[];
}
```

```ts
displayedColumns: [
  {
    name: "name",
    forFilters: "filter[$or][name][$like]",
    label: _t("sucursal"),
    type: ColumnOptionsType.SIMPLE,
    path: ["name"],
    thWidth: '25%',
  },
  {
    name: "phone-email",
    forFilters: "filter[$or][phone][$like]",
    label: _t("teléfono/correo"),
    type: ColumnOptionsType.TEMPLATE_REF,
    templateRef: this.phoneEmailTemplate,
    thWidth: '25%',
  }
]
```

Para las **columnas de tipo texto** y/o **número** se emplea el atributo *path*
donde se define el camino de donde se obtiene dicho atributo en el objeto.
Ej: En el caso anterior mostramos el nombre (name) de la Agencia
> Agencia: Agencia = { private name: string}

Para las **columnas de tipo objeto** se emplea el atributo *templateRef*
Se crea un @ViewChild del template que se desea mostrar en la columna.
Ej: En el agency.component.html se declara el template donde el *element* es la Agencia
donde el email y el phone son atributos de dicho objeto
> Agencia: Agencia = { private name: string; private phone: string; private email: string}

> @ViewChild("phoneEmailTemplate", { static: false }) phoneEmailTemplate: TemplateRef<any>;

```html

<ng-template #phoneEmailTemplate let-element>
  <div class="d-flex flex-column">
    <span> {{element?.phone}}</span>
    <span> {{element?.email}}</span>
  </div>
</ng-template>
```

### Botones:

Se aplican a cada elemento de la tabla. Implementan la interfaz
Por defecto trae 3: editar, detalles y eliminar (son configurables por lo que se pueden esconder, por defecto aparecen
visibles)

* Para configurarlos se implementa la interfaz customOptions donde su valor boolean define si se esconden (false por
  defecto)
  o no (true)

```ts
export interface CustomOptions {
  hideEditButton?: boolean;
  hideDeleteButton?: boolean;
  hideDetailButton?: boolean;
  hideExportButton?: boolean;
  hideFilterRow?: boolean;
  customWidth?: string;
}
```

Ej: En este caso no queremos mostrar los botones de editar ni de eliminar por eso le asignamos el valor true al atributo
hide...

```ts
customOptions = {
  hideEditButton: true,
  hideDeleteButton: true,
}
```

- Se pueden añadir [más botones](#más-botones) y personalizar su apariencia así como su comportamiento

#### Más botones

A cada elemento de la tabla se le pueden aplicar acciones personalizadas, las que implementan la interfaz customActions

```ts
export interface CustomAction {
  name: string;
  icon: string;
  show: boolean;
  type?: CustomActionType.BUTTON | CustomActionType.TOGGLE_FILTER;
  isMultiple?: boolean;
  specificCondition?: SpecificCondition[];
  materialColor?: MaterialColor.PRIMARY | MaterialColor.ACCENT | MaterialColor.WARN;
  backgroundColor?: string;
  color?: string;
  mode?: ButtonMode.MAT_RAISED_BUTTON | ButtonMode.MAT_BUTTON | ButtonMode.MAT_STROKED_BUTTON | ButtonMode.MAT_FLAT_BUTTON | ButtonMode.CUSTOM;
  toggleOptions?: ToggleOptions;
}
```

* Para definirle un comportamiento o acción definimos en el agencia.component.ts un método llamado onCustomAction(
  $event)
  Ej: A cada agencia mostrada en la tabla se le va a aplicar una acción llamada *Adjudicar*
  y se van a mostrar sólo si se cumple que el *status* de la agencia tenga el *valor* de *"NOT_ASSIGNED"*
  y además tenga un *statusPayment con* el *valor "paid"*

```ts
public
customActions: CustomAction = [
  {
    name: _t("Adjudicar"),
    icon: "person_add_alt",
    show: true,
    specificCondition: [
      {
        field: ['status'],
        value: ['NOT_ASSIGNED'],
      },
      {
        field: ['statusPayment'],
        value: ['paid'],
      }
    ],
    type: CustomActionType.BUTTON,
    mode: ButtonMode.MAT_BUTTON,
    materialColor: MaterialColor.ACCENT
  },
]
```

Ej: Aquí para ejecutar el método nombrado "this.toAward($event.element)" el $event?.customAction?.name debe coincidir
con el nombre del customAction puesto
Tienen dos propiedades con condiciones que debe complir para se muestre el customAction
specificCondition: Condiciones o grupo de condiciones
sameValueCheckKeys: keys de los elementos que se compribaran que tengan el mismo valor en todos los elementos seleccionados
        en caso de la key sea otro objeto debe ir separado por punto ej. ['key1', 'key2.key3'] key2 es un objeto en el element.

```ts
public onCustomAction($event = null): void {
  if(!$event){
    return;
  }

  switch ($event?.customAction?.name) {
    case 'Adjudicar': {
      this.toAward($event.element);
      break;
    }
    default: {
      break;
    }
  }
}
 ```

### Selectores

Se le aplican a la tabla entera y son configurables, implementan la interfaz SelectionOptions
> selection: SelectionOptions;
>

```ts
export interface SelectionOptions {
  hasSelection: boolean;
  multiple: boolean;
}
```

Ej: Aquí se desea mostrar el cuadro delantero para seleccionar un elemento por eso se le pone el
"hasSelection" en "true" pero no se desea seleccionar más de un elemento a la vez, por eso el "multiple"
está en "false"

```ts
selection = {
  hasSelection: true,
  multiple: false,
}
```

### Acciones:

Se le aplica a la tabla entera
Por defecto trae 3: añadir, exportar y actualizar (son configurables por lo que se les puede poner un nombre
personalizado)

- Se pueden añadir más opciones

```ts
 basicActions = {
  addBtn: {
    text: _t("Crear Agencia"),
    icon: "add",
    color: MaterialColor.PRIMARY,
    mode: ButtonMode.MAT_FLAT_BUTTON,
  },
  refreshBtn: {
    text: _t("actualizar"),
    icon: "update",
    mode: ButtonMode.MAT_STROKED_BUTTON,
  },
  exportBtn: {
    text: _t("exportar"),
    icon: "save_alt",
    mode: ButtonMode.MAT_BUTTON,
  },
}
```

Para añadirle una funcionalidad a estas 3 acciones se usan los métodos:

1. onAdd() ≥ crear una nueva agencia
2. onExport() ≥ exportar los datos de la tabla entera

* Nota: El actualizar no lleva implementación configurable,
  se encarga automáticamente de actualizar los datos de la tabla

- El dato *text* el texto que se va a mostrar en el botón
- El dato *icon* se refiere al ícono de material que se va a emplear junto al texto proporcionado
- El dato *mode* es de qué tipo será el botón

### Títulos o encabezados:

Por defecto no posee ninguno peros se le puede añadir

### Filtros:

### Inputs - Outputs:

Aquí se muestran los inputs y outputs de la librería, los que al seleccionar uno o varios elementos de la tabla
llaman a una función previamente definida en el .ts del componente que trabaja con la librería, también están los casos
en que las acciones que se ejecutan sin seleccionar previamente ningún elemento

```text
    (add)="onAdd()"
    (delete)="onDelete($event)"
    (detail)="seeDetails($event)"
    (edit)="seeDetails($event)"
    (export)="onExport()"
    (customAction)="onCustomAction($event)"
    [options]="dataTableOption"
    [refresh]="refreshData$"
    (searchFinalized)="searchFinalized()"
    (searchStarted)="searchStarted()"
 ```

Ej:

## Sin seleccionar un elemento:

- add: al configurar el basicActions "addBtn" -> añade un elemento a la tabla
- refresh: al configurar el basicActions "refreshBtn" -> actualizar los datos de la tabla haciéndole una petición a API
- export: al configurar el basicActions "exportBtn" -> exportar los datos de la tabla
- searchStarted: se ejecuta la función configurada al comenzar la petición a API de los datos a mostrar en la tabla
- searchFinalized: se ejecuta la función configurada al terminar la petición a API de los datos a mostrar en la tabla
- options: configuración del componente

## Seleccionando un elemento:

Aquí es muy útil la [selección](#selectores) de los elementos y la configuración de los [botones](#botones-)

- detail: mostrar los detalles del elemento seleccionado
- edit: editar el elemento seleccionado
- delete: eliminar el elemento seleccionado
- customAction: [funcionalidades nuevas configuradas](#más-botones) para la realización de una determinada acción sobre
  el elemento seleccionado

## Seleccionando varios elementos:

Aquí es muy útil la [selección](#selectores) de los elementos

- delete: aquí al seleccionar varios elementos se eliminan simultáneamente de la tabla