UI Script を Client Script から呼び出す

YamaT
Tera Contributor

こんにちは。

複数のClient Scriptで、同じ処理を行うことがあるので、UI Scriptで共通関数化しました。

UI Type が何であっても、一つのClient Scriptで一つのUI Scripを呼び出す最適な方法はないでしょうか?

 

UI Typeごとに設定を分けて作るしかないのでしょうか?(共通化の意味が薄れるので、望ましくありません)

 

詳細:

テーブル上にChoice項目が複数あり、選択肢の組み合わせによって、特定の項目に値を入力したいです。

各Choice項目の onChange の Client Script ( UI Type = 「Desktop」「Service Portal」の両方)で、同じ処理を行いたいです。

しかし、UI Scriptの呼び出しに問題があり、とても困っています。

 

  1. g_ui_scripts を利用して呼び出すとき:
    • Service Portal →OK
    • Desktop →Error
      • onChange script error: ReferenceError: g_ui_scripts is not defined function () { [native code] }
  2. ScriptLoader を利用して呼び出すとき:
    • Service Portal →Error
      • (g_env) [SCRIPT:EXEC] Error while running Client Script <Clinet Script Name> ReferenceError: ScriptLoader is not defined
    • Desktop →OK

 

 

UI Script (ScriptLoader で呼び出す前提

・Application:<scope>(※1)

※1:<scope>は、適当なApplication名に置き換えて読んでください

 

 

var <scope> = <scope> || {};

<scope>.calcMoney = (function() {
	"use strict";

	function getMoney(a, b) {
		var money = 0;
		if(a == 1 || b == 1}{
			money = 10000;
		}esle{
			money = 20000;
		}
		return money;
	}

	return {

		incrementAndReturnMoney: function(a, b) {
			return getMoney(a, b);
		},

		type:  "calcMoney"
	};
})();

 

 

 

Client Script (ScriptLoader で呼び出す前提

・Application:<scope>

・UI Type:All

・Type:onChange

・Field name:a

 

 

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
   if (isLoading || newValue === '') {
      return;
   }
	ScriptLoader.getScripts('<scope>.calcMoney.jsdbx', function () {
		var a = g_form.getValue('u_a');
		var b = g_form.getValue('u_b');
		var result = 0;
		result = <scope>.calcMoney.incrementAndReturnMoney(a, b);
		g_form.setValue("u_test_string", result);
		console.log(result);
	});
}

 

 

 

どうぞよろしくお願いいたします。

1 件の受理された解決策

iwai
Giga Sage

ScriptLoaderとg_ui_scriptsで共通のUIScriptを使う例を、少々無理やり作ってみました。どちらでも動作することを確認しましたが、この方法が安全で正しいのかはわかりません。
UI Scriptを使わないで、ClientScriptのGlobal変数 "globalThis"にfunctionを登録する方法も場合によっては良いかもしれません。

以下の例は、IncidentのClientScriptで、DesktopとPortalで動作する例です。

UI Script
Script Name: "test_incident_script10"
Application: "sn_itsm_spoke"
UI Type: All

(function(t) {
    t.testok3 = 'testok';

    function getMoney(a, b) {
        var money = 0;
        if (a == 1 || b == 1) {
            money = 10000;
        } else {
            money = 20000;
        }
        return money;
    }
	function incrementAndReturnMoney(a, b) {
        return getMoney(a, b);
    }
    t.sn_itsm_spoke = {};
    t.sn_itsm_spoke.test_incident_script10 = { // Desktop
		incrementAndReturnMoney: incrementAndReturnMoney,
		testok4: 'Desktop ok',
		type: "test_incident_script10"
	};

    return {
        test_incident_script10: { // Portal
            incrementAndReturnMoney: incrementAndReturnMoney,
            testok2: 'Portal ok',
            type: "test_incident_script10"
        }
    };
})(this);

 

Client Script
Name: "Test Load Script"
Table: "incident"
UI Type: All
Type: onLoad

function onLoad() {
    function myCallback(myScript) {
        debugger;
        if (typeof myScript === 'undefined' && typeof sn_itsm_spoke !== 'undefined') {
            myScript = sn_itsm_spoke;
        }
        var a = '1';
        var b = '1';
        var result = 0;
        result = myScript.test_incident_script10.incrementAndReturnMoney(a, b);
        g_form.setValue("short_description", result);
        console.log(result);
    }
    try {
        if (typeof ScriptLoader !== 'undefined' && ScriptLoader && typeof ScriptLoader.getScripts === 'function') {
            ScriptLoader.getScripts('sn_itsm_spoke.test_incident_script10.jsdbx', myCallback);
        } else if (typeof g_ui_scripts !== 'undefined' && g_ui_scripts && typeof g_ui_scripts.getUIScript === 'function') {
            g_ui_scripts.getUIScript('sn_itsm_spoke.test_incident_script10').then(myCallback);
        }
    } catch (e) {}
}

 

元の投稿で解決策を見る

3件の返信3

Palash_Sarkar
ServiceNow Employee
ServiceNow Employee

@YamaT 様

"テーブル上にChoice項目が複数あり、選択肢の組み合わせによって、特定の項目に値を入力したいです。"

スクリプトを生成しないで、フィールドの依存関係を設定することで、上記の構成できるかもしれません。以下のURLを参考にしてください。
https://docs.servicenow.com/ja-JP/bundle/washingtondc-platform-administration/page/administer/field-...

 

コミュニティ質問を参照にしてください。

https://www.servicenow.com/community/%E9%96%8B%E7%99%BA%E8%80%85%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A9...

@Palash_Sarkar 様

ご返信ありがとうございます!

 

少し異なる意図で伝わってしまったようです。大変失礼しました。

 

実施したいことは、「Field_A」「Field_B」の選択パターンによって、Choice以外の項目である「Result」に値を設定したい。ということでした。

こちらの実現方法はありますでしょうか?

 

※Resultは、<String>型や、<Reference>型などを想定

YamaT_2-1715069242212.png

 

 

<おまけ>

また、この質問の主題は「以下の組み合わせで全く同じ処理を行っているので、1つにまとめたい。共通化したい」ということでした。

  • Client Script <onChange>
  • Client Script <onSubmit>

×

  • Portal 画面
  • Core UI 画面

 

ですが、下記をたどった結果、「できない」と判断しました。

https://www.servicenow.com/community/now-platform-forum/can-i-write-common-code-for-2-client-scripts...

→Client Scriptを共通化したいのであれば、UI Scriptを使えば良い。

 

https://docs.servicenow.com/csh?topicname=c_UIScripts.html&version=latest

→UI ScriptをClient Scriptで呼び出す場合は「g_ui_scripts」を使うと良い。

 

https://docs.servicenow.com/csh?topicname=GUIScriptsAPI.html&version=latest

→「g_ui_scripts」は、Workspaceと、Service Portalでしか使えず、Core UIでは利用できない。

iwai
Giga Sage

ScriptLoaderとg_ui_scriptsで共通のUIScriptを使う例を、少々無理やり作ってみました。どちらでも動作することを確認しましたが、この方法が安全で正しいのかはわかりません。
UI Scriptを使わないで、ClientScriptのGlobal変数 "globalThis"にfunctionを登録する方法も場合によっては良いかもしれません。

以下の例は、IncidentのClientScriptで、DesktopとPortalで動作する例です。

UI Script
Script Name: "test_incident_script10"
Application: "sn_itsm_spoke"
UI Type: All

(function(t) {
    t.testok3 = 'testok';

    function getMoney(a, b) {
        var money = 0;
        if (a == 1 || b == 1) {
            money = 10000;
        } else {
            money = 20000;
        }
        return money;
    }
	function incrementAndReturnMoney(a, b) {
        return getMoney(a, b);
    }
    t.sn_itsm_spoke = {};
    t.sn_itsm_spoke.test_incident_script10 = { // Desktop
		incrementAndReturnMoney: incrementAndReturnMoney,
		testok4: 'Desktop ok',
		type: "test_incident_script10"
	};

    return {
        test_incident_script10: { // Portal
            incrementAndReturnMoney: incrementAndReturnMoney,
            testok2: 'Portal ok',
            type: "test_incident_script10"
        }
    };
})(this);

 

Client Script
Name: "Test Load Script"
Table: "incident"
UI Type: All
Type: onLoad

function onLoad() {
    function myCallback(myScript) {
        debugger;
        if (typeof myScript === 'undefined' && typeof sn_itsm_spoke !== 'undefined') {
            myScript = sn_itsm_spoke;
        }
        var a = '1';
        var b = '1';
        var result = 0;
        result = myScript.test_incident_script10.incrementAndReturnMoney(a, b);
        g_form.setValue("short_description", result);
        console.log(result);
    }
    try {
        if (typeof ScriptLoader !== 'undefined' && ScriptLoader && typeof ScriptLoader.getScripts === 'function') {
            ScriptLoader.getScripts('sn_itsm_spoke.test_incident_script10.jsdbx', myCallback);
        } else if (typeof g_ui_scripts !== 'undefined' && g_ui_scripts && typeof g_ui_scripts.getUIScript === 'function') {
            g_ui_scripts.getUIScript('sn_itsm_spoke.test_incident_script10').then(myCallback);
        }
    } catch (e) {}
}