# CRUDComponentBase

Este abstração possui todos os métodos necessárias para uma página de CRUD, utilizando todo o potencial do Cat UI.

### C (CREATE)

Para a parte de criação existe a opção padrão que é utilizando [Dialog](https://doc.catui.igordrangel.com.br/janelas-e-alertas/dialog), ou, caso queira, poderá abrir uma [Janela Lateral](https://doc.catui.igordrangel.com.br/janelas-e-alertas/sidewindow) ou navegar para uma nova página.

Para abrir um dialog com seu formulário utilize o método **openFormDialog.**

{% hint style="info" %}
O método **openFormDialog** utiliza por padrão o componente de [formulários dinâmicos](https://doc.catui.igordrangel.com.br/formulario/formulario-dinamico), permitindo a configuração de um [Dialog ](https://doc.catui.igordrangel.com.br/janelas-e-alertas/dialog)com formulário sem a necessidade de criar arquivos para tal.
{% endhint %}

{% code lineNumbers="true" %}

```typescript
import { CatCRUDComponentBase } from "@catrx/ui/common";

@Component({...})
export class PageExempleComponent extends CatCRUDComponentBase {
  ...
  
  openDialog(data?: any) {
    this.openFormDialog(
        this.formService
          .build<Cat>(data)
          .text('Raça', 'race', (builder) =>
            builder.grid(6).setRequired().generate()
          )
          .select('Sexo', 'sex', (builder) =>
            builder
              .setOptions(CatSexSelectOptions)
              .grid(6)
              .setRequired()
              .generate()
          )
          .url('URL da Foto', 'photo', (builder) =>
            builder.setRequired().generate()
          )
          .onSubmit((cat) => this.service.save(cat, data?.id))
          .generate(),
        !!data,
        { title: 'Gato' }
      );
  }
}
```

{% endcode %}

{% hint style="info" %}
Ao realizar o submit no formulário gerado, já será realizado o disparo de [spinner ](https://doc.catui.igordrangel.com.br/loaders/spinner)no **botão de submit** junto com seu **bloqueio**...após o retorno da API em caso de **sucesso** ou **error** um [Snackbar ](https://doc.catui.igordrangel.com.br/janelas-e-alertas/snackbar)será exibido de acordo e em caso de sucesso o [Dialog ](https://doc.catui.igordrangel.com.br/janelas-e-alertas/dialog)será fechado e um comando de reloadList será disparado, em seguida o componente de [Datatable ](https://doc.catui.igordrangel.com.br/exibicao-de-dados/datatable)será recarregado.
{% endhint %}

### R (READ)

Para a parte de leitura, teremos aqui a utilização do componente de [Datatable](https://doc.catui.igordrangel.com.br/exibicao-de-dados/datatable), onde teremos que configurar o mesmo, passando as colunas que serão exibidas, habilitando seletores, botões de ação e filtro.

{% code lineNumbers="true" %}

```typescript
import { CatCRUDComponentBase } from "@catrx/ui/common";

@Component({...})
export class PageExempleComponent extends CatCRUDComponentBase {
  filterConfig = this.filterFormBuilder
    .search('Filtro', 'filter', (builder) => builder.grid(3).generate())
    .onChange((data) => this.filterValueChanges$.next(data?.filter))
    .generate();

  listConfig = this.datatableService
    .build(this.filterValueChanges$, (filter) =>
      this.service.getDatatable(filter)
    )
    .setColumns(['Foto', 'Sexo', 'Raça'])
    .setItemLine({
      columnIndex: 0,
      component: (item) => new CatDynamicComponent(CatPhotoComponent, item.photo),
    })
    .setItemLine({ columnIndex: 1, text: (item) => item.sex })
    .setItemLine({ columnIndex: 2, text: (item) => item.race })
    .setActionButton({
      iconName: 'fa-solid fa-pencil',
      tooltip: 'Editar',
      fnAction: (item) => this.openDialog(item),
    })
    .getSelection((selection) => (this.selection = selection))
    .getDatasource((datasource) => (this.datasource = datasource))
    .hasSelection()
    .hasActions()
    .generate();

  ...
}
```

{% endcode %}

A parte de leitura também existe a possibilidade de exportação em .csv ou .xlsx, e para isso, utilizaremos o método exportByService presente na [abstração de Serviços HTTP](https://doc.catui.igordrangel.com.br/abstracoes/servicebase).

```typescript
import { CatCRUDComponentBase } from "@catrx/ui/common";

@Component({...})
export class PageExempleComponent extends CatCRUDComponentBase {
  ...
  
  export(filename: string): void {
    this.exportByService({ 
      xlsx: { filename, sheetName: 'Gatos' } 
    }, this.service.export());
  }
}
```

```html
...

<cat-form [config]="filterConfig"></cat-form>

<cat-datatable [config]="listConfig">
  ...
  
  <nav list-actions>
    <cat-icon-button
      *ngIf="datasource?.length > 0"
      (click)="export('Lista de Gatos')"
      icon="fa-solid fa-download"
      tooltip="Exportar Lista">
    </cat-icon-button>
  </nav>
</cat-datatable>
```

### U (UPDATE)

Terá a mesma implementação do [Create](#c-create), porém, precisará informar o objeto que deseja editar, para que após a abertura do formulário, o mesmo seja automaticamente preenchido e um comando de PUT seja enviado após o submit.

### D (DELETE)

O componente de [Datatable](https://doc.catui.igordrangel.com.br/exibicao-de-dados/datatable), possui em suas configurações, a opção de habilitar **seletores** ou incluir **botões de ação**. Aproveitando este recurso, iremos implementar a ação de **DELETE** por meio de seletores na lista.

Neste caso, todo a implementação para delete já está pronta para uso, bastando chamar pelo método **deleteSelected** por meio do click do botão.

```html
...

<cat-datatable [config]="listConfig">
  <nav list-checked-actions>
    <cat-icon-button
      (click)="deleteSelected()"
      icon="fa-solid fa-trash-can"
      tooltip="Excluir Selecionados">
    </cat-icon-button>
  </nav>
  
  ...
</cat-datatable>
```

### Overview

{% embed url="<https://cat-ui.igordrangel.com.br/examples/crud-page>" %}

### Implementação Completa

#### 1. Implementando serviço HTTP

{% tabs %}
{% tab title="cat.interface.ts" %}
{% code lineNumbers="true" %}

```typescript
import { CatFormListOptions } from "@catrx/ui/form";

export interface CatFilter {
  filter?: string;
}
export interface Cat {
  id?: number;
  photo: string;
  race: string;
  sex: CatSexType;
}
export type CatSexType = 'M' | 'F';
export const CatSexSelectOptions: CatFormListOptions[] = [
  { value: 'M', name: 'Macho' },
  { value: 'F', name: 'Fêmea' },
];
```

{% endcode %}
{% endtab %}

{% tab title="cat.service.ts" %}
{% code lineNumbers="true" %}

```typescript
import { Injectable } from "@angular/core";
import { CatServiceBase } from "@catrx/ui/common";
import { HttpClient } from '@angular/common/http';
import { Cat, CatFilter } from "./cat.interface";
import { CatDatatableDataHttpResponse } from "@catrx/ui/datatable";
import { map } from "rxjs/internal/operators/map";
import { Observable } from "rxjs/internal/Observable";

@Injectable({ providedIn: 'root' })
export class CatService extends CatServiceBase<CatFilter, Array<Cat>, Cat> {
  constructor(http: HttpClient) {
    super(http, 'cat', {
      useMockup: true,
      mockupStartBase: [
        {
          id: 1,
          race: 'Frajola',
          sex: 'M',
          photo:
            'https://static1.patasdacasa.com.br/articles/7/49/77/@/20775-o-gato-preto-e-branco-tem-um-charme-que-articles_media_mobile-2.jpg',
        },
        {
          id: 2,
          race: 'Tigrado',
          sex: 'M',
          photo:
            'https://t1.ea.ltmcdn.com/pt/posts/1/2/6/4_gato_europeu_23621_3_600.jpg',
        },
        {
          id: 3,
          race: 'Branco',
          sex: 'M',
          photo:
            'https://static1.patasdacasa.com.br/articles/5/29/95/@/12462-saiba-o-que-e-bolsa-primordial-e-sua-fun-articles_media_mobile-1.jpg',
        },
      ],
    });
  }

  public export() {
    return this.exportByService(() => this.getDatatable());
  }

  public getDatatable(filter?: CatFilter): Observable<CatDatatableDataHttpResponse<Cat>> {
    return this.getAll(filter).pipe(map(response => {
      return {
        count: response.length,
        items: response
      };
    }))
  }
}

```

{% endcode %}
{% endtab %}
{% endtabs %}

#### 2. Implementando componente de foto

{% code title="cat-photo.component.ts" lineNumbers="true" %}

```typescript
import { Component } from '@angular/core';
import { CatDynamicComponentDataInterface } from '@catrx/ui/dynamic-component';

@Component({
  template: `<img [src]="data" alt="Foto de Gato" width="100" height="100" />`,
  styles: [
    `
      img {
        border-radius: 50%;
      }
    `,
  ],
})
export class CatPhotoComponent implements CatDynamicComponentDataInterface {
  data: string;
}
```

{% endcode %}

#### 3. Implementando componente de página

{% tabs %}
{% tab title="page-crud-example.component.html" %}

```html
<cat-toolbar [config]="getToolbarInfo()">
  <nav buttons>
    <cat-primary-button (click)="openDialog()">Incluir Gato</cat-primary-button>
  </nav>
</cat-toolbar>
<cat-form [config]="filterConfig"></cat-form>
<cat-datatable [config]="listConfig">
  <nav list-checked-actions>
    <cat-icon-button
      (click)="deleteSelected()"
      icon="fa-solid fa-trash-can"
      tooltip="Excluir Selecionados">
    </cat-icon-button>
  </nav>

  <nav list-actions>
    <cat-icon-button
      *ngIf="datasource?.length > 0"
      (click)="export('Lista de Gatos')"
      icon="fa-solid fa-download"
      tooltip="Exportar Lista">
    </cat-icon-button>
  </nav>
</cat-datatable>
```

{% endtab %}

{% tab title="page-crud-example.component.ts" %}
{% code lineNumbers="true" %}

```typescript
import { Component } from '@angular/core';
import { CatCRUDComponentBase } from '@catrx/ui/common';
import { CatConfirmService } from '@catrx/ui/confirm';
import { CatDatatableService } from '@catrx/ui/datatable';
import { CatDialogService } from '@catrx/ui/dialog';
import { CatDynamicComponent } from '@catrx/ui/dynamic-component';
import { CatFormService } from '@catrx/ui/form';
import { CatLoaderPageService } from '@catrx/ui/loader-page';
import { CatSnackbarService } from '@catrx/ui/snackbar';
import { CatCsvService, CatXlsxService } from '@catrx/ui/utils';
import { CatPhotoComponent } from './cat-photo.component';
import { Cat, CatFilter, CatSexSelectOptions } from './services/cat.interface';
import { CatService } from './services/cat.service';

@Component({
  templateUrl: './page-crud-example.component.html',
  styles: [
    `
      cat-form {
        display: block;
        margin: 20px 20px 10px;
      }
    `,
  ],
})
export class PageCRUDExampleComponent extends CatCRUDComponentBase<
  CatFilter,
  Cat
> {
  filterConfig = this.filterFormBuilder
    .search('Filtro', 'filter', (builder) => builder.grid(3).generate())
    .onChange((data) => this.filterValueChanges$.next(data?.filter))
    .generate();

  listConfig = this.datatableService
    .build(this.filterValueChanges$, (filter) =>
      this.service.getDatatable(filter)
    )
    .setColumns(['Foto', 'Sexo', 'Raça'])
    .setItemLine({
      columnIndex: 0,
      component: (item) => new CatDynamicComponent(CatPhotoComponent, item.photo),
    })
    .setItemLine({ columnIndex: 1, text: (item) => item.sex })
    .setItemLine({ columnIndex: 2, text: (item) => item.race })
    .setActionButton({
      iconName: 'fa-solid fa-pencil',
      tooltip: 'Editar',
      fnAction: (item) => this.openDialog(item),
    })
    .getSelection((selection) => (this.selection = selection))
    .getDatasource((datasource) => (this.datasource = datasource))
    .hasSelection()
    .hasActions()
    .generate();

  constructor(
    protected override service: CatService,
    formService: CatFormService,
    datatableService: CatDatatableService,
    dialogService: CatDialogService,
    confirmService: CatConfirmService,
    csvService: CatCsvService,
    xlsxService: CatXlsxService,
    loaderService: CatLoaderPageService,
    snackbarService: CatSnackbarService
  ) {
    super(
      formService,
      datatableService,
      service,
      loaderService,
      snackbarService,
      dialogService,
      confirmService,
      { csv: csvService, xlsx: xlsxService }
    );
  }

  export(filename: string): void {
    this.exportByService({ 
      xlsx: { filename, sheetName: 'Gatos' } 
    }, this.service.export());
  }

  openDialog(data?: Cat) {
    this.openFormDialog(
      this.formService
        .build<Cat>(data)
        .text('Raça', 'race', (builder) =>
          builder.grid(6).setRequired().generate()
        )
        .select('Sexo', 'sex', (builder) =>
          builder
            .setOptions(CatSexSelectOptions)
            .grid(6)
            .setRequired()
            .generate()
        )
        .url('URL da Foto', 'photo', (builder) =>
          builder.setRequired().generate()
        )
        .onSubmit((cat) => this.service.save(cat, data?.id))
        .generate(),
      !!data,
      { title: 'Gato' }
    );
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### 4. Implementando módulo

{% code title="page-crud-example.module.ts" lineNumbers="true" %}

```typescript
import { NgModule } from '@angular/core';
import { PageCRUDExampleComponent } from './page-crud-example.component';
import { CommonModule } from '@angular/common';
import { CatToolbarModule } from '@catrx/ui/toolbar';
import { CatFormModule } from '@catrx/ui/form';
import { CatDatatableModule } from '@catrx/ui/datatable';
import { CatDialogModule } from '@catrx/ui/dialog';
import { CatConfirmModule } from '@catrx/ui/confirm';
import { PageCRUDExampleRoutingModule } from './page-crud-example.routing.module';
import { CatPrimaryButtonComponent } from '@catrx/ui/button';
import { CatIconButtonModule } from '@catrx/ui/icon-button';
import { CatPhotoComponent } from './cat-photo.component';

@NgModule({
  declarations: [PageCRUDExampleComponent, CatPhotoComponent],
  imports: [
    CommonModule,
    CatToolbarModule,
    CatFormModule,
    CatDatatableModule,
    CatDialogModule,
    CatConfirmModule,
    CatIconButtonModule,
    CatPrimaryButtonComponent,
    PageCRUDExampleRoutingModule,
  ],
})
export class PageCRUDExampleModule {}
```

{% endcode %}

#### 5. Configurando xlsx

{% code title="app.module.ts" lineNumbers="true" %}

```typescript
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CatUiModule } from '@catrx/ui/core';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [AppComponent],
  imports: [CatUiModule.forRoot(environment, {
    xlsxConfig: {
      headerBackgroundColor: '#212121',
      headerFontColor: '#f1f1f1',
      normalizeHeader: true
    }
  }), AppRoutingModule],
  bootstrap: [AppComponent],
})
export class AppModule {}
```

{% endcode %}
