在Angular 7中刷新datatables.net表数据可保留表第一次加载时的旧数据的副本

时间:2019-02-24 00:35:11

标签: angular datatables angular7 angular-datatables

我正在尝试使用Angular 7中的datatables.net库根据REST API请求进行实时报告。如果我对数据库进行数据更新,则表中的数据将更新。但是,如果我触摸表(即重新排序,搜索内容,更改页面等),则在数据重新加载时(每5秒发生一次),表中的数据会从表的第一次加载中添加。如果我再次触摸该表,则更新的数据将消失,仅保留旧数据,直到下一次数据更新时,才将新数据再次添加到表中。

这是页面加载时表的状态 State of the table on page load

这是更新数据库中数据时表的状态

state of the table when the data in the database is updated

这是在表格上进行任何更改(即排序,搜索,切换页面等)时表格的行为 behavior of the table when any change is made on the table

这是组件的代码:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Subject } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { DownloadService } from '../services/download/download.service';
import { stringify } from 'querystring';
import { Router } from '@angular/router';

@Component({
  selector: 'app-downloads',
  templateUrl: './downloads.component.html',
  styleUrls: ['./downloads.component.css']
})

export class DownloadsComponent implements OnInit {

  downloadData$: any[] = [];
  dtOptions: DataTables.Settings = {};
  dtTrigger: Subject<any> = new Subject();
  interval: any;

  constructor(private http: HttpClient, private data: DownloadService, private router: Router) { }

  ngOnInit() {
    this.dtOptions = {
      responsive: true
    };

    this.data.GetDownloads().subscribe(data => {
      this.downloadData$ = data;
      this.dtTrigger.next();
    });

    this.interval = setInterval(() => {
      this.refreshData();
    }, 5000);
  }

  refreshData() {
    this.data.GetDownloads().subscribe(data => {
      this.downloadData$ = data;
    });
  }

  ngOnDestroy(): void {
    this.dtTrigger.unsubscribe();
  }
}

这是html文件

<div>
  <table style="text-align: center;" class="table table-striped table-bordered table-hover" cellspacing="0" width="100%"
    datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger">
    <thead>
      <tr>
        <th>Logger Name</th>
        <th>Progress</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let download of downloadData$">
        <td>{{ download.logger.name }}</td>
        <td [attr.data-order]="download.progress"><progress [attr.value]="download.progress" max="100"></progress>
          {{ download.progress }}%</td>
      </tr>
    </tbody>
  </table>
</div>

4 个答案:

答案 0 :(得分:1)

您必须先销毁表格并重新渲染。您可以参阅文章here。 如果将来会禁用链接,则为代码段。

rerender(): void {
this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
  // Destroy the table first
  dtInstance.destroy();
  // Call the dtTrigger to rerender again
  this.dtTrigger.next();
});
}

另一种解决方案如所讨论的here

让我知道此解决方案是否有效,或者您有任何疑问。

答案 1 :(得分:0)

我尝试了一下,这种行为非常奇怪,它默认恢复为原始值。这不是代码的问题,而是angular-datatable库的问题。

同时使用

降级到angular-datatables@6.0.0

npm install --save angular-datatables@6.0.0 要么 yarn add angular-datatables@6.0.0

我尝试了一下,效果很好。

答案 2 :(得分:0)

我有同样的问题。从我的数据更新方法回调后调用dtTrigger解决了该问题:

rerender(): void {
  this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => { 

    // Destroy the table first
    dtInstance.destroy();

    //reload your data
    this.reloadDataMethod(()=>{

       // Call the dtTrigger to rerender **after callback**
       this.dtTrigger.next();

    })
  });
 }

答案 3 :(得分:0)

当您尝试对 angular-datatables 进行渲染时,我做了一个示例,说明它如何正常工作。它适用于Angular 9。 您必须使用ChangeDetectorRef,因为提供更改检测功能的基类。更改检测树收集所有要检查更改的视图。使用这些方法可以在树中添加和删除视图,启动更改检测以及将视图明确标记为脏视图,这意味着它们已经更改并且需要重新呈现。 签出:https://angular.io/api/core/ChangeDetectorRef

stuff.html

<table 
    datatable
    *ngIf="myData.length" 
    [dtOptions]="dtOptions"
    [dtTrigger]="dtTrigger"
    class="table table-bordered table-striped"
>
    <thead>
        <tr>
            <th> Stuff1 </th>
            <th> Stuff2 </th>
            <th> Stuff3 </th>
            <th> Stuff4 </th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let data of myData">
            <td> {{ data.stuff1 }} </td>
            <td> {{ data.stuff2 }} </td>
            <td> {{ data.stuff3 }} </td>
            <td> {{ data.stuff4 }} °C </td>
        </tr>
    </tbody>
</table>

stuff.ts

@Component({
    selector: 'app-stuff',
    templateUrl: './stuff.component.html'
})
export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
    @ViewChild(DataTableDirective) datatableElement: DataTableDirective;

    public dtOptions: DataTables.Settings = {};
    public dtTrigger: Subject<any> = new Subject();

    constructor(
       private readonly chRef: ChangeDetectorRef,
       private readonly stuffService: StuffService
    ) { }

    ngOnInit() {
        this.stuffService.list().subscribe(response => {
            this.myData = response;
            //put this line before call dtTrigger
            this.chRef.detectChanges();
            this.dtTrigger.next();
        });
    }

    ngOnDestroy() {
        this.dtTrigger.unsubscribe();
    }

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

    public rerender() {
        this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
            dtInstance.destroy();

            this.stuffService.list().subscribe(response => {
                this.myData = response;
                this.dtTrigger.next();
            });
        });
    }
}