見出し画像

注文フォームの制御は通常フォームと別テーブル(catalog_ui_policy)


ServiceNow のサービスカタログで何かを注文するとき、ある質問(変数)が条件によって突然「必須」になることがあります。選択肢に応じて別の質問が現れたり消えたりもします。この「注文フォームがブラウザ側で動く」挙動を作っているのが、主に Catalog UI Policy(カタログ UI ポリシー)Catalog Client Script(カタログ クライアントスクリプト) です。


通常のフォーム(incident など)にも UI Policy と Client Script があります。ただしカタログの注文フォームが扱うのは「テーブルのフィールド」ではなく「カタログ変数(Variable)」で、制御の定義を置くテーブルも通常フォーム用とは別に用意されています。

この記事で起点にするのは3テーブルです。catalog_ui_policy(Catalog UI Policy)、その動作1行ぶんを保存する catalog_ui_policy_action(Catalog UI Policy Action)、そして catalog_script_client(Catalog Client Script)。それぞれが何を担い、通常版と何が違うのか。変数の表示・必須・読み取りをどこで制御しているのか。PDI(Zurich)の OOTB で確認した実測値とともに書いていきます。

想定読者は、ServiceNow の incident を触ったことがあり、通常フォームの UI Policy / Client Script はなんとなく分かる人です。カタログ側(注文フォーム)の制御がどのテーブルでどう作られているのかを、これから理解したい段階を想定しています。実機で確認する順番は、テーブルの継承関係 → 適用先(item / variable_set)の指定 → 適用範囲フラグ → UI Policy Action の動作項目です。

この記事で分かること

  • カタログの注文フォームの挙動を担う2本柱が Catalog UI Policy と Catalog Client Script であること

  • カタログ用3テーブルが、通常版(sys_ui_policy / sys_script_client など)を継承した子テーブルであること

  • 制御対象が「テーブルのフィールド」ではなくカタログ変数(Variable)であること

  • 適用先を applies_to(item=アイテム単位 / set=変数セット単位)で選ぶこと

  • アイテム表示・RITM・カタログタスクなど、適用範囲を boolean フラグで切り替えられること

  • 表示/必須/読み取りが、通常版と同じ visible / mandatory / disabled で制御されること

この記事の内容は ServiceNow の PDI(Personal Developer Instance)Zurich(ズーリッヒ)リリースの OOTB(初期設定)で確認した個人メモです。本番環境やカスタマイズ済み環境では、スクリプト・ポリシー・件数の内容が異なる場合があります。


Catalog UI Policy と Catalog Client Script とは

サービスカタログのアイテムを開くと、注文フォーム(変数の集まり)が表示されます。「ある選択肢を選んだら別の質問を出す」「特定の条件で質問を必須にする」「使わない質問を隠す」。こうした動きをサーバへ保存する前にブラウザ上で起こすのが、Catalog UI Policy と Catalog Client Script です。

  • Catalog Client Script(catalog_script_client) … カタログの注文フォーム上で動く JavaScript です。変数の値の計算・入力検証・他変数の自動入力など、ロジックを自由に書けます。

  • Catalog UI Policy(catalog_ui_policy) … 「この条件のときに、この変数を表示/必須/読み取りにする」を、基本ノーコードで設定する仕組みです。その具体的な動作は Catalog UI Policy Action(catalog_ui_policy_action)に分けて保存されます。

通常フォーム用の UI Policy / Client Script と役割は同じですが、扱う対象が「カタログ変数」になっている点が決定的に違います。


カタログ用3テーブルは「通常版を継承した子テーブル」

ここが通常フォーム用との最大の違いです。通常版の3テーブルは sys_ui_policy / sys_ui_policy_action / sys_script_client です。いずれも sys_metadata(Application File)を直接継承していました。一方カタログ用は、その通常版をもう一段継承した子テーブルでした。


今回確認した PDI(Zurich / OOTB)では、継承関係は次のとおりでした。

  • catalog_ui_policy(Catalog UI Policy)→ super_class = sys_ui_policy

  • catalog_ui_policy_action(Catalog UI Policy Action)→ super_class = sys_ui_policy_action

  • catalog_script_client(Catalog Client Scripts)→ super_class = sys_script_client

この二段継承により、カタログ版は通常版のフィールドをそのまま引き継いだ上で、カタログ固有のフィールドを足しています。たとえば表示/必須/読み取りを表す visible / mandatory / disabled は、親(sys_ui_policy_action)からの継承です。カタログ用テーブルが自前で持つわけではありません。カタログ固有フィールドの数は、catalog_ui_policy が11、catalog_ui_policy_action が6、catalog_script_client が11 でした。

テーブル定義は、次のURLで確認できます(先頭の <YourInstance> は自分のインスタンスに置き換えてください)。

https://<YourInstance>/sys_db_object_list.do?sysparm_query=name=catalog_ui_policy^ORname=catalog_ui_policy_action^ORname=catalog_script_client

通常フォーム用とカタログ用の対応

通常フォームとカタログとで、どのテーブルが対応するかを並べると、構造が見えてきます。



ポイントは2つです。

  • 制御の「対象」が違う … 通常版はテーブルのフィールド(incident の priority など)を制御しますが、カタログ版はカタログ変数(Variable)を制御します。

  • 適用先の「指定方法」が違う … 通常版は table(テーブル名)で対象を決めます。カタログ版は applies_to(item / set)と catalog_item / variable_set で決めます。


どこに適用するか(applies_to:item / variable_set)

Catalog UI Policy / Catalog Client Script は、適用先を applies_to で選びます。今回確認した PDI(Zurich / OOTB)では、選択肢は2種でした。


  • item(A Catalog Item) … 1つのカタログアイテムにだけ適用します。catalog_item(catalog_script_client では cat_item)で対象アイテムを指定します。

  • set(A Variable Set) … 1つの変数セットに適用します。変数セットは複数のアイテムで再利用される変数のまとまりなので、変数セットを使う全アイテムにまとめて効きます。variable_set で対象セットを指定します。

applies_to の実測件数

今回の PDI では、Catalog UI Policy 99件(active)のうち applies_to=item が96件、set が5件でした。Catalog Client Script 128件(active)では item が100件、set が28件です。多くはアイテム単位ですが、変数セット単位もそれなりに使われています。

次の実機画面は、カタログアイテム「Apple iPhone 13」に紐づく Catalog UI Policy です。Applies to=A Catalog Item、Catalog item=Apple iPhone 13 で、On load や Reverse if false の設定を持ちます。「条件が成立したら、ある変数を制御する」というまとまりです。


Catalog UI Policy の一覧は、次のURLで確認できます。

https://<YourInstance>/catalog_ui_policy_list.do?sysparm_query=active=true^ORDERBYapplies_to


公式の Create a UI policy for catalog items(Zurich) に、カタログアイテム/変数セットに対して UI Policy を作る手順と、適用先・条件の意味が説明されています。


どの場面で効かせるか(適用範囲フラグ)

通常版にはなかった、カタログ用ならではの設定が 適用範囲フラグ です。カタログ変数は、注文フォームだけでなく、注文後に生成される Requested Item(RITM)やカタログタスクの画面にも現れます。そこで、「どの場面で効かせるか」を boolean フラグで指定できます。


今回確認した PDI(Zurich / OOTB・active のうち)では、次の件数でした。

  • applies_catalog(カタログアイテム表示)… 94件。ほぼすべての Catalog UI Policy が「注文フォームでの表示」に効かせています。

  • applies_req_item(Requested Item / RITM)… 11件

  • applies_sc_task(Catalog Task)… 9件

  • applies_target_record(生成先レコード)… 9件

大多数は「注文フォームでの制御」が目的で、RITM やタスク側まで効かせているのは少数でした。


「動作」は Catalog UI Policy Action に保存される

Catalog UI Policy の本体(catalog_ui_policy)が持つのは「いつ・どこで動くか」です。「何をするか」は Catalog UI Policy Action(catalog_ui_policy_action)に 1変数=1レコード で保存されます。ここは通常版(sys_ui_policy_action)と同じ作りで、制御値は visible / mandatory / disabled の3つです。複数の Action が同じ Policy に紐づく場合の実行順は、固有フィールドの order で決まります。


visible / mandatory / disabled の3値

visible / mandatory / disabled は3値(True / False / Leave alone)で、既定は「Leave alone(=触らない)」です。1つの Action は「指定した変数だけを、指定した制御に変え、それ以外は触らない」という形で働きます。

次の実機画面は、先ほどの「Hide original number」UI Policy に紐づく Catalog UI Policy Action です。Variable name=what_was_the_original_phone_number、Mandatory=True、Visible=True、Read only=Leave alone でした。条件成立時に「元の電話番号」変数を表示しつつ必須にする動作だと読み取れます。


そして、この制御が実際に効く先が、利用者が見るカタログの注文フォームです。次は「Apple iPhone 13」の注文画面で、赤いアスタリスクが付いた質問が必須になっています。UI Policy / Client Script は、こうした変数の表示・必須・選択肢を、利用者の操作に応じて動的に切り替えています。



Catalog Client Script の種別(type)

Catalog Client Script は、いつ動くかを type で選びます。type は親の sys_script_client から継承しており、選択肢は通常版と同じ onLoad / onChange / onSubmit / onCellEdit の4種でした。ただし今回の PDI(OOTB)で実際に使われていたのは onLoad / onChange / onSubmit の3種で、onCellEdit は0件でした。カタログはリストではなくフォームなので、セル編集用の onCellEdit は実質使われません。

次の実機画面は、Catalog Client Script です。Applies to=A Catalog Item、Type=onChange、Variable name が指定されていました。通常の Client Script と同じく、動作は script 本文に直接書く作りです。


今回の PDI(Zurich / OOTB・active)で Catalog Client Script の type 別内訳を数えました。onLoad 41 / onChange 79 / onSubmit 8 / onCellEdit 0 です。onChange が最多で、ある変数の値が変わったときに別の変数を制御する使い方が中心でした。

Catalog Client Script の一覧は、次のURLで確認できます。

https://<YourInstance>/catalog_script_client_list.do?sysparm_query=active=true^ORDERBYtype

公式の Catalog client scripts(Zurich) に、カタログ用クライアントスクリプトの種別や、変数を扱うときの書き方の注意点がまとめられています。


件数で見るカタログのフォーム挙動

実際に件数を数えると、カタログのフォーム挙動が複数の設定の積み重ねでできていることが分かります。


今回確認した PDI(Zurich / OOTB・active 中心・2026-06-22 確認)では、次の件数でした。

  • Catalog UI Policy(catalog_ui_policy)… 101件(active 99)。applies_to=item 96 / set 5。

  • Catalog UI Policy Action(catalog_ui_policy_action)… 167件。制御値の内訳は mandatory=true 39 / read-only(disabled=true)15 / visible=false 57 です。「隠す(visible=false)」が最多で、通常版と同じ傾向でした。

  • Catalog Client Script(catalog_script_client)… 129件(active 128)。applies_to=item 100 / set 28。type 別は onLoad 41 / onChange 79 / onSubmit 8 / onCellEdit 0。

ここで数えているのは、あくまで OOTB の値です。実環境では、作り込んだカタログアイテムの数だけ Catalog UI Policy / Catalog Client Script が増えます。


ServiceNow のカタログのフォーム挙動のポイント

  • カタログの注文フォームの挙動は、主に Catalog UI Policy(条件→動作)と Catalog Client Script(JavaScript) の2本柱でできています。役割は通常版と同じですが、扱う対象がカタログ変数である点が違います。

  • カタログ用3テーブルは、通常版(sys_ui_policy / sys_script_client / sys_ui_policy_action)を継承した子テーブルです。表示・必須・読み取り(visible / mandatory / disabled)は親から引き継いで使います。

  • 適用先は applies_to(item=アイテム単位 / set=変数セット単位) で選びます。今回の PDI では item が多数派でした。

  • 効かせる場所は適用範囲フラグで切り替えます。applies_catalog / applies_req_item / applies_sc_task / applies_target_record の4つが、注文フォーム・RITM・タスク・生成先に対応します。OOTB ではほぼ「注文フォーム表示」でした。

  • Catalog Client Script は type(onLoad / onChange / onSubmit / onCellEdit)で実行タイミングを選びます。OOTB では onChange が最多でした。

カタログのフォーム挙動を調べるときは、まず「これは Catalog UI Policy の仕事か、Catalog Client Script の仕事か」を切り分けます。UI Policy なら catalog_ui_policy → catalog_ui_policy_action(visible/mandatory/disabled)の順に見ます。Client Script なら type と script を読みます。この順で確認すると迷いません。


実機を見て気づいたこと

  • Catalog Client Script の type=onChange は、変数の値が変わったときだけでなく、フォームの読み込み時にも1回走ります。「onLoadだけ実装すればいい」と思っていると、onChangeのスクリプトが読み込み直後にも動いて意図しない上書きが起きることがあるので、実務で書くときは気をつけたいポイントです。

  • catalog_ui_policy と catalog_script_client には、どちらも va_supported という固有フィールドがありました。名前から判断すると(推測です)、Virtual Agent(チャットボット型の注文フォーム)でも同じ UI Policy / Client Script を効かせるかどうかを制御するフラグのようで、通常のカタログフォームだけでなく会話型インターフェースまで設計の射程に入れていることがうかがえます。


次に読むなら

次に調べたいのは3つです。Catalog UI Policy と Catalog Client Script の実行順序(読込時・値変更時にどちらが先に走るか)。変数セット単位(applies_to=set)の適用が複数アイテムでどう効くか。そして g_form / g_scratchpad などカタログ専用の API です。同じ変数を Catalog UI Policy でも Catalog Client Script でも制御しているとき、最終的にどちらの指定が効くかは、実環境のトラブルで頻出します。通常フォーム側の仕組みは別記事「Client Script と UI Policy の違い」で扱っています。


用語

  • PDI:Personal Developer Instance(無料の検証用インスタンス)

  • OOTB:Out of the Box(初期設定のまま)

  • カタログ変数(Variable):カタログの注文フォームを構成する入力項目(item_option_new)

  • 変数セット(Variable Set):複数アイテムで再利用される変数のまとまり(item_option_new_set)

  • Catalog UI Policy:条件に応じてカタログ変数の表示/必須/読み取りを切り替える設定(catalog_ui_policy)

  • Catalog Client Script:カタログの注文フォーム上で動く JavaScript(catalog_script_client)

  • Leave alone(ignore):UI Policy Action で「その制御は触らない」を表す既定値

自分の環境で確認するときのURL

先頭に自分のインスタンスを付けると、同じ画面が開けます。

テーブル定義       : sys_db_object_list.do?sysparm_query=name=catalog_ui_policy^ORname=catalog_ui_policy_action^ORname=catalog_script_client
Catalog UI Policy  : catalog_ui_policy_list.do?sysparm_query=active=true^ORDERBYapplies_to
Catalog UI Policy Action: catalog_ui_policy_action_list.do?sysparm_query=ui_policy.catalog_item.nameISNOTEMPTY
Catalog Client Script   : catalog_script_client_list.do?sysparm_query=active=true^ORDERBYtype
固有フィールド      : sys_dictionary_list.do?sysparm_query=name=catalog_ui_policy^elementISNOTEMPTY

関連記事


検証範囲とおことわり

  • 確認した範囲:3テーブルの継承(カタログ版は通常版を継承する二段継承。最終的に sys_metadata=Application File)、カタログ固有フィールド数(catalog_ui_policy 11 / catalog_ui_policy_action 6 / catalog_script_client 11)、applies_to の値(item / set)、Catalog Client Script の type(4種・OOTB 実使用3種)、適用範囲フラグ4種の件数、各テーブルの全件/active件数、applies_to 分布、UI Policy Action の visible/mandatory/disabled 件数、type別件数、スクショ対象レコードの実値。すべて PDI(Zurich / 2026-06-22 確認)の OOTB で取得しています。

  • 確認していない範囲(断定しません):各スクリプト本文の挙動、Catalog UI Policy と Catalog Client Script の厳密な実行順序、g_form / g_scratchpad などカタログ専用 API の挙動、Service Portal と旧来UI(Desktop)での描画差、Catalog Builder 経由で作成した場合の保存先、ドメイン分離環境での適用範囲。これらは別記事で扱う予定です。

今回は PDI の OOTB(初期設定)を前提に、カタログのフォーム挙動を担うテーブルの構造を確認しました。実環境では、作り込んだカタログアイテムの数だけスクリプト・ポリシーの数・内容が変わります。

いいなと思ったら応援しよう!