0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

kintoneで「保存前に無理やり止める」が危険なこともある話

0
Posted at

ChatGPT Image 2026年5月21日 12_18_32.png

kintoneのJavaScriptカスタマイズを見ていると、
たまにこういうコードに出会う。

const inputFiles = document.querySelectorAll('.input-file-cybozu');
const inputFile_1 = inputFiles[0];

最初見たとき、
かなり怖かった。

なぜか。

これは、

「画面上の1番目の添付ファイル欄」

を見ているだけだから。


「今たまたまその順番」なだけ

例えば、

inputFiles[0]

は、

  • 今のレイアウト
  • 今の表示順
  • 今のDOM構造

で、
たまたま最初にいる添付欄。

でも、
業務仕様としては、

「特定の添付ファイルフィールド」

を見たいわけですよね。


だからレイアウト変更で壊れる

例えば、

  • フィールド追加
  • グループ移動
  • 非表示条件変更
  • kintone側DOM変更

こういう変更が入る。

すると、

inputFiles[0]

が、
突然別の添付欄を指し始める。


一番怖いのは「エラーにならない」

これ、
本当に怖い。

例えば、

税務顧問を見てるつもり
↓
実際は別ファイルを見てる
↓
でも正常動作して見える

が起きる。

つまり、

“静かに壊れる”

んですよね。

保守で一番危険なタイプ。


じゃあrecordを見ればいいのでは?

最初、
僕もそう思った。

つまり、

record['添付ファイル'].value

を使えばいいのでは、と。

でも実際試すと、
保存前イベントでは取得できないケースがあった。


添付ファイルは普通のフィールドと少し違う

kintoneの添付ファイルって、内部的にはかなり特殊。

新規にアップロードしたファイルは、保存前(submit)イベントの時点ではまだ fileKey が発行されていません。

そのため、保存前イベントで

record['添付ファイル'].value

を見ても、 [](空配列)が返ってくる。

(※すでに保存済みのファイルは取得できますが、新しく入れたものは取れない)

つまり、

  • DOMには表示されてる
  • でもrecordにはまだ反映されてない

が起きる。

普通のフォーム感覚で触ると、
かなりハマる。


だから昔の実装意図も分かる

ここで、

「あぁ、だからDOM見たのか」

と理解した。

つまり、

保存前に添付有無をチェックしたい
↓
でもrecordでは取れない
↓
DOMを見るしかない

という流れ。

なので、

DOMを触ったこと自体

は、
当時としては合理性がある。


でも問題は「index依存」

ただし、
問題はそこじゃない。

本当に危険なのは、

querySelectorAll(...)[0]

のほう。

つまり、

“画面上の何番目か”

を業務仕様にしてしまっていること。


どうしてもDOMを見るなら「順番」ではなく「業務項目」で取る

もちろん、
添付ファイルのように、

保存前ではrecordに反映されない

ケースでは、
DOMを見るしかない場面もある。

なので、

DOMを使うこと自体

は、
必ずしも悪ではない。

ただし、
それでも避けたいのが、

querySelectorAll(...)[0]

のような、
“何番目か”依存。

もしDOMを使うなら、

  • class構造
  • ラベル文字列

を使って、

「添付ファイルという業務項目」

を特定して取得したい。

少なくともこれなら、

  • フィールド追加
  • レイアウト変更
  • グループ移動

だけで、
突然別項目を見る事故はかなり減らせる。


保存後なら普通に取れる

保存後イベント、

  • app.record.create.submit.success
  • app.record.edit.submit.success

でなら、

record['添付ファイル'].value

が普通に取れる。

つまり、

  • contentType
  • size
  • fileKey

も取得できる。


じゃあ「保存後に検査」で良いのでは?

ここで発想を変えた。

無理やり保存前で止めなくても、

「保存後に確実に検査」

すれば良いのでは?

と。


実務では「完全ブロック」が正義とは限らない

エンジニアって、

「保存前に絶対止めるべき」

と思いがち。

でも現場って、

  • とりあえず保存したい
  • 後で修正したい
  • 一時保存したい

も普通にある。

だから、

保存は許可
↓
業務進行を止める

という設計も、
かなり実務的。


アプローチA:プロセス管理のボタンを押した時にチェックする

もしアプリで「プロセス管理(ワークフロー)」を使っているなら、これもスマート。

ステータス変更時イベント(app.record.detail.process.proceed)を使う。

この時点ではレコードが保存されているので、添付ファイルの情報は確実に取得できる。

kintone.events.on('app.record.detail.process.proceed', (event) => {
  const record = event.record;

  // 「作業完了」にステータスを進めるときだけチェック
  if (event.nextStatus.value === '作業完了') {
    const files = record['添付ファイル'].value;

    if (files.length === 0) {
      // エラーメッセージをセットすると、
      // kintoneがステータス変更を自動でブロックする
      event.error =
        '【エラー】作業完了にするには、成果物のファイルを添付してください。';
    }
  }

  return event;
});

これなら、書きかけの「一時保存」は邪魔しない。

いざ、

「次のステップへ回そう!」

とボタンを押したタイミングで、
確実に不備を弾くことができる。

業務の柔軟性を奪わない、
とてもkintoneらしい制御。


アプローチB:保存後にチェックし、画面上に警告を出す

保存後イベントで、

  • PDFかチェック
  • サイズチェック
  • 添付必須チェック

を行う。

もし不備があれば、

添付ファイルに不備があります。
PDFのみ、10MB以内で添付してください。

を表示。

さらに、詳細画面に

  • プロセス管理ボタンを非表示
  • 「添付ファイルを修正してください」を表示

にする。

つまり、

保存はできる
でも次の業務には進めない

という制御。


こっちのほうがkintone向き

kintoneって、

  • 現場運用で育つ
  • レイアウト変更が多い
  • 非同期処理が多い
  • 一時保存文化がある

ので、

「保存前に全部止める」

より、

「業務フローで制御する」

ほうが、
結果的に安全なことがある。


最後に

今回、
最初は

「DOMを見るな」

と思っていた。

でも実際に調べると、

「保存前では添付情報が不安定」

という、
kintone側事情も見えてきた。

だから今回の本質は、

「DOMを使うな」

ではない。

“画面上の何番目か”

を業務仕様にするな

なんですよね。

そして場合によっては、

「保存前で無理に止める」

より、

「保存後に確実に検査し、業務フロー側で進行を制御する」

ほうが、
ずっと安全だったりする。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?