kviewerのSubTable中のカラムを条件付きで非表示にできる方法 伺い

下記の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);
}

 

公式ドキュメントに記載されていないインタフェースは、何時か 予告なく動かなくなるもののようです。

公式ドキュメントに記載されていないインタフェースを使ってしまうと、何時か 予告なく動かなくなるもののようです。

昔の昔のバージョンでの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の内部処理に集約すれば良いので、以下の様なコードが有効でしょう。

 const hide_TableCol_byCode = (state: any, tableFieldCode: string,
    fieldCode: string,
    label: string
  ): void => {
    const subTableViewDef = state.view.detailView.elements.find((d: any) => d.code === tableFieldCode);
    if (subTableViewDef) {
      const colFieldViewDef = subTableViewDef.fields.find((d: any) => d.code === fieldCode);
      if (colFieldViewDef) {
        colFieldViewDef.style.display = "none";
      } else {
        console.error("ERROR at hide_TableCol_byCode: not found table " + tableFieldCode + " col FieldCode :", fieldCode);
      }

    } else {
      console.error("ERROR at hide_TableCol_byCode: not found table FieldCode:", tableFieldCode)
    }
}

 

でも、この改善版コードは、公式ドキュメント記載外のstate.view.detailView.elements[subTableのフィールド番号].fields[カラム番号].styleを参照&更新しています。
ということは、この改善版コードが今日は旨く動いていても、将来 予告なく 誤動作する、危ういコードだということです。

そんな状況を改善するには、公式ドキュメント記載外のstate.view.detailView.elements[subTableのフィールド番号].fields[カラム番号]オブジェクトの仕様を公式ドキュメントに記載していただいて、「予告なく 破壊的な仕様変更しないで、将来とも 互換性を保って欲しい」という 仕様追加要望を、kviewerの開発元に伝えるしか無いと 思います。

 

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。