Ui Scripts - how to make it work?

francescosa
Tera Contributor

Hello,

 

I just created an UI Script to standardize the popup in my portal.

The code will be something like: 

var OER_ModalUtils = (function() {

  /**
   * @typedef {Object} PopupConfig
   *
   * @property {'info'|'confirm'} type
   *   - 'info'    : single OK button, non-blocking by nature.
   *   - 'confirm' : OK and Cancel buttons.
   *
   * @property {string} messageIdBody
   *   sys_ui_message key for the popup body text (required).
   *   Resolved via getMessage; falls back to the raw key if no translation is found.
   *
   * @property {string} [messageIdTitle]
   *   sys_ui_message key for the popup title.
   *   Only rendered in backoffice — ignored on Service Portal.
   *
   * @property {string} [labelConfirm]
   *   sys_ui_message key for the confirm/OK button label. Defaults to getMessage('Confirm').
   *   Only rendered in backoffice — ignored on Service Portal.
   *
   * @property {string} [labelCancel]
   *   sys_ui_message key for the cancel button label. Defaults to getMessage('Cancel').
   *   Only rendered in backoffice (confirm type only) — ignored on Service Portal.
   *
   * @property {Function} [onConfirm]
   *   Optional callback invoked when the user clicks the confirm button.
   *   Receives no arguments. If omitted, the modal simply closes.
   *
   * @property {Function} [onCancel]
   *   Optional callback invoked when the user clicks Cancel or dismisses the modal.
   *   Use this to implement any blocking or reset logic (e.g. field reset, submit cancel).
   *   Receives no arguments.
   *
   * @property {string} [caller]
   *   Optional free-text identifier of the calling context (e.g. 'field_change', 'activate_button').
   *   Not used internally — available for logging or conditional logic in callbacks.
   */

  /**
   * Displays a popup according to the provided configuration.
   * Delegates to spModal on Service Portal, GlideModal on backoffice.
   *
   * @memberof OER_ModalUtils
   * @Param   {PopupConfig} config - Declarative configuration object for the popup.
   * @returns {void}
   */
  function show(config) {
    if (!config || !config.messageIdBody) {
      console.error('[OER_ModalUtils] - show() called without a required messageIdBody.');
      return;
    }

    if (config.type === 'confirm' && !config.onConfirm && !config.onCancel) {
      console.warn('[OER_ModalUtils] - Confirmation popup without onConfirm or onCancel callback. Buttons will simply close the modal.');
    }

    var type     = config.type === 'confirm' ? 'confirm' : 'info';
    var bodyText = getMessage(config.messageIdBody);

    if (typeof spModal !== 'undefined') {
      _showSpModal(type, bodyText, config);
    } else if (typeof GlideModal !== 'undefined') {
      _showGlideModal(type, bodyText, config);
    } else {
      console.error('[OER_ModalUtils] - No supported modal API found in this context.');
    }
  }

  /**
   * Renders the popup using spModal (Service Portal context).
   * Title and button labels are not supported by the standard spModal API and are omitted.
   *
   * @private
   * @Param   {'info'|'confirm'} type
   * @Param   {string}           bodyText - Resolved body message.
   * @Param   {PopupConfig}      config
   * @returns {void}
   */
  function _showSpModal(type, bodyText, config) {
    if (type === 'info') {
      spModal.alert(bodyText).then(function() {
        if (typeof config.onConfirm === 'function') config.onConfirm();
      });
    } else {
      spModal.confirm(bodyText).then(function(confirmed) {
        if (confirmed) {
          if (typeof config.onConfirm === 'function') config.onConfirm();
        } else {
          if (typeof config.onCancel === 'function') config.onCancel();
        }
      });
    }
  }

  /**
   * Renders the popup using GlideModal (backoffice context).
   * Uses glide_modal_confirm for 'confirm' type, glide_modal_info for 'info' type.
   *
   * @private
   * @Param   {'info'|'confirm'} type
   * @Param   {string}           bodyText - Resolved body message.
   * @Param   {PopupConfig}      config
   * @returns {void}
   */
  function _showGlideModal(type, bodyText, config) {
    var titleText   = config.messageIdTitle ? getMessage(config.messageIdTitle) : '';
    var confirmText = config.labelConfirm   ? getMessage(config.labelConfirm)   : getMessage('Confirm');
    var cancelText  = config.labelCancel    ? getMessage(config.labelCancel)    : getMessage('Cancel');

    var modal = new GlideModal(type === 'confirm' ? 'glide_modal_confirm' : 'glide_modal_info');

    if (titleText) modal.setTitle(titleText);

    modal.setPreference('body',                bodyText);
    modal.setPreference('buttonLabelComplete', confirmText);
    modal.setPreference('onPromptComplete', function() {
      modal.destroy();
      if (typeof config.onConfirm === 'function') config.onConfirm();
    });

    if (type === 'confirm') {
      modal.setPreference('buttonLabelCancel', cancelText);
      modal.setPreference('onPromptCancel', function() {
        modal.destroy();
        if (typeof config.onCancel === 'function') config.onCancel();
      });
    }

    modal.render();
  }

  return {
    show: show
  };

})();

 

The script, configured with "ui type: desktop" and "global:true" was working perfectly in my backoffice though a "client script" and "Ui action" but now I need to activate it also in the service portal.


I changed the  "ui type" to all and... everything stop to work.

The global option disappeared and in the backoffice I'll receive an error saying "ReferenceError: OER_ModalUtils is not defined"

 

I've tried everyting but nothing seems to work.

 

My ui action was:

const util = new global.OER_global_util();
const nri = current.u_procedural_code_number;

if (util.isFormatContractDuplicate(nri)) {
    OER_ModalUtils.show({
        type: 'confirm',
        messageIdTitle: 'eba_formatContract_pupup_title',
        messageIdBody: 'eba_formatContract_pupup_body_2',
        labelConfirm: 'Confirm',
        labelCancel: 'Cancel',
        onConfirm: function() {
            done();
        },
        onCancel: function() {
            current.setAbortAction(true);
        }
    });
} else {
    done();
}

function done() {
    current.update();
    action.setRedirectURL(current);
}

 

The client script, is (after thousand of try so probably now is not really good):

 

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
    try {
        if (isLoading || newValue === '') {
            return;
        }

        const showPopup = function() {
            OER_ModalUtils.show({
                type: 'info',
                messageIdTitle: 'eba_formatContract_pupup_title',
                messageIdBody: 'eba_formatContract_pupup_body_2',
                labelConfirm: 'Confirm',
                onConfirm: function() {},
            });
        }

        const util = new GlideAjax('OER_global_util');
        util.addParam('sysparm_name', 'isFormatContractDuplicate_ajax');
        util.addParam('sysparm_nri', newValue);
        util.getXMLAnswer(function(res) {
            try {
                console.log("%c[HERE][res]", "color: pink", res)
                if (res) {
                    if (!OER_ModalUtils && g_ui_scripts) {
                        g_ui_scripts.getUIScript('myUIScript').then(function(script) {
                            showPopup()
                        }, function() {
                            console.log('The script did not load');
                        });
                    } else {
						showPopup()
					}

                    console.log("%c[HERE][7]", "color: pink")
                }
            } catch (e) {
                console.error("[EBA - FORMAT CONTRACT][GLIDE AJAX] - ", e)
            }
        })
    } catch (e) {
        console.error("[EBA - FORMAT CONTRACT] - ", e)
    }
}

 

Any suggestion? 
The documentation said to add the script as dependences but I really need to have it available everywhere and, also, the dependence field is never present.

I'm using Australia release.


Thanks

0 REPLIES 0