dispatch の応答命令と実行順を読み解く
_dispatch.js は、応答に並んだ命令をブラウザで実行する部分です。値を保存する処理そのものではなく、DOM・送信バッファ・ブラウザ側の状態・イベントを操作する入口になります。
使う命令だけでなく、配列の順序、対象の書き方、値の型、渡されたデータの参照で結果が変わります。このページで仕組みを確認し、dispatch の実装サンプルで値の反映と表示更新を試せます。
3つの関数の役割
| 関数 | 役割 | 入力と結果 |
|---|---|---|
$p.setByJson() | 応答全体の処理 | 命令配列を順に実行し、必要なら UI と検証を再適用。最後に反映後イベントを呼ぶ |
$p.setByJsonElement() | 命令1件の振り分け | Method に応じて DOM やデータを操作する |
$p.handleMessageFromJson() | メッセージだけを取り出す補助 | 最初の Message を探し、値があれば表示して true、なければ false |
根拠は _dispatch.js の各関数です。handleMessageFromJson() は他の命令を実行せず、setByJson() からも呼ばれません。HTTP エラー時の処理は _ajax.js が呼ぶ別の setServerErrorMessage() であり、通常の成功応答の命令配列実行と区別します(_ajax.js の失敗時処理、エラーメッセージの選別)。
setByJson の6つの引数
呼び出しの形は $p.setByJson(url, methodType, data, $control, _async, json) です。
| 引数 | この関数内での使われ方 |
|---|---|
url | 真と評価される場合に before_set と after_set を呼ぶ条件。イベントの引数にも入る |
methodType | イベントの引数に入る。命令の分岐には使わない |
data | 各命令へそのまま渡すデータ。SetFormData・ClearFormData・空の対象の Focus が利用する |
$control | 発火元のコントロール。対象がない After・Before の追加先、Href の操作対象になる |
_async | イベントの引数に入る。この関数の命令実行を非同期に切り替える指定ではない |
json | Method などを持つ命令オブジェクトの配列 |
根拠は setByJson()と命令の振り分けです。
通常の Ajax 成功時には、通信で使った data と $control をそのまま渡します。初回の画面表示でサーバースクリプトの応答を反映する経路では、URL を undefined、データを MainForm のバッファ、コントロールを #MainForm として渡します。初回表示では、この呼び出しによる before_set・after_set は実行されません(Ajax 成功時、初回表示の応答反映)。
命令オブジェクトの形とシリアライズ
次は形式を説明する応答例です。
[
{
"Method": "SetValue",
"Target": "#Results_Title",
"Value": "応答で指定したタイトル",
"Options": "{\"Hide\":true}"
}
]| フィールド | 注意点 |
|---|---|
Method | 大文字小文字を含めて switch の名前と一致させる |
Target | セレクタ、物理名、データのキー、関数名など。命令によって意味が変わる |
Value | 文字列・真偽値などをそのまま使う命令と、JSON 文字列を解析する命令がある |
Options | 存在すれば、命令を選ぶ前に JSON.parse() する。オブジェクトを直接入れる形式ではない |
サーバー側の context.AddResponse(method, target, value, options) は ResponseCollection に追加します。Value に null を渡すと空文字列に置き換えられ、Target・Options が null のフィールドは通常の JSON 化で省略されます。未指定、空文字列、明示した null は、自作の命令配列では同じ意味になりません。 Options を使わないときはフィールドを省略します(AddResponse()、応答への追加、JSON 化の既定値)。
命令の実行順と UI 再適用
図を読み込み中…
Html・ReplaceAll・Append・Prepend・After・Before のいずれかが配列にあれば、全命令を実行した後に $p.apply() と $p.applyValidator() を1回ずつ呼びます。途中の Invoke は再適用より前です。対象が見つからず DOM が変わらなかった場合でも、命令名が配列にあれば再適用の対象になります。Remove や Attr だけでは、この分岐には入りません(再適用の判定)。
$p.apply() は本体の画面部品を、$p.applyValidator() はフォームの入力検証を再適用する処理です。独自の装飾やイベントを自動で再登録する処理ではありません(UI の再適用、検証の再適用)。
before_set の false は中止条件ではない
before_set の戻り値を調べて中断する分岐はありません。false を返しても命令は実行されます。独自の反映後処理を置くなら、URL が渡される応答では after_set が再適用後の位置になります。初回表示も扱う場合は on_editor_load など、初回用の呼び出しも用意します(イベント呼び出し、setByJson())。
関数やイベントの完了を待つ仕組みではない
Invoke は $p[Target](Value)、Events は $p.execEvents(Target, '') を呼び、戻り値を使いません。呼び出した関数が Promise を返しても待機せず、次の命令へ進みます。Trigger で change を発火すれば、応答の後続命令や再適用に進む前に変更イベントの処理が始まります(Trigger・Invoke・Events)。
値を扱う5命令は、反映先が違う
| 命令 | Target | DOM | データの反映先・副作用 |
|---|---|---|---|
Set | 項目の表示名・物理名、またはセレクタ | 値を設定 | コントロールが所属するフォームのバッファを更新。通常の単一選択は change も発火 |
SetValue | セレクタ | 表示値を設定し、項目の表示状態を調整 | 自分では setData() を呼ばず、通常の単一選択でも change を発火しない |
SetData | セレクタ | 値は変更しない | コントロールの現在値を、その所属フォームのバッファに登録 |
SetFormData | データのキー | 変更しない | setByJson() に渡された data を直接変更 |
ClearFormData | キー・セレクタ・未指定 | 変更しない | 渡された data のキーを削除。データを渡さない場合は main-form のバッファを使う |
根拠は dispatch の値操作、SetValue・ClearFormData、set・setData、setValueです。
SetData と SetFormData は、常に同じオブジェクトを変更するわけではありません。例えば data が MainForm のバッファで、SetData の対象が DialogEditorForm 内にあれば、更新先のフォームが違います。対象のフォームと、応答へ渡された data の両方を確認してください。
Set の対象が空でも、セレクタへ切り替わるとは限らない
Set の分岐は、getControl() の戻り値が真かを見ます。項目名を解決できるが DOM が無い場合、戻り値は空の jQuery オブジェクトであり、セレクタへの切り替えは行いません。set() は要素数が1の場合に処理するため、対象が0件・複数件ならその値設定は行われません(対象の解決、Set の分岐、要素数の判定)。
ClearFormData は入力値を消す命令ではない
Target がデータのキーならそのキーを削除し、キーが無くセレクタとして要素が見つかれば、その要素の ID をキーとして削除します。Value が startsWith なら指定したキーの前方一致です。Target を省略した全体削除では、control-selectable の要素に対応するキーを残します。ignoreView は削除時に View で始まるキーを保護する指定です(clearData())。
DOM の値はこの命令では変更しません。また、次の送信で入力欄から再収集される値まで永続的に除外する設定でもありません。送信バッファの収集条件も合わせて確認します。
JSON 文字列と真偽値の使い分け
| 命令・項目 | 指定する型と意味 |
|---|---|
Attr・Css の Value | JSON.stringify({ Name, Value }) の文字列。オブジェクトを直接渡さない |
Message の Value | JSON.stringify({ Css, Text }) の文字列 |
SetValue の Options | JSON.stringify({ Hide: true }) などの文字列 |
Toggle の Value | 表示は文字列 '1'。数値 1 や真偽値 true は表示指定にならない |
Disabled の Value | true・false の真偽値を使う |
Options はすべての命令で先に解析しますが、その解析結果を使う分岐は SetValue の hideField() です。省略時は空オブジェクトになり、Hide が真偽値 true でなければ隠れている対象フィールドの hidden クラスを外す経路があります。隠したまま値を返すなら Hide: true を指定します(Options の解析、Attr・Css、Toggle・Disabled、hideField())。
例外と未知の命令
| 条件 | 結果 |
|---|---|
未知の Method | default 分岐がないため、対応する処理は行わず次の命令へ進む |
不正な Options | Method の判定前に JSON 解析で例外。未知の命令でもこの例外は起こる |
不正な Attr・Css の値 | その分岐の JSON 解析で例外 |
存在しない関数への Invoke | 呼び出し時に例外 |
After・Before の対象なし、かつ $control なし | 追加先へメソッドを呼ぶ段階で例外 |
| 空配列 | 命令はない。URL があれば反映前後イベントは呼ばれる |
json が undefined・null | 後段で json.filter() を呼ぶため、空配列の代わりにはならない |
setByJson() に命令ごとの try/catch や変更を戻す処理はありません。途中で同期的な例外が出ると、それより前の変更は残り、その後の命令、UI 再適用、after_set へ進みません。Ajax の成功コールバックでも、後に書かれた結果判定と ajax_after_done には到達しません(応答の逐次実行、命令分岐の全体、成功コールバック)。
C# のメソッド名と受け取る命令名を分ける
ResponseCollection.Val() は SetValue を生成します。一方、ValAndFormData() は SetValueAndFormData を生成しますが、確認したフロントエンドの _dispatch.js には、その case がありません。名前から両方の値を更新できると判断せず、SetValue と SetFormData を個別に指定します(C# 側の生成、受信側の全 case)。
用途から命令を選ぶ
| 目的 | 主な命令・実装 | 注意点 |
|---|---|---|
| 値の反映 | Set・SetValue・SetData・SetFormData | 送信先フォームと change の有無を区別する |
| HTML の更新 | Html・ReplaceAll・Append・Prepend・After・Before | 再適用は全命令の後。差し替えた要素を取り直す |
| 属性・表示の変更 | Attr・RemoveAttr・Css・Toggle・Disabled | 命令ごとの型を合わせる |
| ブラウザ側の処理を呼ぶ | Invoke・Events・Trigger・Click | 登録先と渡る引数が違う。呼び出し先の戻り値を待たない |
| 状態を次の処理へ渡す | SetMemory | $p のキーに代入。関数名など既存のキーを上書きしない |
| 移動・フォーカスなど | Href・PushState・Focus・スクロール命令 | 操作元のコントロールとデータに依存する命令がある |
全命令の引数は context.AddResponse の Method と引数を参照してください。使い分けを確認する具体例は dispatch の実装サンプルにまとめています。
調査する位置
応答をネットワーク表示で開き、対象命令の順序と型を確認します。デバッガーでは setByJsonElement() の switch と、setByJson() の再適用直前にブレークポイントを置くと、どの命令まで成功したかを追えます。
- 表示だけ変わる場合は、
SetValueとバッファ操作の有無を確認する。 - 応答の途中まで変わる場合は、JSON 解析や
Invokeの例外を確認する。 - 独自処理が UI の初期化前に動く場合は、
Invokeとafter_setの位置を確認する。 - 初回だけ独自処理が動かない場合は、URL が未指定の呼び出しか確認する。
- 再通信する場合は、
Set・Trigger・Clickの呼び出し先を確認する。