<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>G_modal on SNow adventures</title>
    <link>https://www.snow-adventures.com/tags/g_modal/</link>
    <description>Recent content in G_modal on SNow adventures</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>© Samuel Meylan - 2020</copyright>
    <lastBuildDate>Sat, 12 Jul 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://www.snow-adventures.com/tags/g_modal/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Make workspace modals work with reference fields and UI pages</title>
      <link>https://www.snow-adventures.com/posts/make-workspace-modals-work-with-reference-fields-and-ui-pages/</link>
      <pubDate>Sat, 12 Jul 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.snow-adventures.com/posts/make-workspace-modals-work-with-reference-fields-and-ui-pages/</guid>
      <description>Fix issues with reference fields in workspace modals and build nicer confirm/alert dialogs inside UI pages.</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>If you&rsquo;ve ever tried to trigger a workspace modal from a list action, you’ve probably hit some quirks, especially when using reference fields. For example, calling <code>g_modal.showFields()</code> with a reference field works fine <strong>on a form</strong>, but breaks when launched from a list.</p>
<p>On top of that, if you’re trying to build a nice modal experience in a UI Page—something more modern than <code>alert()</code> or <code>confirm()</code>—you’ll quickly notice the default browser prompts aren’t great and the workspace modal APIs aren’t usable inside Jelly.</p>
<p>This post walks through both of these issues and shows how to fix them.</p>
<h2 id="problem-1-reference-fields-dont-work-from-list-modals">Problem 1: Reference fields don’t work from list modals</h2>
<p>Here’s a basic <code>g_modal.showFields()</code> call with a reference field, in a Workspace UI action / Action Assignment<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>This is in an Action Assignment of type List Action, Implemented as Client Scipt, and this script would go in the Client Script setion</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">fields</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">type</span><span class="o">:</span> <span class="s1">&#39;reference&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;caller_id&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">label</span><span class="o">:</span> <span class="nx">getMessage</span><span class="p">(</span><span class="s1">&#39;Who is the user?&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">mandatory</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">reference</span><span class="o">:</span> <span class="s1">&#39;sys_user&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">referringTable</span><span class="o">:</span> <span class="s1">&#39;incident&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">referringRecordId</span><span class="o">:</span> <span class="nx">g_form</span><span class="p">.</span><span class="nx">getUniqueValue</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">value</span><span class="o">:</span> <span class="nx">g_form</span><span class="p">.</span><span class="nx">getValue</span><span class="p">(</span><span class="s1">&#39;caller_id&#39;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="nx">displayValue</span><span class="o">:</span> <span class="nx">g_form</span><span class="p">.</span><span class="nx">getDisplayValue</span><span class="p">(</span><span class="s1">&#39;caller_id&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">g_modal</span><span class="p">.</span><span class="nx">showFields</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">title</span><span class="o">:</span> <span class="s2">&#34;Select a user&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">fields</span><span class="o">:</span> <span class="nx">fields</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">size</span><span class="o">:</span> <span class="s1">&#39;lg&#39;</span>
</span></span><span class="line"><span class="cl"><span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">fieldValues</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">g_form</span><span class="p">.</span><span class="nx">setValue</span><span class="p">(</span><span class="s1">&#39;caller_id&#39;</span><span class="p">,</span> <span class="nx">fieldValues</span><span class="p">.</span><span class="nx">updatedFields</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">value</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">g_form</span><span class="p">.</span><span class="nx">save</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>The problem is that <code>referringTable</code>, <code>referringRecordId</code>, and <code>name</code> all assume the context of a form. If you trigger this from a <strong>list button</strong>, you&rsquo;re missing the right record context, and it fails.</p>
<h3 id="solution-use-a-ui-page-inside-a-modal">Solution: use a UI Page inside a modal</h3>
<p>So, instead of using <code>g_modal.showFields()</code>, you can use <code>g_modal.showFrame()</code> to load a custom UI Page. That page gives you full control over inputs, including reference fields.</p>
<h4 id="step-1-create-a-ui-page">Step 1: create a UI page</h4>
<p>To keep things simple, let’s start with native <code>alert()</code> and <code>confirm()</code>.</p>
<p>Create a UI page, called in this example <code>select_author</code>, and add this to the HTML part:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="cp">&lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34; ?&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;j:jelly</span> <span class="na">trim=</span><span class="s">&#34;false&#34;</span> <span class="na">xmlns:j=</span><span class="s">&#34;jelly:core&#34;</span> <span class="na">xmlns:g=</span><span class="s">&#34;glide&#34;</span> <span class="na">xmlns:j2=</span><span class="s">&#34;null&#34;</span> <span class="na">xmlns:g2=</span><span class="s">&#34;null&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="nt">&lt;g:ui_reference</span> <span class="na">name=</span><span class="s">&#34;author&#34;</span> <span class="na">id=</span><span class="s">&#34;author&#34;</span> <span class="na">table=</span><span class="s">&#34;x_1588981_demo_authors&#34;</span> <span class="na">query=</span><span class="s">&#34;active=true&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl">	<span class="nt">&lt;g:dialog_buttons_ok_cancel</span> <span class="na">ok=</span><span class="s">&#34;return actionOK();&#34;</span> <span class="na">cancel=</span><span class="s">&#34;return cancel();&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/j:jelly&gt;</span>
</span></span></code></pre></div><p>And then this to the Client Script:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">actionOK</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Get the value from the reference field with ID &#39;author&#39;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">var</span> <span class="nx">authorId</span> <span class="o">=</span> <span class="nx">gel</span><span class="p">(</span><span class="s1">&#39;author&#39;</span><span class="p">).</span><span class="nx">value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// If no value is selected, show an alert and stop execution
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">authorId</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">alert</span><span class="p">(</span><span class="s2">&#34;Please select an author&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Ask the user for confirmation before proceeding
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="nx">confirm</span><span class="p">(</span><span class="s2">&#34;Are you sure you want to proceed?&#34;</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// In a real version, this would send the selected authorId back to the parent modal
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// For now, we just show a confirmation message
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">alert</span><span class="p">(</span><span class="s2">&#34;Confirmed with author: &#34;</span> <span class="o">+</span> <span class="nx">authorId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Prevent default form submission behavior
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">cancel</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Show a cancellation message and prevent default behavior
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">alert</span><span class="p">(</span><span class="s2">&#34;Action cancelled&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Your UI Page will also need a matching UI Page ACL to allow access. You will be asked when saving it the first time, but in case you want more information you can refer to ACL rule types documentation<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> and the article &ldquo;How to create ACL for UI page&rdquo; from theServiceNow Community<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> for details.</p>
<h4 id="step-2-call-the-page-from-workspace">Step 2: Call the page from Workspace</h4>
<p>On the UI Action / Action Assignment, replace the Client Script with the one below. It use the <code>g_modal.showFrame()</code> that use the UI page we created previously.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">onClick</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Open a UI Page inside a modal using g_modal.showFrame
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">g_modal</span><span class="p">.</span><span class="nx">showFrame</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">        <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;/x_1588981_demo_select_author.do&#39;</span><span class="p">,</span>  <span class="c1">// UI Page to load.  Note: the .do suffix is automatically added to the UI Page name
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">title</span><span class="o">:</span> <span class="s2">&#34;Select an author&#34;</span><span class="p">,</span>                <span class="c1">// Modal title
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">size</span><span class="o">:</span> <span class="s1">&#39;xl&#39;</span><span class="p">,</span>                               <span class="c1">// Modal width size
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">autoCloseOn</span><span class="o">:</span> <span class="s1">&#39;URL_CHANGED&#39;</span><span class="p">,</span>               <span class="c1">// Automatically close modal if iframe URL changes
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">callback</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">ret</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// If the user confirmed the modal
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="k">if</span> <span class="p">(</span><span class="nx">ret</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="c1">// Log the returned data (e.g., selected authorId)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>                <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Concerning the part <code>autoCloseOn: 'URL_CHANGED'</code>: the goal is to closes the modal automatically when the iframe navigates. This works nicely with the close pattern:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">close</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">href</span> <span class="o">+</span> <span class="s1">&#39;&amp;sysparm_next_pg=true&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This triggers the <code>URL_CHANGED</code> condition and closes the modal from within the iframe.</p>
<h2 id="problem-2-returning-values-and-closing-the-modal">Problem 2: Returning values and closing the modal</h2>
<p>If you try the button now, the UI page open in a modal, but if you select an author and click OK, nothing happens. This is because it lacks a mechanism to return values to the calling script.
<figure>
    <img loading="lazy" src="/img/workspaceModalsReferenceFields/modal_without_resize.png"/> <figcaption>
            Modal without resize
        </figcaption>
</figure>
</p>
<p>For this, the <code>iframeHelper</code> come to the rescue. This utility solves the communication with the Actoin Assignment using <code>window.postMessage()</code> to confirm or cancel modal interactions<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</p>
<h3 id="iframehelper-a-postmessage-helper-for-modals">iframeHelper: a postMessage helper for modals</h3>
<p>Here’s a UI Script (<code>iframeHelper</code>) that includes <code>confirm</code>, <code>cancel</code> methods. It is from the snpro blog<sup id="fnref1:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>, but I copied it here for convenience.</p>
<p>Simply create a new UI script:</p>
<ul>
<li>Script name:  <code>iframeHelper</code></li>
<li>UI Script: All&quot; types.</li>
<li>Script: copy/paste the code below</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> *  Script from 
</span></span></span><span class="line"><span class="cl"><span class="cm"> *  &#34;Workspace Modals - Working with UI Pages - SNPro.dev&#34;
</span></span></span><span class="line"><span class="cl"><span class="cm"> *   - https://snpro.dev/2023/11/20/workspace-modals-working-with-ui-pages/
</span></span></span><span class="line"><span class="cl"><span class="cm"> *  (c) Callum Ridley
</span></span></span><span class="line"><span class="cl"><span class="cm"> *  
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">iframeHelper</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nx">createPayload</span><span class="p">(</span><span class="nx">action</span><span class="p">,</span> <span class="nx">modalId</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">messageType</span><span class="o">:</span> <span class="s1">&#39;IFRAME_MODAL_MESSAGE_TYPE&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">modalAction</span><span class="o">:</span> <span class="nx">action</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">modalId</span><span class="o">:</span> <span class="nx">modalId</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">data</span><span class="o">:</span> <span class="p">(</span><span class="nx">data</span> <span class="o">?</span> <span class="nx">data</span> <span class="o">:</span> <span class="p">{})</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nx">pm</span><span class="p">(</span><span class="nb">window</span><span class="p">,</span> <span class="nx">payload</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">parent</span> <span class="o">===</span> <span class="nb">window</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">console</span><span class="p">.</span><span class="nx">warn</span><span class="p">(</span><span class="s1">&#39;Parent is missing. Is this called inside an iFrame?&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="nb">window</span><span class="p">.</span><span class="nx">parent</span><span class="p">.</span><span class="nx">postMessage</span><span class="p">(</span><span class="nx">payload</span><span class="p">,</span> <span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">function</span> <span class="nx">IFrameHelper</span><span class="p">(</span><span class="nb">window</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="p">.</span><span class="nb">window</span> <span class="o">=</span> <span class="nb">window</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">href</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="p">.</span><span class="nx">messageHandler</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">messageHandler</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="p">.</span><span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">&#39;message&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">messageHandler</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">IFrameHelper</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">messageHandler</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">messageType</span> <span class="o">!==</span> <span class="s1">&#39;IFRAME_MODAL_MESSAGE_TYPE&#39;</span> <span class="o">||</span> <span class="nx">e</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">modalAction</span> <span class="o">!==</span> <span class="s1">&#39;IFRAME_MODAL_ACTION_INIT&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="p">.</span><span class="nx">modalId</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">modalId</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">IFrameHelper</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">confirm</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">payload</span> <span class="o">=</span> <span class="nx">createPayload</span><span class="p">(</span><span class="s1">&#39;IFRAME_MODAL_ACTION_CONFIRMED&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">modalId</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">pm</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nb">window</span><span class="p">,</span> <span class="nx">payload</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">IFrameHelper</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">cancel</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">payload</span> <span class="o">=</span> <span class="nx">createPayload</span><span class="p">(</span><span class="s1">&#39;IFRAME_MODAL_ACTION_CANCELED&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">modalId</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">pm</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nb">window</span><span class="p">,</span> <span class="nx">payload</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">IFrameHelper</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">hideCloseButton</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">iframeRootNode</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nb">window</span><span class="p">.</span><span class="nx">frameElement</span><span class="o">?</span><span class="p">.</span><span class="nx">getRootNode</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nx">iframeRootNode</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kd">var</span> <span class="nx">scriptedModal</span> <span class="o">=</span> <span class="nx">iframeRootNode</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;sn-scripted-modal&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="nx">scriptedModal</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="kd">var</span> <span class="nx">nowModal</span> <span class="o">=</span> <span class="nx">scriptedModal</span><span class="p">.</span><span class="nx">shadowRoot</span><span class="o">?</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;now-modal&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="nx">nowModal</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                    <span class="kd">var</span> <span class="nx">modalFooter</span> <span class="o">=</span> <span class="nx">nowModal</span><span class="p">.</span><span class="nx">shadowRoot</span><span class="o">?</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;.now-modal-footer&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="k">if</span> <span class="p">(</span><span class="nx">modalFooter</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nx">modalFooter</span><span class="p">.</span><span class="nx">style</span> <span class="o">=</span> <span class="s1">&#39;display: none;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">IFrameHelper</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">autoResize</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">add</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">iframeRootNode</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nb">window</span><span class="p">.</span><span class="nx">frameElement</span><span class="o">?</span><span class="p">.</span><span class="nx">getRootNode</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">slotEl</span> <span class="o">=</span> <span class="nx">iframeRootNode</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s1">&#39;.slot-content&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">body</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">html</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="kd">var</span> <span class="nx">height</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="nx">body</span><span class="p">.</span><span class="nx">scrollHeight</span><span class="p">,</span> <span class="nx">body</span><span class="p">.</span><span class="nx">offsetHeight</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">html</span><span class="p">.</span><span class="nx">clientHeight</span><span class="p">,</span> <span class="nx">html</span><span class="p">.</span><span class="nx">scrollHeight</span><span class="p">,</span> <span class="nx">html</span><span class="p">.</span><span class="nx">offsetHeight</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">slotEl</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">height</span> <span class="o">=</span> <span class="p">(</span><span class="nx">height</span> <span class="o">+</span> <span class="mi">40</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;px&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="k">new</span> <span class="nx">IFrameHelper</span><span class="p">(</span><span class="nb">window</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}());</span>
</span></span></code></pre></div><p>You will get a warning message like this one, but you can safely click &ldquo;OK&rdquo;:</p>
<figure>
    <img loading="lazy" src="/img/workspaceModalsReferenceFields/message-ui-script.png"/> <figcaption>
            Message when saving the UI Script
        </figcaption>
</figure>

<h4 id="update-the-ui-page">Update the UI Page</h4>
<p>After creating the helper, update the the UI Page, by adding this line in the HTML part, in the jelly:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;g:requires</span> <span class="na">name=</span><span class="s">&#34;x_1588981_demo.iframeHelper.jsdbx&#34;</span><span class="nt">&gt;&lt;/g:requires&gt;</span>
</span></span></code></pre></div><p>Then adapt the Client Script part as follow:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// When the DOM is fully loaded, auto-resize the modal using the iframeHelper
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">$j</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">iframeHelper</span><span class="p">.</span><span class="nx">autoResize</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">actionOK</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">authorId</span> <span class="o">=</span> <span class="nx">gel</span><span class="p">(</span><span class="s1">&#39;author&#39;</span><span class="p">).</span><span class="nx">value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">authorId</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">alert</span><span class="p">(</span><span class="s2">&#34;Please select an author&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">confirm</span><span class="p">(</span><span class="s2">&#34;Are you sure you want to proceed?&#34;</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Send the selected authorId back to the parent modal using iframeHelper
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">iframeHelper</span><span class="p">.</span><span class="nx">confirm</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">            <span class="nx">authorId</span><span class="o">:</span> <span class="nx">authorId</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">cancel</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Cancel the modal and close it without returning data
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">iframeHelper</span><span class="p">.</span><span class="nx">cancel</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>As you might have noticed, we now:</p>
<ul>
<li>use the <code>autoresize</code> at the start of the Client Script, which resize the modal dynamically;</li>
<li>use <code>cancel</code> to close the modal (and return control to the calling button).</li>
<li>use <code>confirm</code> to send back the data to the calling button;</li>
</ul>
<p>As a reminder, the object you pass to iframeHelper.confirm() (e.g., { authorId }) is returned directly to the callback function in your Action Assignment. as <code>data</code> in this example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="nx">callback</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">ret</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// If the user confirmed the modal
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="nx">ret</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Log the returned data (e.g., selected authorId)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This data is passed directly to your callback. If you later use it in server-side code (like GlideAjax), be sure to validate it. Never trust client input blindly.</p>
<h2 id="problem-3-building-custom-alert-and-confirm-modals-in-ui-pages">Problem 3: Building custom alert and confirm modals in UI Pages</h2>
<p>At this point, you probably noticed that the alert and confirm message box are the standard one. Those native <code>alert()</code> and <code>confirm()</code> calls are functional but clunky. They don’t match the workspace UX, and you can’t use workspace modals directly in UI Pages.</p>
<figure>
    <img loading="lazy" src="/img/workspaceModalsReferenceFields/modal_with_alert.png"/> <figcaption>
            Modal with the standard browser alert message
        </figcaption>
</figure>

<p>Here’s how to build nicer modals with inline HTML and JavaScript.</p>
<p>Add the following code in the HTML part of the UI page:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="c">&lt;!-- Alert modal --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&#34;alertModal&#34;</span> <span class="na">style=</span><span class="s">&#34;display:none; position:fixed; left:0; top:0; width:100vw; height:100vh; background:rgba(0,0,0,0.4); z-index:9999;&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">&#34;background:white; padding:2em; margin:10% auto; width:300px; border-radius:10px; box-shadow:0 4px 16px #333;&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&#34;modalMessage&#34;</span><span class="nt">&gt;&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;button</span> <span class="na">onclick=</span><span class="s">&#34;hideAlertModal()&#34;</span><span class="nt">&gt;</span>OK<span class="nt">&lt;/button&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">&lt;!-- Confirm modal --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&#34;confirmModal&#34;</span> <span class="na">style=</span><span class="s">&#34;display:none; position:fixed; left:0; top:0; width:100vw; height:100vh; background:rgba(0,0,0,0.4); z-index:9999;&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">&#34;background:white; padding:2em; margin:10% auto; width:320px; border-radius:10px; box-shadow:0 4px 16px #333;&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&#34;confirmMessage&#34;</span><span class="nt">&gt;&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;button</span> <span class="na">id=</span><span class="s">&#34;confirmOKBtn&#34;</span><span class="nt">&gt;</span>OK<span class="nt">&lt;/button&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;button</span> <span class="na">id=</span><span class="s">&#34;confirmCancelBtn&#34;</span><span class="nt">&gt;</span>Cancel<span class="nt">&lt;/button&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/div&gt;</span>
</span></span></code></pre></div><p>These modal blocks use inline styles for layout and appearance. You can adjust the width or make them dynamic with JS if needed, but the fixed size works well in most cases.</p>
<p>Then add those functions in the Client Script</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// Show the alert modal with a given message
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">function</span> <span class="nx">showAlertModal</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Set the alert message content
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;modalMessage&#39;</span><span class="p">).</span><span class="nx">innerText</span> <span class="o">=</span> <span class="nx">message</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Make the alert modal visible
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;alertModal&#39;</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">&#39;block&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Hide the alert modal
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">function</span> <span class="nx">hideAlertModal</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;alertModal&#39;</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">&#39;none&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Show a custom confirm modal with a message and a callback for the user&#39;s choice
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">function</span> <span class="nx">showConfirmModal</span><span class="p">(</span><span class="nx">message</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">var</span> <span class="nx">modal</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmModal&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Set the confirm message content
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmMessage&#39;</span><span class="p">).</span><span class="nx">innerText</span> <span class="o">=</span> <span class="nx">message</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Make the confirm modal visible
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nx">modal</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">&#39;block&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// Internal function to clean up after user makes a choice
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="kd">function</span> <span class="nx">cleanUp</span><span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">modal</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">&#39;none&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Remove previous click handlers to avoid stacking
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmOKBtn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmCancelBtn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Run the callback with the user&#39;s choice (true or false)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">callback</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</span><span class="p">)</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// OK button confirms the action
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmOKBtn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="nx">cleanUp</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Cancel button cancels the action
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmCancelBtn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="nx">cleanUp</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>And replace the <code>alert</code> and <code>confirm</code> calls with the new functions:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">authorId</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">//alert(&#34;Please select an author&#34;);
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">showAlertModal</span><span class="p">(</span><span class="s2">&#34;Please select an author&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="cm">/*if (confirm(&#34;Are you sure you want to proceed?&#34;)) {
</span></span></span><span class="line"><span class="cl"><span class="cm">    // Send the selected authorId back to the parent modal using iframeHelper
</span></span></span><span class="line"><span class="cl"><span class="cm">    iframeHelper.confirm({
</span></span></span><span class="line"><span class="cl"><span class="cm">        authorId: authorId
</span></span></span><span class="line"><span class="cl"><span class="cm">    });
</span></span></span><span class="line"><span class="cl"><span class="cm">}
</span></span></span><span class="line"><span class="cl"><span class="cm">*/</span>
</span></span><span class="line"><span class="cl"><span class="nx">showConfirmModal</span><span class="p">(</span><span class="s2">&#34;Are you sure you want to continue?&#34;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">confirmed</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">confirmed</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">iframeHelper</span><span class="p">.</span><span class="nx">confirm</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">            <span class="nx">authorId</span><span class="o">:</span> <span class="nx">authorId</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Do nothing
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>Et voilà: you now have a nice message:</p>
<figure>
    <img loading="lazy" src="/img/workspaceModalsReferenceFields/nice_message.png"/> <figcaption>
            New modal message
        </figcaption>
</figure>

<h2 id="complete-working-example-of-the-ui-page">Complete, working example of the UI page</h2>
<p>Here is the complete and working example. This is this part you may want to copy/paste and adapt.</p>
<h3 id="html">HTML</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-XML" data-lang="XML"><span class="line"><span class="cl"><span class="cp">&lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34; ?&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;j:jelly</span> <span class="na">trim=</span><span class="s">&#34;false&#34;</span> <span class="na">xmlns:j=</span><span class="s">&#34;jelly:core&#34;</span> <span class="na">xmlns:g=</span><span class="s">&#34;glide&#34;</span> <span class="na">xmlns:j2=</span><span class="s">&#34;null&#34;</span> <span class="na">xmlns:g2=</span><span class="s">&#34;null&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;g:requires</span> <span class="na">name=</span><span class="s">&#34;x_1588981_demo.iframeHelper.jsdbx&#34;</span><span class="nt">&gt;&lt;/g:requires&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;g:ui_reference</span> <span class="na">name=</span><span class="s">&#34;author&#34;</span> <span class="na">id=</span><span class="s">&#34;author&#34;</span> <span class="na">table=</span><span class="s">&#34;x_1588981_demo_authors&#34;</span> <span class="na">query=</span><span class="s">&#34;active=true&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;g:dialog_buttons_ok_cancel</span> <span class="na">ok=</span><span class="s">&#34;return actionOK();&#34;</span> <span class="na">cancel=</span><span class="s">&#34;return cancel();&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c">&lt;!-- Alert modal --&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&#34;alertModal&#34;</span> <span class="na">style=</span><span class="s">&#34;display:none; position:fixed; left:0; top:0; width:100vw; height:100vh; background:rgba(0,0,0,0.4); z-index:9999;&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">&#34;background:white; padding:2em; margin:10% auto; width:300px; border-radius:10px; box-shadow:0 4px 16px #333;&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&#34;modalMessage&#34;</span><span class="nt">&gt;&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;button</span> <span class="na">onclick=</span><span class="s">&#34;hideAlertModal()&#34;</span><span class="nt">&gt;</span>OK<span class="nt">&lt;/button&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c">&lt;!-- Confirm modal --&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&#34;confirmModal&#34;</span> <span class="na">style=</span><span class="s">&#34;display:none; position:fixed; left:0; top:0; width:100vw; height:100vh; background:rgba(0,0,0,0.4); z-index:9999;&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">&#34;background:white; padding:2em; margin:10% auto; width:320px; border-radius:10px; box-shadow:0 4px 16px #333;&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&#34;confirmMessage&#34;</span><span class="nt">&gt;&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;button</span> <span class="na">id=</span><span class="s">&#34;confirmOKBtn&#34;</span><span class="nt">&gt;</span>OK<span class="nt">&lt;/button&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&lt;button</span> <span class="na">id=</span><span class="s">&#34;confirmCancelBtn&#34;</span><span class="nt">&gt;</span>Cancel<span class="nt">&lt;/button&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/div&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/j:jelly&gt;</span>
</span></span></code></pre></div><h3 id="client-script">client script</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// When the DOM is fully loaded, auto-resize the modal using the iframeHelper
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nx">$j</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">iframeHelper</span><span class="p">.</span><span class="nx">autoResize</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">actionOK</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">authorId</span> <span class="o">=</span> <span class="nx">gel</span><span class="p">(</span><span class="s1">&#39;author&#39;</span><span class="p">).</span><span class="nx">value</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">authorId</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">showAlertModal</span><span class="p">(</span><span class="s2">&#34;Please select an author&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">showConfirmModal</span><span class="p">(</span><span class="s2">&#34;Are you sure you want to continue?&#34;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">confirmed</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="nx">confirmed</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">iframeHelper</span><span class="p">.</span><span class="nx">confirm</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">                <span class="nx">authorId</span><span class="o">:</span> <span class="nx">authorId</span>
</span></span><span class="line"><span class="cl">            <span class="p">});</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// Do nothing
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">cancel</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Cancel the modal and close it without returning data
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">iframeHelper</span><span class="p">.</span><span class="nx">cancel</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Show the alert modal with a given message
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">function</span> <span class="nx">showAlertModal</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Set the alert message content
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;modalMessage&#39;</span><span class="p">).</span><span class="nx">innerText</span> <span class="o">=</span> <span class="nx">message</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Make the alert modal visible
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;alertModal&#39;</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">&#39;block&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Hide the alert modal
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">function</span> <span class="nx">hideAlertModal</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;alertModal&#39;</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">&#39;none&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="c1">// Show a custom confirm modal with a message and a callback for the user&#39;s choice
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">function</span> <span class="nx">showConfirmModal</span><span class="p">(</span><span class="nx">message</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">modal</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmModal&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Set the confirm message content
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmMessage&#39;</span><span class="p">).</span><span class="nx">innerText</span> <span class="o">=</span> <span class="nx">message</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Make the confirm modal visible
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">modal</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">&#39;block&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Internal function to clean up after user makes a choice
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">function</span> <span class="nx">cleanUp</span><span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">modal</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="s1">&#39;none&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Remove previous click handlers to avoid stacking
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmOKBtn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmCancelBtn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// Run the callback with the user&#39;s choice (true or false)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">callback</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</span><span class="p">)</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// OK button confirms the action
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmOKBtn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">cleanUp</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Cancel button cancels the action
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;confirmCancelBtn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">cleanUp</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="final-notes">Final Notes</h2>
<ul>
<li>The UI Page uses <code>iframeHelper.autoResize()</code> to dynamically adjust height.</li>
<li>This pattern works well for modal workflows launched from Workspace list buttons<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>.</li>
<li>It’s a reliable but not officially documented pattern—test thoroughly.</li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://www.servicenow.com/community/next-experience-articles/how-to-use-ui-actions-in-workspaces/ta-p/2331988#showFields">How to use UI Actions in Workspaces – servicenow.com</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://www.servicenow.com/docs/bundle/yokohama-platform-security/page/administer/contextual-security/concept/acl-rule-types.html">ACL rule types – servicenow.com</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://www.servicenow.com/community/developer-forum/how-to-create-acl-for-ui-page/m-p/1624054">How to create ACL for UI page – SN Community</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://snpro.dev/2023/11/20/workspace-modals-working-with-ui-pages/">Workspace modals: Working with UI Pages – snpro.dev</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>Based on implementation in declarative action <code>assign_to_apartement</code>, which filters selected records and passes them via GlideAjax.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]></content:encoded>
    </item>
    
  </channel>
</rss>
