プログラマ探偵の事件簿:DataTablesで列の数を変更するとUnhandled Promise Rejection: TypeError: undefined is not an object (evaluating 'headerCells[i].style')
新人助手の猫さんがやってきて1ヶ月半、仕事に慣れてきたころの事件である。
事件の始まり
シン・TWSNMPのMIBブラウザーを改善しようとしていた時のことである。MIBを取得していると謎のハングアップが発生することに気付いた。
猫のアニメが表示されたままになってしまう。ブラウザーの開発者ツールで見ると
Unhandled Promise Rejection: TypeError: undefined is not an object (evaluating 'headerCells[i].style')
のエラーである。何となくテーブルの列に関係していそうであった。
テーブルの列数が変わった時に発生する
発生する条件を探るために試行錯誤していると、どうやらMIBを表示するためのテーブルの列数が変わった時に発生するようである。
のような3列のMIBを表示した後、
4列あるMIBを表示するような場合や、その逆である。
テーブルの列数が変わらない時は発生しない。
謎を解く鍵はDataTablesの削除にあった
MIBを表示するテーブルは DataTables
を使って表示している。MIBを取得する毎にテーブルを再作成するようにしている。
const showTable = () => {
if (table && DataTable.isDataTable("#mibTable")) {
table.clear();
table.destroy();
table = undefined;
}
table = new DataTable("#mibTable", {
columns: columns,
data: data,
language: getTableLang(),
select: {
style: "single",
},
});
前に表示したテーブルがあれば、削除してから再度作成するような仕組みである。ソースコード上も、そういう動作に見える。しかし、実際はそうではなかった。亡霊のようにテーブルは残っていて列の数を変えると悪さをするのである。
table.destroy()では消えない
table.destroy()でテーブルがなくなると信じていたが、消えてはいなかったのだ!!
DataTables のマニュアルを読むとtable.destroy(true)という方法を見つけた。試してみるとテーブルの亡霊は消えるが2回目にテーブルが作成できない別の問題が発生した。
ここから、テーブルを消す方法を探すための長い試行錯誤が始まった。いつものようにGoogleさんから教えてもらった方法をいろいろ試すがテーブルの亡霊は消えない。テーブル全部ではなく、列だけ変更する方法も調べたが、それもできなないようである。テーブルを削除して作り直す方法が見つかり振り出しに戻る。諦めて寝ることにした。
table.destroy(true)でリベンジ
朝起きて、新人助手の猫さんが私の部屋までやって来て
「がんばって、昨日の問題を解決するのよ!」
と言った。
table.destroy(true) に再挑戦することにした。
table.destroy(true) の動作を観察するとテーブルを表示したいところ書いた
<table id="mibTable" class="display compact" style="width:99%" />
がテーブルを作成した時点でなくなっていることに気づいた。2回目に作成する時にはテーブルを作成する場所がなくなっているためにテーブルが表示されなくなる。作成する場所も再作成すればいけそうな気がした。
<div id="table">
<table id="mibTable" class="display compact" style="width:99%" />
</div>
消えない大元の場所の中に、消えてもよいテーブルの場所を作って
if (table && DataTable.isDataTable("#mibTable")) {
table.clear();
table.destroy(true);
table = undefined;
const e = document.getElementById("table");
if(e) {
e.innerHTML = `<table id="mibTable" class="display compact" style="width:99%" />`;
}
}
table = new DataTable("#mibTable", {
columns: columns,
data: data,
language: getTableLang(),
select: {
style: "single",
},
});
のようにテーブルを作成する場所も再作成するようにして解決した。
「消したと思っても亡霊のように悪さをするオブジェクトもある!」
と先代の助手の猫が天から言っている。
開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。