下記のKviewer プラグインコードで、subTable中のカラムを条件付きで非表示にしようとしたら、何んだか 良く解らないタイミングで、上手く非表示にできたり、非表示にできなかったりして、動作が不安定になっています。
特に、kv.events.record.mountedイベントハンドラの中で、setTimeout関数を使って、dom更新処理を遅延させないと、非表示にしようとした<td>タグ部のstyleが「style="padding: 1em;"」というkviewerのレコード詳細画面の設定として指定していた値に上書きされてしまって、非表示とならない頻度が 高まります。
それは、多分、kv.events.record.mountedイベントの公式ドキュメントに記載されていた「※内部的に状態は変更されますが、DOMに変更が反映されない場合があります。」というのに 関連するのだろうと思います。
もっと 確実に、KviewerのsubTable中のカラムを条件付きで非表示にできる方法を、教示 いただけないでしょうか?
const hide_TableCol_byLabel = (tableFieldCode: string,
fieldCode: string,
label: string
): void => {
// @ts-ignore
const targetTableEl1 = kv.detail.getElementByCode(tableFieldCode);
let targetHeaderColEl1: HTMLElement;
let targetHeaderColIndex: number;
if (targetTableEl1?.children[0]?.children[1]?.children[0]?.children[0]?.children?.length > 0) { // HTMLCollectionのforEach関数はundefined
for (let colIndex = 0; colIndex < targetTableEl1.children[0].children[1].children[0].children[0].children.length; colIndex++) {
const f = targetTableEl1.children[0].children[1].children[0].children[0].children[colIndex];
if (f.children[0].innerText === label) { // headerに表示しているcolのFieldCodeとラベルが異なるので、labelで、対象カラムを探す
targetHeaderColEl1 = f;
targetHeaderColIndex = colIndex;
}
}
}
if (targetHeaderColEl1) {
targetHeaderColEl1.style.display = 'none'; // header行のCOLを非表示
if (targetTableEl1.children[0]?.children[1]?.children[1]?.children?.length > 0) {
// targetBodyColRowsEl2.forEach((r: any) => { // bodyの各行について
for (let rowIndex = 0; rowIndex < targetTableEl1.children[0].children[1].children[1].children.length; rowIndex++) {
const r: HTMLElement = targetTableEl1.children[0].children[1].children[1].children[rowIndex];
// r.style.display = 'none'; // 所定のtdカラムを非表示
// @ts-ignore
r.children[targetHeaderColIndex].children[0].style.display = 'none'; // 所定のtdカラム配下のdivを非表示
// @ts-ignore
r.children[targetHeaderColIndex].children[0].innerHTML = ''; // 所定のtdカラム配下のdivを非表示
// @ts-ignore
r.children[targetHeaderColIndex].style.display = 'none'; // 所定のtdカラムを非表示
}
}
} else {
// @ts-ignore
console.error("At hide_TableCol_byLabel: field not find: table=" + tableFieldCode + " " + label, targetHeaderColEl1)
}
};
///////////////////////////////
kv.events.record.mounted.push(function (state) {
setTimeout(() => {
hide_TableCol_byLabel("テーブルのfieldCode", "カラムのfieldCode", "カラムのラベル");
}, 32);
}
1件のコメント
公式ドキュメントに記載されていないインタフェースは、何時か 予告なく動かなくなるもののようです。
公式ドキュメントに記載されていないインタフェースを使ってしまうと、何時か 予告なく動かなくなるもののようです。
昔の昔のバージョンでのkviewer用のカスタマイズでは、DOM更新が有効だったらしいという状況から、
多分、昔のバージョンでのkviewerのDOM更新シーケンスは、こんな風な順序だったのでしょう。
「
(A):kviewerの"レコード詳細画面”で定義された基本的なレイアウトに従って、DOMの組み立て。
(B):kviewerの"レコード詳細画面”の中のフィールドやSUBTABEのカラム・フィールド毎のstyle関連の設定値に従って、DOM更新。
(C): kv.events.record.mountedイベント発火
(D): kv.events.record.mountedイベントハンドラの中のカスタマイズ処理で、DOMを更新
(E): kv.events.record.mountedイベントハンドラから返されたstatusの内容を、以降の処理に伝搬。
(F): これ以前の(D)段階での内部的なDOMの更新内容が、再描画されて、画面表示内容になる。
」
でも、kviewerかブラウザのバージョンアップの何処かの段階で、多分、下記の機能追加の時に、予告なく、こんな風にDOM更新&再描画の順序が変わったのだと思います。
kViewerで各フィールドに対する非表示設定が可能になりました│kintoneapp BLOG
「
(A):kviewerの"レコード詳細画面”で定義された基本的なレイアウトに従って、DOMの組み立て。
(C): kv.events.record.mountedイベント発火
(D): kv.events.record.mountedイベントハンドラの中のカスタマイズ処理で、DOMを更新
(B’):kviewerの"レコード詳細画面”の中のフィールドやSUBTABLEのカラム・フィールド毎のstyle関連の設定値に従って、DOM更新。
(SUBTABLEのカラム毎のstyle関連設定値は、state.view.detailView.elements[subTableのフィールド番号].fields[カラム番号].styleに入って居て)、{display,width}等の値が入って居る)
(E): kv.events.record.mountedイベントハンドラから返されたstatusの内容を、以降の処理に伝搬。
(F): これ以前の(E)の段階での内部的なDOMの更新内容が、再描画されて、画面表示内容になる。
」
これでも正確性には欠けていて、「(B')と(D)のDOM更新内容が再描画されて画面表示内容に反映されるタイミングは、順不定で、SUBTABLEのカラム毎に入れ替わりうる」と解釈したほうが良いかもしれない。
もし、そうなら、style関連のDOM更新箇所を kviewerの内部処理に集約すれば良いので、以下の様なコードが有効でしょう。
でも、この改善版コードは、公式ドキュメント記載外のstate.view.detailView.elements[subTableのフィールド番号].fields[カラム番号].styleを参照&更新しています。
ということは、この改善版コードが今日は旨く動いていても、将来 予告なく 誤動作する、危ういコードだということです。
そんな状況を改善するには、公式ドキュメント記載外のstate.view.detailView.elements[subTableのフィールド番号].fields[カラム番号]オブジェクトの仕様を公式ドキュメントに記載していただいて、「予告なく 破壊的な仕様変更しないで、将来とも 互換性を保って欲しい」という 仕様追加要望を、kviewerの開発元に伝えるしか無いと 思います。