CSM Workspace – Modal popup validation not stopping submit (UI Page + UI Builder approach)

AviKadam
Mega Contributor

Click to collapse CRM and Industry solutions category

Hi everyone,

I am working on a requirement in CSM Workspace where I need to implement a modal popup that contains:

  • Notes (mandatory)
  • Date/Time (mandatory, should not allow past date)

On clicking a button from the Case form:

  • A modal popup opens
  • User fills both fields
  • On Submit → values should update fields on the Case record

Current Approach (UI Action + UI Page + Glide Ajax)

  • Workspace UI Action → opens modal using "g_model.showframe"
  • UI Page contains form (text area + datetime)
  • Client script performs validation
  • Script Include updates the case record

Issue

Validation is working (error message shows), but:

 The modal still closes even when validation fails


Expected Behavior

  • If fields are empty → modal should NOT close
  • If date is in past → modal should NOT close
  • Modal should only close after successful save

What I tried

  • Using "return false" in submit function
  • Controlling button behavior
  • Handling validation before GlideAjax call

Still seeing inconsistent modal behavior in Workspace.

 

Sharing the full code base -

 

UI action-

function onClick(g_form) {

var sysId = g_form.getUniqueValue();

g_modal.showFrame({
title: "Enter Information for Manual ORT",
url: "/sn_customerservice_openmanualort_InfoDialog.do?sysparm_sys_id=" + sysId,
type: "page",
size: "lg",
height: "280px"
});
}

 

UI Page-

HTML

<?xml version="1.0" encoding="utf-8" ?>

<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
    <style>
        /* Removes the vertical scrollbar inside the modal iframe */
        html,
        body {
            overflow: hidden !important;
        }

        /* For some Workspace versions */
        .now-modal-body,
        now-modal-body {
            overflow-y: hidden !important;
        }

        /* Prevent inner divs from forcing scrollbars */
        #ort_wrapper {
            overflow: hidden !important;
        }
    </style>
    <div style="padding: 5px; font-family: Arial, sans-serif, max-width: 500px; margin: auto;">

        <j:set var="jvar_sysid" value="${sysparm_sys_id}" />
        <g:ui_form>
            <div style="margin-bottom: 16px; font-family: Arial, sans-serif">
                <label for="info_text" style="display:block; font-weight:bold; margin-bottom:6px;">
                    Notes / Comments <span style="color:red;">*</span>
                </label>
                <textarea id="info_text" name="info_text" rows="4" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px; box-sizing:border-box;" placeholder="Enter your notes here..."></textarea>
            </div>

            <div style="margin-bottom: 20px;  font-family: Arial, sans-serif">
                <label for="info_datetime" style="display:block; font-weight:bold; margin-bottom:6px;">
                    Scheduled Date / Time <span style="color:red;">*</span>
                </label>
                <input type="datetime-local" id="info_datetime" name="info_datetime" style="width:100%; padding:8px; border:1px solid #ccc; border-radius:4px; box-sizing:border-box;" />
            </div>

            <div id="error_msg" style="color:red; margin-bottom:12px; display:none;"></div>

            <div style="text-align:right;">
                <button onclick="cancelDialog()" style="margin-right:10px; padding:8px 16px; border:1px solid #ccc;
               background:#fff; border-radius:4px; cursor:pointer;">
                    Cancel
                </button>
                <!-- <button onclick="submitDialog()" style="padding:8px 16px; background:#0070d2; color:#fff;
               border:none; border-radius:4px; cursor:pointer;">
                    Submit
                </button> -->
                <button id="submit_btn" onclick="return submitDialog()" style="padding:8px 16px; background:#0070d2; color:#fff; border:none; border-radius:4px; cursor:pointer;">
                    Submit
                </button>
            </div>

            <!-- <div style="text-align:right;">
                <button type="button" onclick="cancelDialog()" style="margin-right:10px; padding:8px 16px; border:1px solid #ccc;
               background:#fff; border-radius:4px; cursor:pointer;">
                    Cancel
                </button>

                <button type="button" onclick="submitDialog()" style="padding:8px 16px; background:#0070d2; color:#fff;
               border:none; border-radius:4px; cursor:pointer;">
                    Submit
                </button>
            </div> -->

        </g:ui_form>

    </div>
</j:jelly>
 
Client Script-
function submitDialog() {
    try {

        var notes = document.getElementById('info_text').value.trim();
        var datetime = document.getElementById('info_datetime').value;
        var errorDiv = document.getElementById('error_msg');
        var submitBtn = document.getElementById("submit_btn");
        if (!notes || !datetime) {
            errorDiv.style.display = 'block';
            errorDiv.style.color = "red";
            errorDiv.innerHTML = 'Both fields are required before submitting.';
            return;
        }

        if (!validateORTDate()) {
            //submitBtn.disabled = true;
            submitBtn.style.display = 'none';
            //return; // stop submit
        }

        errorDiv.style.display = 'none';

        var sysId = getParameterByName('sysparm_sys_id');

        if (!sysId) {
            alert("ERROR: sys_id is empty");
            return;
        }

        var ga = new window.parent.GlideAjax('sn_customerservice.CaseInfoDialogAjax');

        ga.addParam('sysparm_name', 'saveInfo');
        ga.addParam('sysparm_sys_id', sysId);
        ga.addParam('sysparm_notes', notes);
        ga.addParam('sysparm_datetime', datetime);

        ga.getXMLAnswer(function(answer) {

            if (answer === 'success') {
                try {
                    GlideDialogWindow.get().destroy();
                    //top.NOW.modal.close();
                    //g_modal.hide();
                } catch (e) {
                    window.close();
                }

                if (window.parent && window.parent.g_form) {
                    window.parent.g_form.reload();
                }

            } else {
                errorDiv.style.display = 'block';
                errorDiv.style.color = "red";
                errorDiv.innerHTML = 'Save failed. Please try again.';
            }
        });

        return false;

    } catch (e) {
        alert("inside catch block" + e);
    }

}
function cancelDialog() {
    // try {
    //     GlideDialogWindow.get().destroy();
    // } catch (e) {
    //     window.close();
    // }
    top.NOW.modal.close();
    //g_modal.hide();
}

function getParameterByName(name) {
    var url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)");
    var results = regex.exec(url);
    if (!results) return "";
    if (!results[2]) return "";
    return decodeURIComponent(results[2].replace(/\+/g, " "));
}

function validateORTDate() {
    var dtField = document.getElementById("info_datetime");
    var errorDiv = document.getElementById("error_msg");

    var entered = dtField.value;
    if (!entered) return true; // nothing to validate

    var selectedDate = new Date(entered);
    var now = new Date();

    // Compare selected date with current date/time
    if (selectedDate < now) {

        dtField.value = "";
        errorDiv.style.display = 'block';
        errorDiv.style.color = "red";
        errorDiv.innerHTML = "Only current or future date/time can be selected.";
        return false;
    }

    // Hide error if valid
    errorDiv.style.display = "none";
    return true;
}
 
 
 
Script Include- Client callable is enabled and values are being updated as per requirement
 
var CaseInfoDialogAjax = Class.create();
CaseInfoDialogAjax.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {

    saveInfo: function() {
        var sysId = this.getParameter('sysparm_sys_id');
        var notes = this.getParameter('sysparm_notes');
        var datetime = this.getParameter('sysparm_datetime');

        if (!sysId) {
            return 'error: missing sys_id';
        }
        var gr = new GlideRecord('sn_customerservice_case');
        if (gr.get(sysId)) {

            gr.setValue('u_manual_ort_reason', notes);
            gr.setValue('u_sap_manual_ort', datetime);

            gr.update();
            return 'success';
        }

        return 'error: record not found';
    },

    type: 'CaseInfoDialogAjax'
});
 
 This approach is working, but I am not able to handle the "submit" and "cancel" buttons they get closed even if there is any applied validation.
 
<div style="text-align:right;">
                <button onclick="cancelDialog()" style="margin-right:10px; padding:8px 16px; border:1px solid #ccc;
               background:#fff; border-radius:4px; cursor:pointer;">
                    Cancel
                </button>
                <!-- <button onclick="submitDialog()" style="padding:8px 16px; background:#0070d2; color:#fff;
               border:none; border-radius:4px; cursor:pointer;">
                    Submit
                </button> -->
                <button id="submit_btn" onclick="return submitDialog()" style="padding:8px 16px; background:#0070d2; color:#fff; border:none; border-radius:4px; cursor:pointer;">
                    Submit
                </button>
            </div>

            <!-- <div style="text-align:right;">
                <button type="button" onclick="cancelDialog()" style="margin-right:10px; padding:8px 16px; border:1px solid #ccc;
               background:#fff; border-radius:4px; cursor:pointer;">
                    Cancel
                </button>

                <button type="button" onclick="submitDialog()" style="padding:8px 16px; background:#0070d2; color:#fff; border:none; border-radius:4px; cursor:pointer;">
                    Submit
                </button>
            </div> -->
 
 
The comment "div" when enabled makes the validation applied in client script work, but the "popup" stops closing on click of "submit" and "cancel".

Questions

  1. Is using UI Page + g_modal the correct approach in Workspace?
  2. How can we properly stop modal from closing on validation failure?
  3. Is there a recommended way to implement this using UI Builder (Modal component + data resource)?

Any guidance or best practices would be really helpful.

Thanks!

 

0 REPLIES 0