form-creator について
一時的な入力を集め、呼び出し元にデータを返すDatex Studioフォームの作成・変更を支援するスキルです。コンポーネント選択、JSON作成、検証、ブランチへのCLI更新を案内します。
主な機能
- 01フォーム・エディター・グリッドの選択
- 02フォームJSONの作成ガイド
- 03入出力パラメーターの契約
- 04検証と確認フローのパターン
- 05ブランチ単位のCLI手順
活用シーン
- 01入力を集めるダイアログの作成
- 02入力値を呼び出し元のコンポーネントへ返却
- 03確認を有効にする前のフィールド検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ datex/ skills --skill form-creatorインストール後、Claude Code で/form-creatorを入力して読み込まれたか確認します。
同梱ファイルevals/evals.jsonreferences/forms.md
詳細
フォーム作成
ブランチ上で Datex Studio フォーム(configurationTypeId=5)を作成または変更します。フォームはユーザーデータを収集する入力コンポーネントで、必要に応じて検証後にアクションを実行するワークフローをホストし、閉じる際に outParams を介してペイロードを呼び出し元に返します。フォームは通常、グリッド、ハブ、その他のフォームからモーダルまたはフライアウトダイアログとして開かれます。
参考資料
- ../datex-studio-shared/branch-setup.md — ブランチ/接続の選択(複数のスキルで共有)
- references/forms.md — フォーム作成の正式なリファレンス:ファイル構造、ランタイムグローバル、呼び出しコントラクト、一般的なパターン、事前確認チェックリスト
- ../datex-studio-conventions/file-format.md —
configurationTypeIdの表と TypeScript 式のエンコード規則 - ../datex-studio-conventions/naming-conventions.md —
_formサフィックス、ファイル名の幹との一致、表示名のルール - ../datex-studio-runtime/runtime-globals.md — フォームコードで利用できる、プラットフォームが注入するグローバル(
$form、$flows、$shell、$utils、...) - ../datex-studio-runtime/calling-conventions.md — UI 層の呼び出し規則(関数を呼び出し、アクションは呼び出さないこと。CRUD は
$apis.<Package>.FootprintApi.extendedActions.<action_name>を介して実行) - ../editor-creator/references/editors.md — 関連コンポーネント:エンティティに紐付いた表示/編集(フォームとエディターの選択)
- ../embed-creator/references/embeds.md — 関連コンポーネント:フィールドコントロールなしで iframe/URL/HTML 文字列を表示(フォームと埋め込みの選択)
- ../grid-creator/references/grids.md — 行アクション/ツールバーボタンのフローを介したフォームの一般的なホスト
- ../selector-creator/references/selectors.md — ドロップダウン/オートコンプリートのフィールドでセレクターをマウント
- ../component-wiring-check/references/component-wiring.md — ホスト参照コントラクト、vars を宣言する規則、moduleId の規則
依存関係
requirements-gatheringスキル — 会話のコンテキストに要件概要がまだない場合、その作成のために呼び出されますeditor-creator/grid-creatorスキル — 要件が一時的な入力収集ではなく、単一エンティティの表示/編集画面(エディター)または複数レコードのリスト(グリッド)に該当する場合に呼び出されますselector-creatorスキル — フォームのドロップダウン/オートコンプリートフィールドに必要なセレクターがまだ存在しない場合に呼び出されますhub-creatorスキル — フォームのホストがハブのタブ/ボタンで、フォームをダイアログとして開くためのconfigParametersコントラクトを設定する必要がある場合に呼び出されますcomponent-wiring-checkスキル — プッシュ前に、フォームのホスト(ハブボタン/グリッド行アクション/親フォーム)におけるconfigParametersと対象のinParamsのコントラクトを監査するために呼び出されますtype-definition-creatorスキル — フォームのinParams/outParams/varsの形状が、作成または拡張が必要なインターフェースを参照している場合に呼び出されます
CLI のライフサイクル
フォームの作成では dxs configuration を使用します。これは、すべてのプラットフォーム設定タイプに対応する汎用 CRUD プリミティブです。dxs form サブコマンドやフィールド単位のパッチ適用はありません。JSON 本文全体を作成する(または取得して抽出する)か、編集してから全体をプッシュします。CLI のタイプ識別子は form(小文字。ConfigurationEndpoints.normalize_type の出力と一致)で、configurationTypeId: 5 に対応します。
新しいフォームを作成する:
# 1. Build body.json from scratch (see references/forms.md → Minimal Valid Skeleton)
# 2. Validate — gates the push. Exit 1 = errors found (read validation_errors, fix, re-run), not a broken CLI
dxs configuration validate form -b <branchId> -D body.json
# 3. Create
dxs configuration upsert form -b <branchId> -D body.json
既存のフォームを編集する:
# 1. Fetch — note the envelope wrapper
dxs configuration get form <configId> -b <branchId> -O envelope.json
# 2. EXTRACT THE INNER BODY (round-trip footgun guard — see "Round-trip rule" below)
jq .json envelope.json > body.json
# 3. Edit body.json
# 4. Validate — gates the push. Exit 1 = errors found (read validation_errors, fix, re-run), not a broken CLI
dxs configuration validate form -b <branchId> -D body.json
# 5. Push
dxs configuration upsert form -b <branchId> -D body.json
ラウンドトリップのルール(重要)
既存の設定を編集する際は、envelope.json を直接 dxs configuration upsert にパイプしてはいけません。設定内容が気づかないうちに破壊されます。上記の修正後の手順(編集前に jq で内側の .json を抽出する)は、あらゆるラウンドトリップで必須です。正式なラウンドトリップの手順と根本的なバグについては、../datex-studio-shared/configuration-roundtrip.md を参照してください。
フォームには、toolbar、フィールドごとの controlConfig ブロックを含む fieldsets、すべての executeCodeConfig ステップに code 文字列を含む flows、および inParams/outParams/vars のスキーマが含まれます。ラウンドトリップの手順(取得 → jq で抽出 → 編集 → 検証 → プッシュ)は必ず守ってください。
ワークフロー
[Phase 1: Setup + Requirements]
Follow branch-setup.md for branch/connection selection
|
[requirements brief in context?]
+-----+-----+
| |
YES NO -> invoke `requirements-gathering`
| |
+-----+------+
|
[Phase 2: Form vs Editor vs Grid decision]
Consult references/forms.md → "Purpose & When to Use":
- transient input collection, returns outParams, no entity -> form
- single hydrated entity, view/edit toggle, persist via CRUD -> editor
- multi-record tabular view -> grid
If editor -> invoke `editor-creator` instead and stop here.
If grid -> invoke `grid-creator` instead and stop here.
Create-only dialogs are usually forms, not editors.
|
[Phase 3: Author form body]
Build body.json:
- File shape (configurationTypeId=5, *-form.json suffix,
referenceName ends _form, snake_case matches filename stem)
- TypeScript-expression encoding on every declarative string slot
(value, tooltip, placeholder, format): backticks for display text,
TS quotes for plain literals, raw expressions unwrapped
- Declarative vs imperative init — don't mix; if both are present
they must read the same inParam path
- Open form as dialog via $shell.<TargetPackage>.open<referenceName>Dialog
(target's package, not the caller's; snake_case preserved)
- Validate-then-gate-confirm via onFormValidateFlowConfig +
formValidationFlows, not one-shot onInitFlowConfig assignments
- Emit is_confirmed: boolean outParam if callers must distinguish
confirm from cancel
- Every $form.vars.<id> written in flow code is declared in vars[];
every $form.<flowName>() call has a matching flow in flows[]
- Sibling *Config keys explicitly null on every controlConfig
- No $types.<Package>.e_<enum> in vars/inParams/outParams —
primitives only at the param layer; cast at usage in flow code
- Invoke `selector-creator` if a dropdown field needs a new selector
- Invoke `component-wiring-check` to audit the host's configParameters
|
[Phase 4: Validate + push]
dxs configuration validate form -b <branchId> -D body.json
|
+----+----+
| |
CREATE MODIFY-EXISTING
| |
| use the corrected round-trip
| (get -O envelope -> jq .json -> body)
| |
+----+----+
|
v
dxs configuration upsert form -b <branchId> -D body.json
(upsert creates or updates by referenceName — one command for both)
|
[Phase 5: Verify in Studio (optional)]
Open the form as a dialog (from its host hub/grid/form);
confirm field hydration, validate-then-gate-confirm, confirm vs cancel
return shapes
|
[invoke `post-edit-verification`; then `component-validator`]
フェーズの詳細
フェーズ 1:セットアップと要件
- ブランチと接続の選択については、../datex-studio-shared/branch-setup.md に従ってください。ブランチ ID を決めつけてはいけません。ユーザーに確認してください。
- 会話のコンテキストに要件ブリーフ(
requirements-gatheringまたは別の呼び出し元のスキルが作成したもの)がすでに存在するか確認してください。- ブリーフがある場合 — それを使用してください。ブリーフには、フォームが収集する入力、妥当性のルール、呼び出し元が返されたペイロードをどのように扱うか(確定時にどの CRUD アクションが実行されるか、該当する場合)、およびフォームの開き方(ダイアログを呼び出すホスト)が記載されている必要があります。
- ブリーフがない場合 — まず
requirements-gatheringスキルを呼び出してください。入力の形、妥当性のルール、確定とキャンセルのセマンティクスを最初に正しく把握することで、検証後に確定をゲートするフローを作り直す手間を避けられます。
フェーズ 2:フォーム、エディター、グリッドの選択
作成に着手する前に、references/forms.md → 目的と使用場面 を確認してください。これは見た目の違いではありません。フォーム、エディター、グリッドはそれぞれ異なる役割があり、互換性はありません。
フォームを選ぶ場合:
- 保存済みレコードにはまだ対応していない、一時的な入力の収集を行います。
- ダイアログは
outParamsを呼び出し元に返します。フォーム自体から暗黙的に何かが永続化されることはありません。 - ダイアログは作成専用で、データを入力する対象となるエンティティはまだ存在しません。
- ダイアログで設定(スケジュールやオプションのセットなど)を求め、その値を呼び出し元に返します。
代わりにエディターを選ぶ場合:
- ユーザーがキーで特定される単一のエンティティを表示または変更します。
- フィールドレベルの入力が、そのエンティティのプロパティに 1 対 1 で対応します。
- UX では、閲覧モード(読み取り専用)と編集モード(入力が有効になり、保存がアクティブになる)の切り替えを明確にします。
- フローによって CRUD アクション経由で変更を永続化します。ダイアログが値を返すだけではありません。
代わりにグリッドを選ぶ場合:
- ユーザーが表形式のレイアウトで複数のレコードを表示または操作します。
答えがエディターの場合は、作業を中止して editor-creator を呼び出してください。答えがグリッドの場合は、作業を中止して grid-creator を呼び出してください。フォームでは確定時に CRUD アクションを呼び出すことができます(検証後にアクションを実行するパターン)が、それでもフォームです。ハイドレートされたエンティティ参照はなく、収集した入力を使ってアクションを呼び出すだけです。
フェーズ 3:フォーム本体の作成
references/forms.md → 最小限の有効なスケルトン のスケルトンから body.json を作成してください。主なポイント:
-
ファイルの基本事項。 以下の事前チェックリストと../datex-studio-conventions/universal-checklist.mdに従ってください。
-form.jsonのファイル形式については、references/forms.md → ファイルの場所と命名 を参照してください。 -
すべての宣言的文字列スロットで TypeScript 式としてエンコードします。
controlConfig内のすべてのvalue、tooltip、placeholder、format、および(変数にバインドされている場合の)ボタンのlabelは、そのまま生成された TS にインライン展開されます。表示テキストはバッククォートで囲み("`Set schedule…`")、プレーンな文字列リテラルは TS の引用符で囲み("'MM/DD/YYYY'")、生の式は囲まずに記述します("$form.inParams.foo")。囲まれていない"Opens the dialog."のようなツールチップは、トークンとしてそのままコンパイルされ、ビルドが失敗します。コントロールが公開する文字列スロットが多いため、フォームでこのルールに違反するケースが最もよく見られます。../datex-studio-conventions/file-format.md → Declarative String Values Are TypeScript Expressions を参照してください。 -
動的なツールチップは変数を介して設定します。 Flow コードから
$form.fields.x.control.tooltipに直接代入することはできません。これは宣言専用のスロットです。実行時にツールチップを変更するには、$form.vars.<name>(文字列)を宣言し、フィールドのtooltipを生の TS 式"$form.vars.<name>"にバインドして、Flow コードで変数に値を代入します。../datex-studio-conventions/file-format.md → Declarative String Values Are TypeScript Expressions と → Dynamic Tooltip Values Go Through a Var を参照してください。 -
宣言的な初期化と命令的な初期化は混在させないでください。
inParamsからフィールドに初期値を設定する方法は 2 つあります。コントロールのvalueフィールドへの宣言的バインディング(例:"$form.inParams.foo"。レンダリング時に評価されます)と、onInitFlowConfig内での命令的な代入($form.fields.foo.control.value = $form.inParams.foo。初期化 Flow の後に実行されます)です。1 回限りの初期化には宣言的バインディングを、条件付きまたは非同期の初期化には命令的な代入を使います。混在させないでください。宣言的バインディングと命令的な代入で異なる inParam パスを参照していると、気付かないうちにバグになります。レンダリング時には宣言的バインディングが優先され、命令的な代入は正しく見えても効果がありません。両方を使う場合は、同じパスを参照させるか、どちらか一方を削除してください。references/forms.md → Receiving inParams inside a form を参照してください。 -
ダイアログとして開く場合。 ダイアログを開くシェル呼び出しは、フォームの
referenceNameから導出されます。$shell.<TargetPackage>.open<referenceName>Dialog(inParams, 'modal' | 'flyout', EModalSize.<size>)。<TargetPackage>は呼び出し先フォームのパッケージです。呼び出し元の機能フォルダーではなく、デフォルトのUtilitiesでもありません。<referenceName>は呼び出し先フォームのreferenceNameであり、snake_case を維持します(camelCase には変換しません)。解決される値は呼び出し先のoutParamsオブジェクトです。$form.close()を呼ばずにキャンセルすると、outParam フィールドは undefined になります。references/forms.md → Opening a form as a dialog と ../component-wiring-check/references/component-wiring.md を参照してください。 -
検証してから確定ボタンを制御します。 複数フィールドの検証は、フィールドごとの
onValidationFlowConfigではなく、onFormValidateFlowConfigから参照されるformValidationFlowsに記述します。この Flow はフィールドが変更されるたびに実行され、有効性を計算して$form.toolbar.confirm.control.readOnlyを設定します。onInitFlowConfig内での 1 回限りの代入は、ユーザーが操作すると古い状態になるため、確定ボタンの制御には適しません。フィールド単位のエラーは$validation.fieldErrors.<id>に追加します。references/forms.md → Validate-then-gate-confirm を参照してください。 -
確定とキャンセルを区別できること。 呼び出し元の
await openXxxDialog(...)は、対象のoutParamsオブジェクトに解決されます。また、$form.close()を呼び出さずにキャンセルした場合、これらのフィールドはundefinedのままです。呼び出し元で確定とキャンセルを区別する必要がある場合、対象フォームで 明示的なis_confirmed: booleanoutParam を出力し、呼び出し元でその値に応じて分岐します。個々の outParam フィールドの truthy 判定でキャンセルを検出しないでください。 -
すべての終了経路で
outParamsの型契約を満たすこと。required: trueの outParam を、一部の分岐だけで書き込むことはできません。型契約は、すべての終了経路で満たす必要があります。確定分岐ではoutParams.valueに書き込み、キャンセル分岐では書き込まない場合(キャンセルでは$form.close()をまったく呼び出さないため)、value.requiredはfalseのままにします。references/forms.md の事前チェックリスト項目 11 を参照してください。 -
$form.varsを宣言し、$form.<flow>()を実在するフローに対応させること。 フローコードで書き込むすべての$form.vars.<id>は、トップレベルのvars[]配列で宣言する必要があります("vars": nullの状態で$form.vars.x = ...を記述すると、インポート時にProperty 'vars' does not exist on type 'IForm'エラーになります)。すべてのawait $form.<flowName>()呼び出しは、flows[]の実在するエントリーに対応させる必要があります(プラットフォームは各フローのreferenceNameに対して、$formにメソッドを自動生成します)。よくある例として、formValidationFlowsがawait $form.set_state()を呼び出しているのに、set_stateフローが存在しないケースがあります。不足しているフローを定義するか、検証フックを削除してください。references/forms.md →$form.varsの宣言が必要;$form.<flow>()に対応するフローが必要 を参照してください。 -
フローコードと
inParams/outParams/varsのスキーマを一致させること。 フローコードで読み書きするすべてのネストされたフィールドは、対応するトップレベルのobjectTypeDefに、3 つすべてで同じプロパティ記述子の形で記述する必要があります。フィールドの不足は、インポート時にProperty 'X' does not exist on type {...}として発生します。フローコードが参照するオブジェクトにフィールドを追加するときは、関連するすべてのobjectTypeDef(vars + inParams + outParams)に同じ編集で追加してください。 -
兄弟の
*Configキーを明示的に null にすること。 各controlConfigでは、有効なサブ設定(例:textBoxフィールドのtextBoxConfig)だけを設定し、それ以外(buttonConfig、selectBoxConfigなど)は明示的にnullのままにします。構造的な差分比較でもこの規約に従ってください。既存のフォームコンポーネントでは、兄弟のスロットはすべて存在し、null に設定されています。 -
vars/inParams/outParamsにカスタム列挙型の FQN を指定しないこと。 フォームはパラメーター宣言内の$types.<Package>.e_<enum>を解決できません。これらのフィールドはプリミティブ型(文字列値の列挙型にはstring、数値の列挙型にはnumber)として宣言し、フローコード内で使用するときにキャストしてください。 -
呼び出し階層に準拠すること。 フォームコードでは
$flows.<Package>.<fn>を介して関数を呼び出し、その関数内で$apis.<Package>.FootprintApi.extendedActions.<action_name>({...})として CRUD アクションを呼び出します。フォームコードからアクションを直接呼び出さないでください。../datex-studio-runtime/calling-conventions.md を参照してください。 -
ホスト契約を監査すること。 このフォームをダイアログとして開くハブボタン、グリッド行アクション、またはフォームでは、完全な
configParameters契約を宣言する必要があります。フォームで宣言するすべてのinParamに対して、ホスト側にエントリーを用意してください。未使用のものもvalue: nullを指定して含めます。プッシュする前にcomponent-wiring-checkを実行して、参照契約を監査してください。../component-wiring-check/references/component-wiring.md を参照してください。 -
フォームがデータソースをバインドする場合は、その形状とリンクされたデータソースの形状を確認します。 ほとんどのフォームはパラメーター駆動型であり、
datasourceConfig: null/linkedDatasources: nullを持ちます。フォームがデータソースをバインドする場合は、エディターと同じ要件に従い、単一結果(get)でなければなりません。また、すべてのlinkedDatasourcesエントリが、それぞれのリンクのtypeと一致している必要があります。サーバー側の使用ゲートでは、いずれかが一致しない場合に公開がブロックされます。バインドされたデータソースはデフォルトでフォーム所有であり、フォーム自身のdatasources[]に埋め込まれます。スタンドアロンのデータソースは、../datasource-creator/references/datasources.md → デフォルトで所有に記載されたオーバーライド用に限られます。references/forms.md → オプションのデータソース配線を参照してください。
フェーズ 4:検証してプッシュする
# Validate the body locally against the branch. Exit 1 = validation found errors
# (read validation_errors, fix body.json, re-run) — not a broken CLI. Do not push on exit 1.
dxs configuration validate form -b <branchId> -D body.json
# For a new form
dxs configuration upsert form -b <branchId> -D body.json
# For modify-existing (round-trip — never skip the jq extract)
dxs configuration get form <configId> -b <branchId> -O envelope.json
jq .json envelope.json > body.json
# ... edit body.json ...
dxs configuration upsert form -b <branchId> -D body.json
検証では、必須フィールドの不足、不正なパラメーター記述子の形状、未定義のフロー ID 参照、参照エラーがプッシュ前に検出されます。ただし、宣言型と命令型の初期化の競合、未宣言の $form.vars.<id> への書き込み、ラップされていない TypeScript 式のスロット、誤ったフックに置かれた確認ボタンのゲーティングは検出されません。これらは動作に関する問題であり、実行時にのみ表面化します。プッシュ前にreferences/forms.md → 事前確認チェックリストを確認してください。
フェーズ 5:Studio で確認する(任意)
通常の呼び出し経路(ハブのツールバーのボタン、グリッドの行アクション、または別のフォームから連鎖して呼び出す親フォーム)を通じて、ダイアログとしてフォームを開きます。
- フィールドのデータ取得が成功します。宣言型バインディングと命令型の
onInitFlowConfigへの代入によって、呼び出し元が実際に値を設定する inParam パスから値が設定されます。 onFormValidateFlowConfigが有効と報告するまで、確認ボタンは無効のままです。- 確認するとフォームが閉じ、呼び出し元の
await openXxxDialog(...)は値が設定されたoutParamsを返します。 - キャンセル(X で閉じる、ESC、明示的なキャンセルボタン)すると、呼び出し元のプロミスは outParam フィールドが
undefinedの状態で解決されます。呼び出し元が確認とキャンセルを区別する必要がある場合は、確認時に明示的なis_confirmed: booleanoutParam が出力され、呼び出し元はその値に応じて処理を分岐します。 - 検証フィールドのエラーは適切なフィールドに表示されます(
$validation.fieldErrors.<id>.push(message)は指定されたフィールドに反映されます)。
アプリを実行できない場合は、設定を再取得し(修正済みの jq .json 抽出パターンを使用)、body.json と差分を比較してプッシュが反映されたことを確認します。
公開前チェックリスト
公開する前に、references/forms.md → 公開前チェックリストのチェックリスト全体を確認します。簡易版は次のとおりです。
- ファイルの基本事項。
configurationTypeId: 5、サフィックスは-form.json、referenceNameの末尾は_form— さらに共通チェック(../datex-studio-conventions/universal-checklist.md)。 - フロー ID の参照先が存在する。
onInitFlowConfig.flowId、すべてのclickFlowConfig.flowId、uiValueChangeFlowConfig.flowId、onValidationFlowConfig.flowId、onFormValidateFlowConfig.flowId— それぞれがflows[]に存在するフローを指定している必要があります。 - TypeScript 式の文字列が正しくラップされている。 表示テキストはバッククォートで囲み、生の式は囲まず、通常のリテラルは引用符で囲みます。動的なツールチップは、宣言済みの
$form.vars.<name>を経由します(.control.tooltipへの直接代入は何もしません)。 - 宣言的な初期化と命令的な初期化が競合しない。 フィールドに
valueバインディングとonInitFlowConfigによる代入の両方がある場合、同じ inParam パスを参照する必要があります。そうでない場合、宣言的な設定が黙って優先されます。 - 確認ボタンは、単発の
onInitFlowConfigによる代入ではなく、formValidationFlowsを介して制御されている。 - ダイアログを開く呼び出しでは、
<Package>に呼び出し元ではなく対象フォームのパッケージを使用している。 デフォルトで呼び出し元の機能フォルダーやUtilitiesを使用しないでください。キャメルケースにはしません。 - 呼び出し元が確認とキャンセルを区別する必要がある場合、
is_confirmed: booleanの outParam が出力されている。 outParamsの型コントラクトが、すべての終了パスと一致している。required: trueの outParam を条件付きでのみ設定しないでください。$form.varsが宣言されている。 フローコードで書き込むすべての var が、トップレベルのvars[]に含まれています。$form.<flowName>()の呼び出し先が存在する。 呼び出すすべてのフローがflows[]に存在します。不足しているフローを定義するか、それを参照する検証フックを削除してください。vars/inParams/outParamsのスキーマがフローコードと一致している。 フローコードで読み書きするすべてのネストされたフィールドが、対応するobjectTypeDefに一致するプロパティ記述子とともに含まれています。- すべての
controlConfigで、兄弟の*Configキーを明示的に null にしている。 有効なものだけに値を設定します。 vars/inParams/outParamsに$types.<Package>.e_<enum>がない。 パラメーター層ではプリミティブ型のみを使用し、使用時にキャストします。- 呼び出し階層の規則に準拠している。 フォームコードは
$flows.<Package>.<fn>経由で関数を呼び出します。関数は$apis.<Package>.FootprintApi.extendedActions.<action_name>({...})経由で CRUD アクションをラップします。フォームからアクションを直接呼び出しません。 - ホストに完全な
configParametersコントラクトがある。 フォームで宣言されたすべての inParam にホスト側のエントリーがあり、未使用のものにはvalue: nullを指定します。component-wiring-checkで監査します。 - データソースの形状が制約されている。 フォームが
datasourceConfigをバインドする場合、それは単一結果であり、すべてのlinkedDatasourcesエントリーが対応するリンクのtypeと一致しています。どちらも満たされない場合、公開はブロックされます。
よくある間違い
| 間違い | 修正方法 |
|---|---|
宣言的な文字列スロットをラップしていない("`Opens the dialog.`" ではなく "Opens the dialog.") | 生成された TS にそのままインライン展開されるため、トークンをそのまま置くとビルドに失敗します。表示テキストにはバッククォート、通常のリテラルには引用符、生の式はラップせずに使用します。 |
フローコードで $form.fields.x.control.tooltip に代入しても、実行時にツールチップが変わらない | .control.tooltip は宣言専用です。$form.vars.<name>(文字列)を宣言し、フィールドの tooltip を "$form.vars.<name>" にバインドして、フローコードで変数に代入します。 |
宣言的な value: "$form.inParams.foo" と onInitFlowConfig での $form.fields.x.control.value = $form.inParams.bar の書き込み | レンダリング時には宣言的なバインディングが優先されるため、命令的な代入は何の効果もなく無視されます。同じパスを参照するようにするか、どちらか一方を削除します。 |
onInitFlowConfig で一度だけ代入して確認ボタンの readOnly を制御する | 最初のフィールド変更後に古い状態になります。制御処理を onFormValidateFlowConfig と formValidationFlows に移します。 |
呼び出し元の await openXxxDialog(...) がキャンセル時に undefined の outParams を返し、コードが空の値での確定として扱う | 対象フォームから明示的な is_confirmed: boolean の outParam を返し、それに基づいて分岐します。 |
トップレベルで "vars": null のまま、フローコードで $form.vars.x = ... を実行する | インポートエラー:Property 'vars' does not exist on type 'IForm'。inParams/outParams と同じプロパティ記述子の形式で、すべての変数を vars[] に宣言します。 |
flows[] に set_state フローがない状態で、フローコードから await $form.set_state() を呼び出す | インポートエラー:Property 'set_state' does not exist on type 'IForm'。不足しているフローを定義するか、呼び出し(およびそれを含む formValidationFlows/onFormValidateFlowConfig フック)を削除します。 |
outParams.value.required: true だが、キャンセル分岐で value を設定せずに $form.close() を呼び出す | 型の契約は、すべてのクローズ経路と一致する必要があります。required: true を削除するか、すべてのクローズ時に value が書き込まれるようにします。 |
対象フォームが Utilities に登録されているのに、ダイアログを開く呼び出しで呼び出し元の機能フォルダーを <Package> に指定する(例:$shell.MyFeature.openXFormDialog) | <Package> は呼び出し元ではなく、対象フォームのモジュールです。対象フォームで宣言されているモジュールを確認します。 |
ダイアログを開く呼び出しで referenceName をキャメルケースにする(referenceName: my_form に対して openMyFormDialog) | スネークケースはそのまま保持されます:$shell.<Package>.openmy_formDialog(...)。 |
隣接する *Config スロットを省略する(例:textBoxConfig だけを設定し、他のサブ設定を省略する) | 既存のフォームでは、構造差分を取れるよう、隣接するスロットをすべて残して null にします。この規約に従います。 |
vars/inParams/outParams で $types.<Package>.e_<enum> を指定する | パラメーター層ではカスタム列挙型の FQN を解決できません。プリミティブ型(string/number)として宣言し、フローコード内で使用時にキャストします。 |
| フォームコードからアクションを直接呼び出す | UI 層のルールでは、フォームから呼び出せるのは関数のみです。関数内で $apis.<Package>.FootprintApi.extendedActions.<action_name>({...}) を介してアクションを呼び出します。 |
dxs configuration get -O envelope.json の結果を直接 dxs configuration upsert -D envelope.json に渡す | 設定内容が警告なく破壊されます。編集前に必ず jq .json envelope.json > body.json を実行します。上記の「ラウンドトリップのルール」を参照してください。 |
description が100文字を超える | SQL 列の上限により、プッシュ時の検証に失敗します。短くします。 |
referenceName が _form で終わっていない、またはファイル名のベース名と一致しない | インポート/検索に失敗します。スネークケースを使い、_form を末尾に付け、ファイル名のベース名と一致させます。 |
ホストの reference に設定した moduleId が、フォームではなくホストのパッケージを指している | コンポーネント間参照のルールにより、moduleId は常に対象のパッケージを指定します。../component-wiring-check/references/component-wiring.md を参照してください。 |
編集後は post-edit-verification を実行し、description/JSON/スキーマの違反を検出してください。最終レビューには component-validator を実行してください。