使用 Angular 数据表作为共享组件时出现的问题
Issues when using Angular Datatables as a shared component
我将数据表用作一个组件,这样我就可以在我拥有的所有模板中使用它。我有以下文件:
table.component.ts
import * as _ from "lodash";
import { Observable, Subject, merge } from 'rxjs';
import { Component, OnInit, ViewChild, Renderer2, Input, Output, EventEmitter, ContentChild, ElementRef } from "@angular/core";
import { DataTableDirective } from "angular-datatables";
import { TableActionEvent } from "../../types/table/table.actions";
@Component({
selector: "common-table",
templateUrl: "./table.component.html",
styleUrls: ["./table.component.scss"],
})
export class TableComponent implements OnInit {
public dtOptions: DataTables.Settings = {};
public dtTrigger: Subject<any> = new Subject();
public _data: Array<any>;
public _settings: any;
public _loading: boolean;
@ViewChild(DataTableDirective, { static: false }) private datatableElement: DataTableDirective;
/**
* Grid data with pagination meta
*/
@Input()
set data(data: any) {
if (data) {
this._data = data;
}
}
get data(): any {
return this._data;
}
/**
* Grid data with pagination meta
*/
@Input()
set settings(data: any) {
if (data) {
this._settings = data;
}
}
get settings(): any {
return this._settings;
}
@Input()
set loading(loading: boolean) {
this._loading = loading;
setTimeout(() => {
$('#releaseDatatable').DataTable().destroy();
this.dtTrigger.next();
}, 100);
}
get loading(): boolean {
return this._loading;
}
@Output() public event: EventEmitter<TableActionEvent<any>> = new EventEmitter<TableActionEvent<any>>();
/**
* DashboardComponent constructor
*/
constructor(
private renderer: Renderer2,
private elem: ElementRef
) { }
/**
* @memberof DashboardComponent
*/
public ngOnInit(): void {
this.dtOptions = {
info: false,
order: []
};
}
/**
*
*/
cellRender(render, row) {
if (_.isString(render)) {
return render;
}
if (_.isFunction(render)) {
return render(row);
}
}
/**
* @param $event
*/
public search($event) {
const term = $event.target.value;
this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
dtInstance.search(term).draw();
});
}
/**
* On Table Action
*
* @param {string} action
* @param {T} row
* @param {number} index
*
* @memberof AdminGridComponent
*/
public onAction(action: string, row: any): void {
const tableActionItem: any = {
action: action,
row: row
};
this.event.emit(tableActionItem);
}
rerender() {
this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
dtInstance.destroy();
this.dtTrigger.next();
});
}
ngAfterViewInit(): void {
this.dtTrigger.next();
}
ngOnDestroy(): void {
// Do not forget to unsubscribe the event
this.dtTrigger.unsubscribe();
}
}
模板文件table.component.html如下所示:
<div class="ma-datatables">
<form>
<div class="d-flex align-items-center app-login_input-layout">
<input class="form-control app-login_input-style rm-release_search-bar" type="search" id="release-search"
placeholder="Search here..." (keyup)=search($event)>
<i class="material-icons rm-release_search-icon">search</i>
</div>
</form>
<div class="table-responsive">
<div *ngIf="!loading">
<table class="table animate__animated animate__fadeIn" id="releaseDatatable" datatable
[dtOptions]="dtOptions" [dtTrigger]="dtTrigger">
<thead>
<tr>
<th *ngFor="let header of settings.columns">{{ header.title }}</th>
<th *ngIf="settings.actions">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let release of data">
<ng-container *ngFor="let column of settings.columns">
<td class="rm-release_table-cell" [style.width]=column.width>
<div>
<p *ngIf="column.dataType !='html'" class="rm-release_data-id">
{{release[column.field]}}
</p>
<span *ngIf="column.dataType =='html'">
<div innerHTML="{{ cellRender(column.render, release) }}"></div>
</span>
</div>
</td>
</ng-container>
<td class="rm-release_table-cell" *ngIf="settings.actions">
<div>
<a id="release-action" href="javascript:void(0)" (click)="openAction($event)">
<i class="material-icons">more_vert</i>
</a>
<div class="rm-release_action-layout hidden" #actionSlide
id="release-{{release[settings.columns[0].field]}}">
<div class="rm-release_action-container animate__animated" #actionContainer>
<div
class="d-flex align-items-center justify-content-between rm-release_action-header">
<a class="rm-release_action-close" href="javascript:void(0)"
(click)="closeAction($event)">
<i class="material-icons">close</i>
</a>
</div>
<div class="rm-release_action-item-layout">
<div class="rm-release_action-item-layout">
<ng-container *ngIf="release.permitted_actions;else actionMenu">
<ng-container *ngFor="let action of settings.actions">
<div *ngIf="release.permitted_actions.includes(action.action)"
class="d-flex align-items-center rm-release_action-item"
(click)="onAction(action.action, release)">
<i class="material-icons">{{action.icon}}</i>
<p>{{action.title}}</p>
</div>
</ng-container>
</ng-container>
<ng-template #actionMenu>
<ng-container *ngFor="let action of settings.actions">
<div class="d-flex align-items-center rm-release_action-item"
(click)="onAction(action.action, release)">
<i class="material-icons">{{action.icon}}</i>
<p>{{action.title}}</p>
</div>
</ng-container>
</ng-template>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
我正在使用这个组件,如下所示:
<common-table [data]="items" [settings]="settings" [loading]="isLoading"
(event)="onGridEvent($event)">
</common-table>
现在我面临着多个问题:
有时显示No data available in table
,但当
页面刷新了,就没了
有时显示
DataTables warning: table id=releaseDatatable - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3"
如果有人能帮我解决这个问题,那将非常有帮助。我正在使用 Angular Datatables 包。
好像是两个不同的问题;
第二个错误DataTables warning: table id=releaseDatatable - Cannot reinitialise DataTable
表示您使用了多个具有相同id的dataTable。
当您加载多个 dataTable 组件时,很可能会遇到此错误。
要解决这个问题,您应该生成一种识别每个唯一数据的方法 table 例如,声明一个变量计数器并在获取数据表时调用 $('#releaseDatatable' + counter).DataTable().destroy();
,同时绑定到 [attr.id]='"releaseDatatable" + counter'
html
第一个错误将归因于下面的代码
$('#releaseDatatable').DataTable().destroy();
this.dtTrigger.next();
考虑上面的问题 2,您在其中加载具有相同 ID 的相同 HTMLElement。在你销毁元素然后调用 this.dtTrigger.next();
没有元素将存在因此错误 No data available in table
为数据表设置唯一 ID 应该可以解决这两个问题
我将数据表用作一个组件,这样我就可以在我拥有的所有模板中使用它。我有以下文件:
table.component.ts
import * as _ from "lodash";
import { Observable, Subject, merge } from 'rxjs';
import { Component, OnInit, ViewChild, Renderer2, Input, Output, EventEmitter, ContentChild, ElementRef } from "@angular/core";
import { DataTableDirective } from "angular-datatables";
import { TableActionEvent } from "../../types/table/table.actions";
@Component({
selector: "common-table",
templateUrl: "./table.component.html",
styleUrls: ["./table.component.scss"],
})
export class TableComponent implements OnInit {
public dtOptions: DataTables.Settings = {};
public dtTrigger: Subject<any> = new Subject();
public _data: Array<any>;
public _settings: any;
public _loading: boolean;
@ViewChild(DataTableDirective, { static: false }) private datatableElement: DataTableDirective;
/**
* Grid data with pagination meta
*/
@Input()
set data(data: any) {
if (data) {
this._data = data;
}
}
get data(): any {
return this._data;
}
/**
* Grid data with pagination meta
*/
@Input()
set settings(data: any) {
if (data) {
this._settings = data;
}
}
get settings(): any {
return this._settings;
}
@Input()
set loading(loading: boolean) {
this._loading = loading;
setTimeout(() => {
$('#releaseDatatable').DataTable().destroy();
this.dtTrigger.next();
}, 100);
}
get loading(): boolean {
return this._loading;
}
@Output() public event: EventEmitter<TableActionEvent<any>> = new EventEmitter<TableActionEvent<any>>();
/**
* DashboardComponent constructor
*/
constructor(
private renderer: Renderer2,
private elem: ElementRef
) { }
/**
* @memberof DashboardComponent
*/
public ngOnInit(): void {
this.dtOptions = {
info: false,
order: []
};
}
/**
*
*/
cellRender(render, row) {
if (_.isString(render)) {
return render;
}
if (_.isFunction(render)) {
return render(row);
}
}
/**
* @param $event
*/
public search($event) {
const term = $event.target.value;
this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
dtInstance.search(term).draw();
});
}
/**
* On Table Action
*
* @param {string} action
* @param {T} row
* @param {number} index
*
* @memberof AdminGridComponent
*/
public onAction(action: string, row: any): void {
const tableActionItem: any = {
action: action,
row: row
};
this.event.emit(tableActionItem);
}
rerender() {
this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
dtInstance.destroy();
this.dtTrigger.next();
});
}
ngAfterViewInit(): void {
this.dtTrigger.next();
}
ngOnDestroy(): void {
// Do not forget to unsubscribe the event
this.dtTrigger.unsubscribe();
}
}
模板文件table.component.html如下所示:
<div class="ma-datatables">
<form>
<div class="d-flex align-items-center app-login_input-layout">
<input class="form-control app-login_input-style rm-release_search-bar" type="search" id="release-search"
placeholder="Search here..." (keyup)=search($event)>
<i class="material-icons rm-release_search-icon">search</i>
</div>
</form>
<div class="table-responsive">
<div *ngIf="!loading">
<table class="table animate__animated animate__fadeIn" id="releaseDatatable" datatable
[dtOptions]="dtOptions" [dtTrigger]="dtTrigger">
<thead>
<tr>
<th *ngFor="let header of settings.columns">{{ header.title }}</th>
<th *ngIf="settings.actions">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let release of data">
<ng-container *ngFor="let column of settings.columns">
<td class="rm-release_table-cell" [style.width]=column.width>
<div>
<p *ngIf="column.dataType !='html'" class="rm-release_data-id">
{{release[column.field]}}
</p>
<span *ngIf="column.dataType =='html'">
<div innerHTML="{{ cellRender(column.render, release) }}"></div>
</span>
</div>
</td>
</ng-container>
<td class="rm-release_table-cell" *ngIf="settings.actions">
<div>
<a id="release-action" href="javascript:void(0)" (click)="openAction($event)">
<i class="material-icons">more_vert</i>
</a>
<div class="rm-release_action-layout hidden" #actionSlide
id="release-{{release[settings.columns[0].field]}}">
<div class="rm-release_action-container animate__animated" #actionContainer>
<div
class="d-flex align-items-center justify-content-between rm-release_action-header">
<a class="rm-release_action-close" href="javascript:void(0)"
(click)="closeAction($event)">
<i class="material-icons">close</i>
</a>
</div>
<div class="rm-release_action-item-layout">
<div class="rm-release_action-item-layout">
<ng-container *ngIf="release.permitted_actions;else actionMenu">
<ng-container *ngFor="let action of settings.actions">
<div *ngIf="release.permitted_actions.includes(action.action)"
class="d-flex align-items-center rm-release_action-item"
(click)="onAction(action.action, release)">
<i class="material-icons">{{action.icon}}</i>
<p>{{action.title}}</p>
</div>
</ng-container>
</ng-container>
<ng-template #actionMenu>
<ng-container *ngFor="let action of settings.actions">
<div class="d-flex align-items-center rm-release_action-item"
(click)="onAction(action.action, release)">
<i class="material-icons">{{action.icon}}</i>
<p>{{action.title}}</p>
</div>
</ng-container>
</ng-template>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
我正在使用这个组件,如下所示:
<common-table [data]="items" [settings]="settings" [loading]="isLoading"
(event)="onGridEvent($event)">
</common-table>
现在我面临着多个问题:
有时显示
No data available in table
,但当 页面刷新了,就没了有时显示
DataTables warning: table id=releaseDatatable - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3"
如果有人能帮我解决这个问题,那将非常有帮助。我正在使用 Angular Datatables 包。
好像是两个不同的问题;
第二个错误DataTables warning: table id=releaseDatatable - Cannot reinitialise DataTable
表示您使用了多个具有相同id的dataTable。
当您加载多个 dataTable 组件时,很可能会遇到此错误。
要解决这个问题,您应该生成一种识别每个唯一数据的方法 table 例如,声明一个变量计数器并在获取数据表时调用 $('#releaseDatatable' + counter).DataTable().destroy();
,同时绑定到 [attr.id]='"releaseDatatable" + counter'
html
第一个错误将归因于下面的代码
$('#releaseDatatable').DataTable().destroy();
this.dtTrigger.next();
考虑上面的问题 2,您在其中加载具有相同 ID 的相同 HTMLElement。在你销毁元素然后调用 this.dtTrigger.next();
没有元素将存在因此错误 No data available in table
为数据表设置唯一 ID 应该可以解决这两个问题