
# consentFlow Webform Development

## Overview

consentFlow の Form.io スキーマ (webform JSON) を編集する全タスクの入口。Form.io コンポーネント `key` ↔ Notes アイテム `<prefix>{key}` の 1:1 マッピングが前提。`<prefix>` は consentFlow 側設定 (デフォルト `CF_`、既存アプリのモダナイズでは空文字もあり) で、**webform 側は接頭語非依存で書く** ([references/data-binding.md](/docs/data-binding.md) §1)。

## このガイドの前提 (Premise)

- **対象は最新版の consentFlow**。旧バージョン固有の挙動には触れない (必要なら「旧バージョンでは」と明記した箇所だけ)
- **webform JSON の置き場所と適用手順**: consentFlow デザイナーのフォームビルダーで設計 → JSON をエクスポート → 管理画面「WEB フォーム管理」の **WEBフォーム JSON** 欄に貼り付けて保存。JSON を直接編集した場合も同じ欄に貼る
- **運用中のフォームを編集するときは、編集前に「リビジョン保存」する**。申請文書は「WEBフォーム ID + リビジョン番号」で定義を参照するので、退避したリビジョンを指す既存文書は旧デザインのまま保たれ、新規申請から新デザインになる
- **consentFlow 本体 (サーバー側の処理・管理画面) は変更しない**。フォーム JSON の中だけで解決する

## Red Flags — STOP and check

これらは「違反すると確実に事故る」ルール。該当するコードを書こうとしたら一旦止まって対応する references/ を読むこと。

1. **`"type": "container"` でレイアウトしようとしている** → panel を使え。container はデータをネストしてフラット保存モデル (`<prefix><key>`) と不整合 ([references/layout-styling.md](/docs/layout-styling.md) §1)
2. **`cfAPI.getCurrentDoc().getItemValueString()` を StatusNo/ApplicationNo/sectionCode 等で呼ぼうとしている** → cfGlobal 直読で REST ゼロ ([references/server-data.md](/docs/server-data.md) §1)
3. **cfAPI を呼ぶのに `cfGlobal.isNewNote` ガードを書いていない** → 新規時に `Invalid universal id` エラーストーム ([references/server-data.md](/docs/server-data.md) §1)
4. **`"type": "textfield" + "hidden": true` に setValue() で書き込もうとしている** → `clearOnHide` で送信時クリア。`"type": "hidden"` を使え ([references/data-binding.md](/docs/data-binding.md) §2)
5. **`<script>` を htmlelement/content の content に書いている** → サニタイズで実行されない。`customConditional` / `calculateValue` / `logic[]` を使え ([references/scripting.md](/docs/scripting.md) §1)
6. **modalEdit panel を JS から閉じるのに `[ref="modalClose"]` を click している** → 「変更内容は保存されません」確認ダイアログ。`[ref="modalSave"]` を click ([references/layout-styling.md](/docs/layout-styling.md) §4)
7. **Select with `restViewJson` + `dataType: "string"` + `valueProperty: ""` で行オブジェクト保存** → `"[object Object]"` 文字列保存。`dataType: "object"` + `idPath: "@unid"` ([references/server-data.md](/docs/server-data.md) §3.8)。Notes 側は `<prefix>key` に行 JSON 文字列 1 アイテム ([references/data-binding.md](/docs/data-binding.md) §1)
8. **運用中のフォームで select の `valueProperty` / `dataType` を変えようとしている** → 変更前に保存された文書の値が選択肢と照合できずブランクになる (EditGrid は一覧だけ見えて行エディタがブランク)。再保存でも治らない。読込時の正規化 `calculateValue` と、`.value` 裸参照 JS の両対応をセットで入れる ([references/data-binding.md](/docs/data-binding.md) §1.1)
9. **panel × `customConditional` の自作ステップで、提出の `checkValidity` が表示中ステップにしか掛からない** → 非表示ステップは無検証、子の `clearOnHide:true` は消える。全ステップ表示フラグ + `clearOnHide:false` ([references/layout-styling.md](/docs/layout-styling.md) §6)
10. **Notes ビュー / メールトークン / SQL で値を使う select を `valueProperty: ""` のまま置いている、または `multiple: true` の select に `valueProperty` が無い** → Notes には `{"label":…,"value":…}` の JSON 文字列 (複数選択は行展開で衝突)。スカラーが要るなら `valueProperty` を設定 ([references/data-binding.md](/docs/data-binding.md) §1)
11. **「開いたとき 1 回だけ」の処理を `calculateValue` に `window.__xxxDone` フラグ + `setTimeout` で手書きしている / `customDefaultValue` に書いている** → 予約キー `scriptBlock` のコンポーネントに `cfAPI.form.onOpen` / `onNew` / `migrate(ver)` を登録する (コアが保存データ適用後に 1 回だけ呼ぶ)。手書き版は旧バージョンの consentFlow 向けのフォールバックのみ ([references/scripting.md](/docs/scripting.md) §9)
12. **`persistent:false` にしたから Notes に保存されない、と前提にしている** → 既定のアプリ設定では**全キーが保存される** (button の押下値も)。保存されないのは設定「persistent:false / Client-only の項目を保存しない」が はい の環境だけで、その環境では逆に非永続項目の値をビュー・メール・SQL から読めない。後で読む値は `persistent:true` に置き、一時入力・表示用計算値には `persistent:false` を付ける ([references/data-binding.md](/docs/data-binding.md) §1)
13. **`logic[]` の `trigger.event` に `blur` / `change` / `initialized` を書いて「この項目の」イベントのつもりでいる、または htmlelement / content に載せている** → 対象は常にフォーム全体 (`result[0] === instance` で絞る)。htmlelement / content に載せるとイベント名が i18n 翻訳され `error` / `submit` は永久に発火しない。入力系コンポーネント (textfield / `type:"hidden"`) に載せる ([references/scripting.md](/docs/scripting.md) §13)

## Quick Reference (やりたいこと → 読む reference)

| やりたいこと | reference |
|---|---|
| Form.io key と Notes アイテムのマッピング (接頭語は設定値、デフォルト `CF_`)、隠しフィールド (`hidden` vs `textfield+hidden`)、`input:false` の落とし穴 | [references/data-binding.md](/docs/data-binding.md) |
| サーバ値読出し: cfGlobal 直読 → cfAPI → restViewJson/restDocJson の判定と書き方、入力値を文書へ反映して承認者を再計算する `myFormio.syncFields()` | [references/server-data.md](/docs/server-data.md) |
| パネル選択 (panel vs container)、styleBlock CSS とテンプレート、modalEdit ダイアログ、参照モード disabled | [references/layout-styling.md](/docs/layout-styling.md) |
| Form.io 拡張点 (customConditional 等)、button の自動注入変数 (`form`/`data`/`row`)、Chart.js v2、multi-select バリデータ、**フォームスクリプト `scriptBlock` + `cfAPI.form` (開いたとき 1 回だけ: onOpen / onNew / migrate / onReady)** | [references/scripting.md](/docs/scripting.md) |
| JSON 整形 (肥大化・1 行 JSON・重複キーの罠)、WebFormRevisionJson vs FieldJson、prune orphan items の挙動 | [references/json-conventions.md](/docs/json-conventions.md) |

## Decision flow: フォーム内 JS から Notes フィールド値を読みたい

```
need to read a Notes field from form JS?
  ├─ value in cfGlobal preload list? (docid / isNewNote / statusNo / applicationNo / currentUserName / sectionCode / postName / unitName / lang / acl / storageUnid / batchId / webFormRevisionNo / masterDb / cacheExpiration / ...)
  │   yes → cfGlobal.<member> directly (zero REST, no guard)
  │   no  → current doc field?
  │       yes → cfAPI.getCurrentDoc().getItemValueString(...) WITH cfGlobal.isNewNote guard
  │       no  → restDocJson (single doc by UNID) OR restViewJson (view query)
  │              WITH timeout: 30000 + clear-then-set + encodeURIComponent
```

詳細は [references/server-data.md](/docs/server-data.md)。

## When NOT to apply

- consentFlow コアエンジン本体 (ポータル / 部門マスタ含む) の編集 → コア改修は別プロセス。本スキルは webform JSON の範囲のみ
- 旧 Notes フォーム (クラシック設計要素) の編集 → Form.io ではない
- consentFlow 本体 (サーバー側プログラム・管理画面・文書画面の枠組み) の改修 → このスキルのスコープ外

## 運用ルール (新規 TIPS の追記先)

- **新しい TIPS** は references/<該当 ref>.md に追記する
- **Red Flag** は「違反すると確実に事故るレベル」のみ本 SKILL.md に列挙する。それより細かい注意は references/ 内に留める
- **SKILL.md 本体は <500 語維持** — auto-discovery 効率と毎セッション読込コスト最適化のため
- **本スキルは一般公開ドキュメント** — 顧客名・社内アプリ名・コア内部実装名 (クラス名 / 画面ファイル名 / スクリプトライブラリ名)・PC やワークスペースのパス・シェルや特定ツールのレシピ・案件日付を書かない。実例は症状・原因・対処の一般形に匿名化し、「最新版前提」で書く。これらを含む補足は社内向けの別資料に置く
