【问题标题】:Cannot reinitialise DataTable with Angular Datatable无法使用 Angular Datatable 重新初始化 DataTable
【发布时间】:2019-11-07 00:02:25
【问题描述】:

我有一个带有简单 CRUD 功能的 Angular 应用程序。我已经用静态 HTML 表测试了我的数据,这很有效。现在我正在使用一个名为 Angular 数据表的数据表框架。

链接:https://l-lin.github.io/angular-datatables/#/welcome

我可以创建读取删除记录,但执行此操作后我收到如下错误:

DataTables 警告:表 id=DataTables_Table_0 - 无法重新初始化 数据表。有关此错误的更多信息,请参阅 http://datatables.net/tn/3

我尝试了几种解决方案,例如它提供的链接和其他堆栈溢出帖子,如下所示:

Getting error in Angular 5 Datatables: cannot reinitialise DataTable

https://l-lin.github.io/angular-datatables/#/basic/angular-way

https://l-lin.github.io/angular-datatables/#/advanced/rerender

这是我在 car-component.js 中的代码,我使用 car-services.js 进行所有 HTTP 调用。

import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { CarService } from '../services/carservices/car.service';
import { CarVM } from '../viewmodels/car/car-vm';
import { Subject } from 'rxjs';
import { DataTableDirective } from 'angular-datatables';

@Component({
  selector: 'app-car',
  templateUrl: './car.component.html',
  styleUrls: ['./car.component.css']
})
export class CarComponent implements OnInit {

  FormCar: any;
  countrecords: any;
  Carid: number = 0;
  dtTrigger: Subject<any> = new Subject();
  dtElement: DataTableDirective;
  allCars: CarVM[];
  dtOptions: DataTables.Settings = {};

  constructor(private formbuilder: FormBuilder, private carservice: CarService) { }

  ngOnInit() {

    this.dtOptions = {
      pagingType: 'full_numbers',
      pageLength: 5,
    };

    this.GetCar();
    this.GetCarCount();

    this.FormCar = this.formbuilder.group({
      CarId: ['', Validators.required],
      Brand: ['', Validators.required],
      Model: ['', Validators.required],
      Color: ['', Validators.required],
      TopSpeed: ['', Validators.required],
    });
  }

  AddCar(CarVM: CarVM) {
    CarVM.CarId = this.Carid;
    this.carservice.CreateCar(CarVM).subscribe(() => {
      this.GetCar();
      this.GetCarCount();
      this.Reset();
      this.Carid = 0;
    })
  }

  GetCar() {
    this.carservice.getAllCars().subscribe(res => {
      this.allCars = res;
      this.dtTrigger.next();
    })
  }

  GetCarCount() {
    this.countrecords = this.carservice.getCount();
  }

  EditCar(car: CarVM) {
    this.carservice.updateCar(car).subscribe(Response => {
      this.Carid = Response.CarId;
      this.FormCar.controls['Brand'].setValue(Response.Brand);
      this.FormCar.controls['Model'].setValue(Response.Model);
      this.FormCar.controls['Color'].setValue(Response.Color);
      this.FormCar.controls['TopSpeed'].setValue(Response.TopSpeed);
    })
  }

  DeleteCar(CarId: string) {
    if (confirm("Are you sure?")) {
      this.carservice.deleteCar(CarId).subscribe(() => {
        this.GetCar();
        this.GetCarCount();
      })
    }
  }

  Reset() {
    this.FormCar.reset();
  }
}

这是我的汽车 HTML 页面:

<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="row-border hover">
  <thead>
    <tr>
      <th>Id</th>
      <th>Brand</th>
      <th>Model</th>
      <th>Color</th>
      <th>Speed</th>
      <th>Action</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let car of allCars">
      <td>{{car.carId}}</td>
      <td>{{car.brand}}</td>
      <td>{{car.model}}</td>
      <td>{{car.color}}</td>
      <td>{{car.topSpeed }}</td>
      <td>
        <button type="button" class="btn btn-danger mr-1" (click)="DeleteCar(car.carId)">Delete</button>
      </td>
    </tr>
  </tbody>
</table>

注意:

我使用的是 Angular 版本而不是 JQuery 版本!

有人能指出正确的方向吗?

【问题讨论】:

    标签: jquery html angular typescript datatable


    【解决方案1】:

    您需要在再次触发之前销毁数据表实例。

    你可以像这样创建一个函数:

    import { DataTableDirective } from 'angular-datatables';

    dtElement: DataTableDirective;

    isDtInitialized:boolean = false

      GetCar() {
        this.carservice.getAllCars().subscribe(res => {
          this.allCars = res;
    
          if (this.isDtInitialized) {
            this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
              dtInstance.destroy();
              this.dtTrigger.next();
            });
          } else {
            this.isDtInitialized = true
            this.dtTrigger.next();
          }
        })
      }
    

    使用这个,第一次会去else块直接触发datatable。之后刷新时会先销毁数据表再触发。

    【讨论】:

    • 感谢您的宝贵时间!我需要在我的构造函数中调用这个函数吗?
    • 编辑了答案,在 getCar() 中进行
    • 我初始化了布尔变量并使用了你的方法。然后我在 ngOnInit() this.getCar(); 上调用它,当我刷新时我会立即收到相同的错误。单击确定后,我的数据正在加载。
    • 请在评论中显示您的功能,或者如果您可以创建一个 stackbiltz 更好。我遇到过同样的事情并通过销毁 dtInstance 来修复它
    • 删除行`this.dtTrigger.next();`后的行`this.allCars = res;`,GetCar()中的第3行
    【解决方案2】:

    上面的答案@Adrita Sharma 对我不起作用,它抛出了这个错误。

    core.js:9110 错误类型错误:无法读取属性“dtInstance” 未定义

    所以我加了

    @ViewChild(DataTableDirective, {static: false})
    

    成功了

    import { Component, ViewChild, OnInit } from '@angular/core';
    import { DataTableDirective } from 'angular-datatables';
    
    export class AttendancePage implements OnInit {
    
    @ViewChild(DataTableDirective, {static: false})
    dtElement: DataTableDirective;
    
    isDtInitialized:boolean = false;
    

    在我初始化数据表的函数内部

    if (this.isDtInitialized) {
        this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
            dtInstance.destroy();
            this.dtTrigger.next();
        });
    } else {
        this.isDtInitialized = true;
        this.dtTrigger.next();
    }
    

    【讨论】:

      【解决方案3】:

      HTML

      <div class="table-responsive">
                                                  <table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" 
                                                      style="width: 99.5% !important;" class="table table-responsive-sm table-bordered table-striped table-sm">
                                                  <thead>
                                                      <tr>
                                                      <th>Client ID</th>
                                                      <th>Client Name</th>
                                                      <th>Client Phone</th>
                                                      <th>Join Date</th>
                                                      <th>Email</th>
                                                      <th>Is Active</th>
                                                      <th>Operation</th>
                                                      </tr>
                                                  </thead>
                                                  <tbody *ngIf="modelList && modelList?.length != 0">
                                                      <tr *ngFor="let m of modelList">
                                                      <td>{{ m.ClientID }}</td>
                                                      <td>{{ m.ClientName }}</td>
                                                      <td>{{ m.ClientPhone }}</td>
                                                      <td>{{ m.JoinDate | date : "MMM d, y" }}</td>
                                                      <td>{{ m.Email}}</td>
                                                      <td>
                                                              <div class="btn-group project-list-ad" *ngIf="m.IsActive">
                                                                      <button class="btn btn-white btn-xs">Active</button>
                                                              </div>
      
                                                              <div class="btn-group project-list-ad-rd" *ngIf="!m.IsActive">
                                                                      <button class="btn btn-white btn-xs">Unactive</button>
                                                              </div>
                                                      </td>
                                                      <td>
                                                          <button class="btn btn-pill btn-dark" type="button" (click)='editbuttonClick(m.ClientID)'>
                                                          <i class="fa fa-file-o fa-sm mt-1"></i>&nbsp;Edit
                                                          </button>
                                                      </td>
                                                      </tr>
                                                  </tbody>
                                                  <tbody *ngIf="!modelList || modelList?.length == 0">
                                                      <tr>
                                                      <td colspan="3" class="no-data-available">No data!</td>
                                                      </tr>
                                                  <tbody>
                                                  </table>
                                              </div>
      

      键入脚本代码 对于 Angular 8

      @ViewChild(DataTableDirective, {static : false})
      dtElement: DataTableDirective;
      
      dtOptions: DataTables.Settings = {};
      dtTrigger: Subject<ClientList> = new Subject();
      

      在类上实现 AfterViewInit

      loadAllData() {
      
      const that = this;
      
      
      this.dtOptions = {
        pagingType: 'full_numbers',
        pageLength: 10,
        serverSide: true,
        processing: true,
        ajax: (dataTablesParameters: any, callback) => {
          that._http
            .post<DataTablesResponse>(
              //'https://angular-datatables-demo-server.herokuapp.com/',
              this.env.apiUrl + 'api/setup/ClientList_SelectAll_Grid',
              dataTablesParameters, {}
            ).subscribe(resp => {
              //console.log(dataTablesParameters);
              that.modelList = resp.data;
      
      
              callback({
                recordsTotal: resp.recordsTotal,
                recordsFiltered: resp.recordsFiltered,
                data: []
              });
            });
        },
        columns: [{ data: 'ClientID' }, { data: 'ClientName' }, { data: 'ClientPhone' }, { data: 'JoinDate' }, { data: 'Email' }, { data: 'IsActive' }, { defaultContent: '', orderable: false }]
      };
      
      
      
       }
      
       ngAfterViewInit(): void {
          this.dtTrigger.next();
       }
      
      
      
       rerender(): void {
      
      this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
        // Destroy the table first
        dtInstance.destroy();
        // Call the dtTrigger to rerender again
        this.dtTrigger.next();
      });
      
      
      }
      

      full example of Angular DataTables Server side pagination & Sorting

      【讨论】:

      • 调用渲染函数时,添加新数据后,只显示最后添加的记录。不显示所有记录。你能帮忙吗?如何修复以显示所有记录,包括新添加的记录。 -- 谢谢
      • 我成功修复了它。感谢您的回复。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-09
      • 2021-10-05
      • 1970-01-01
      • 2015-11-04
      • 2015-05-30
      • 1970-01-01
      相关资源
      最近更新 更多