Angular - Datatables:TypeError:无法读取null的属性'nodeName'
这一个很棘手,我会尽我所能地尽力解释自己。Angular - Datatables:TypeError:无法读取null的属性'nodeName'
简要说明:
我有数据表库集成在我的角度项目,有它,因为我几个月前购买了该项目的主题。主题已更新,因此我用最新版本继续更新了我的项目。
奇怪的是,什么不工作是DataTables和DataTables没有改变!
代码故障:
从X组件我触发我的共享服务IBOsService
的方法。
当触发此方法时,我的DatatableComponent
导入Promise
中的数据表库。
直到现在,从来没有这个问题。
在DatatableComponent
:
this.tablesService.initTableData$.subscribe(() => {
if (!this.datatableInitialized) {
log.info('Starting script import promise');
Promise.all([
System.import('script-loader!my-plugins/datatables-bundle/datatables.min.js')
]).then(values => {
log.data('success', JSON.stringify(values));
this.render();
}, reason => {
log.error('error', JSON.stringify(reason));
});
}
}
);
在我的控制台我看到:DataTables success [{}]
。因此,我明白这个承诺就是成功。
那么我们再输入this.render();
的方法。
的方法一直持续到这条线的位置:
const _dataTable = element.DataTable(options);
的事情是,在我的IDE,我可以浏览到所有变量,方法,等等......但我不能浏览到DataTable()
,因此我猜测只是不认识这种方法,这就是为什么它会抛出错误。
但,因为脚本在加载的承诺,是正常的IDE不具备的数据表方法的映射......
全部组件代码:
import { Component, Input, ElementRef, AfterContentInit, OnInit, Injectable, OnDestroy } from '@angular/core';
import { IBOsService } from '../../../+ibos/ibos.service';
import { Subscription } from 'rxjs/Subscription';
import { Log, Level } from 'ng2-logger';
import { logConfig } from '../../../../environments/log_config';
const log = Log.create('DataTables');
log.color = logConfig.dataTable;
declare let $: any;
@Component({
selector: 'sa-datatable',
template: `
<table class="dataTable {{tableClass}}" width="{{width}}">
<ng-content></ng-content>
</table>
`,
styles: [
require('my-plugins/datatables-bundle/datatables.min.css')
]
})
@Injectable()
export class DatatableComponent implements OnInit, OnDestroy {
@Input() public options: any;
@Input() public filter: any;
@Input() public detailsFormat: any;
@Input() public paginationLength: boolean;
@Input() public columnsHide: boolean;
@Input() public tableClass: string;
@Input() public width = '100%';
public datatableInitialized: boolean;
public subscription: Subscription;
constructor(private el: ElementRef, private tablesService: IBOsService) {
this.tablesService.refreshTable$.subscribe((tableParams) => {
this.filterData(tableParams);
}
);
this.tablesService.initTableData$.subscribe(() => {
if (!this.datatableInitialized) {
log.info('Starting script import promise');
Promise.all([
System.import('script-loader!my-plugins/datatables-bundle/datatables.min.js')
]).then(values => {
log.data('success', JSON.stringify(values));
this.render();
}, reason => {
log.error('error', JSON.stringify(reason));
});
}
}
);
}
ngOnInit() {
}
render() {
log.info('Starting render!');
const element = $(this.el.nativeElement.children[0]);
let options = this.options || {};
log.info('1 render!');
let toolbar = '';
if (options.buttons) {
toolbar += 'B';
}
log.info('2 render!');
if (this.paginationLength) {
toolbar += 'l';
}
if (this.columnsHide) {
toolbar += 'C';
}
log.info('3 render!');
if (typeof options.ajax === 'string') {
const url = options.ajax;
options.ajax = {
url: url,
// complete: function (xhr) {
//
// }
};
}
log.info('4 render!');
options = $.extend(options, {
'dom': '<\'dt-toolbar\'<\'col-xs-12 col-sm-6\'f><\'col-sm-6 col-xs-12 hidden-xs text-right\'' + toolbar + '>r>' +
't' +
'<\'dt-toolbar-footer\'<\'col-sm-6 col-xs-12 hidden-xs\'i><\'col-xs-12 col-sm-6\'p>>',
oLanguage: {
'sSearch': `<span class='input-group-addon'><i class='glyphicon glyphicon-search'></i></span>`,
'sLengthMenu': '_MENU_'
},
'autoWidth': false,
retrieve: true,
responsive: true,
initComplete: (settings, json) => {
element.parent()
.find('.input-sm')
.removeClass('input-sm')
.addClass('input-md');
}
});
log.info('5 render! element', JSON.stringify(element));
log.info('5.1 render! options', JSON.stringify(options));
const _dataTable = element.DataTable(options);
log.info('5.2 render! _dataTable', JSON.stringify(_dataTable));
if (this.filter) {
// Apply the filter
element.on('keyup change', 'thead th input[type=text]', function() {
console.log('searching?');
_dataTable
.column($(this).parent().index() + ':visible')
.search(this.value)
.draw();
});
}
log.info('6 render!');
if (!toolbar) {
element.parent().find('.dt-toolbar')
.append(
'<div class="text-right">' +
'<img src="assets/img/logo.png" alt="SmartAdmin" style="width: 111px; margin-top: 3px; margin-right: 10px;">' +
'</div>'
);
}
log.info('7 render!');
if (this.detailsFormat) {
const format = this.detailsFormat;
element.on('click', 'td.details-control', function() {
const tr = $(this).closest('tr');
const row = _dataTable.row(tr);
if (row.child.isShown()) {
row.child.hide();
tr.removeClass('shown');
} else {
row.child(format(row.data())).show();
tr.addClass('shown');
}
});
}
log.info('8 render!');
this.datatableInitialized = true;
}
filterData(tableParams) {
console.log('reloading DT... With these parameters: ' + JSON.stringify(tableParams));
const element = $(this.el.nativeElement.children[0]);
const table = element.find('table.dataTable');
log.data('current table element is: ', JSON.stringify(table));
Object.keys(tableParams).forEach(function (key) {
log.warn('current key: ', JSON.stringify(key));
table.DataTable().column(`${key}:name`).visible(tableParams[key]);
});
table.DataTable().ajax.reload();
}
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}
你会看到我用日志侵入了组件,它帮助我了解组件在哪里失败。
完全控制台登录:
有趣的信息:
如果我称之为filterData(tableParams)
方法... DataTable中呈现,没有任何问题。
这告诉我两件事情:
-
DataTable()
不是问题。 - 这个问题只在第一次渲染,然后,在更新时,我没有遇到任何问题。
我为我的文字的墙非常抱歉......但我做了一些福尔摩斯由我自己,无法找到解决方案。
如果你需要澄清或更多的细节让我知道。
在此先感谢!
更新:
调试天后,我发现错误的可能来源:
的事情是,s
是null
。
也许有人对DataTables有更多的经验或遇到这个问题可能会给我提示发生了什么。
我会在这里调试...;)
更新2:
经过调试,我发现,数据表不使第一Ajax调用。
我正在使用服务器端数据表,在POST中使用Ajax调用。
这里是我的options
对象的代码:
this.options = {
dom: 'Bfrtip',
processing: true,
serverSide: true,
pageLength: 20,
searchDelay: 1200,
ajax: {
url: this.jsonApiService.buildURL('/test_getUsers.php', 'remote'),
type: 'POST',
data: function (d) {
Object.assign(d, IBOsTable.params);
log.data('DT options obj. New params are: ', JSON.stringify(IBOsTable.params));
return d;
}
},
columns: this.initColumns,
};
这不是让Ajax调用在初始化,但它使得它table.DataTable().ajax.reload();
。
这告诉我,代码不是不正确或损坏(上reload()
作品就像一个魅力)...
我还没有完全undesrtanding为什么这个数据表的初始化是不工作...但是,我相信我已经够接近了!
我终于找到了错误的来源!
如果你看过我的更新你会发现我想通了,我的数据表并没有使第一Ajax调用,但reload()
是完美的工作:
这是因为在初始化JavaScript错误不允许进行Ajax调用。提示:TypeError:无法读取空值的属性'nodeName'。
speaking to Allan (from DataTables)之后,他给我提示错误可能是由于thead
的列数不等于tbody
的列数引起的。
所以我查了一下.html,发现我有一些空的<thead>
和<tfoot>
标签。我评论他们......并且工作!
我已经跑了个遍每一个可能的解决方案:
- 依赖
- 实例化的数据表服务器端
- 的角2应用
- 许多不同的方式中的jQuery库在代码中改变方法:TypeScript,jQuery,Ng2等...
最后,我只需要清除我的DataTable加载到的div,以避免此问题。
有趣的事实:随着该.HTML我的应用程序工作了3/4个月,没有任何问题,用数据表没有问题到现在为止...
如果是S定义?我没有看到该代码 – Bindrid
@Bindrid嗨! 's'不是行列式。我发现我的DT没有进行第一次Ajax调用,因此没有实际的数据进行渲染,这就是错误发生的原因。这里的问题是找出为什么不做第一个Ajax调用。干杯! ;) – SrAxi