l-lin / angular-datatables

DataTables with Angular
https://l-lin.github.io/angular-datatables/
MIT License
1.57k stars 487 forks source link

paging and searching #1478

Closed sbemarketing closed 3 years ago

sbemarketing commented 3 years ago

Hello, good morning everyone, I am using angular-datatables and with the example data it works correctly, but when entering a new element to the array I have some problems that I would like to help me solve:

I use two ways to display data in the datatable, by entering the new json into the this.data array using this.data.push (json), and by using the service to get data from the backend.

In both cases I have the same problems:

I am using Angular 9

Please your help with this problem, I am new to angular and I don't know how to solve this problem I have, Thank you very much,

shanmukhateja commented 3 years ago

Hi,

If you could provide a Github repo or StackBlitz link, it would be easier to assist you with this as we need more info.

BelvedereHenrique commented 3 years ago

@shanmukhateja Same here.

Here is my component

@Component({
  selector: 'app-avaliacao',
  templateUrl: './avaliacao.component.html',
  styleUrls: ['./avaliacao.component.css']
})
export class AvaliacaoComponent implements OnInit {
  dtOptions: DataTables.Settings = {};
  dtTrigger: Subject<any> = new Subject<any>();
  avaliacoes: Avaliacao[] = [];

  constructor(private route: ActivatedRoute,
    private service: AvaliacaoService) {
  }

  ngOnInit(): void {
    this.dtOptions = new GenericDataTableSettings();
    this.avaliacoes = this.route.snapshot.data.avaliacoes;
  }

  ngAfterViewInit(): void {
    this.dtTrigger.next();
  }

  search = (value: string) => {
    this.service.search(value).subscribe((result) => {
      this.avaliacoes = result;
    });
  }

  changeStatus = (avaliacao: Avaliacao): void => {
    alert(avaliacao.status);
  }

  ngOnDestroy(): void {
    // Do not forget to unsubscribe the event
    this.dtTrigger.unsubscribe();
  }

and my html

        <table datatable class="data-table" [dtOptions]="dtOptions">
            <colgroup>
                <col span="1" style="width: 5%;">
                <col span="1" style="width: 70%;">
                <col span="1" style="width: 20%;">
                <col span="1" style="width: 5%;">
             </colgroup>
            <thead>
                <tr>
                    <th scope="col"></th>
                    <th scope="col"> Designação </th>
                    <th scope="col"></th>
                    <th scope="col"></th>
                </tr>
            </thead>
            <tbody>
                <tr *ngFor="let avaliacao of avaliacoes">
                    <td></td>
                    <td>{{avaliacao.designacao}}</td>
                    <td class="data-table-icons" [ngSwitch]="avaliacao.status">
                        <i class="bi bi-pencil data-table-edit-icon"></i>
                        <i class="bi bi-trash data-table-trash-icon" *ngSwitchCase="true" tooltip="Desativar" (click)="changeStatus(avaliacao)"></i>
                        <i class="bi bi-check2 data-table-check-icon" *ngSwitchCase="false" tooltip="Ativar" (click)="changeStatus(avaliacao)"></i>
                    </td>
                    <td></td>

                </tr>
            </tbody>
        </table>

whenever i update "this.avaliacoes", the table itself updates, but it keeps the pagination untouched. That means if I have a table with 10 pages, and I update the data which will result on only 1 page, data-table component keeps showing 10 pages at the selector.

BelvedereHenrique commented 3 years ago

For example Full table: image

After Search (updated "this.avaliacoes" on "search" method, showed above): image

if we go to page 2 and go back to page 1: image

All the data is back, but we didn't change the data array.

shanmukhateja commented 3 years ago

@BelvedereHenrique it looks like your server side processing is reporting incorrect info. Could you make a small reproducible repo with StackBlitz or GitHub and paste the link here?

BelvedereHenrique commented 3 years ago

Hey @sbemarketing , thanks for the fast reply. I'm on a rush now, but I can create a stackblitz later for sure.

I managed to fix it this way:

Whenever I query my API, I rerender the whole table:

  search = (value: string) => {
    this.service.search(value).subscribe((result) => {
      this.avaliacoes = result;
      this.reRenderDataTable();
    });
  }

  reRenderDataTable(): void {
    this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
      dtInstance.destroy();
      this.dtTrigger.next();
    });
  }

I got the table reference by ViewChild: @ViewChild(DataTableDirective, { static: false }) dtElement!: DataTableDirective; I'm not sure if what I'm doing is leading me to future problems, I'm not really used to front-end. What do you think?

shanmukhateja commented 3 years ago

Hi, calling destroy on each AJAX call sounds unhealthy. Have you try dtInstance.draw()?

It feels like Angular's change detection isn't able to "notice" table has changed. Try the below code:

dtOptions = {
...., // your code
drawCallback: () => {this.applicationRef.tick() // Inject ApplicationRef to constructor
}
BelvedereHenrique commented 3 years ago

drawCallback: () => {this.applicationRef.tick()

This doesn't seens to work as well.

shanmukhateja commented 3 years ago

That's unfortunate. could you provide a StackBlitz or GitHub repo link when you can?

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 3 years ago

This issue has been closed due to inactivity. Please feel free to re-open the issue to add new inputs.