- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-31-2025 03:27 PM
Good evening all!
I am currently trying to configure a pop-up window/prompt that displays when an ad hoc catalog task is created from RITM - the window would bring up the Assignment Group field so they can select the proper team to assign this new task to. Here is what I have done so far:
- Created a UI action button on RITM that creates the SC task. It also sets a boolean field called "Ad Hoc Task" to true on the SC task form when the task is inserted.
- I then created a UI page called "Assignment_Group_Prompt" with the following HTML:
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-02-2025 06:00 PM
Here is how I would do it...
UI Action (just the basics listed here):
Action name = u_acme_create_ad_hoc_task
Form button = checked
Show update = checked
Client = checked
Onclick = uAcmeConfirmAdHocTask();
Script
function uAcmeConfirmAdHocTask() {
//are there unsaved values?
if (g_form.modified) {
//the form data has been modified but not saved yet so warn the user
var modalWindow = new GlideModal("glide_confirm_standard"); //SN OOTB confirm dialog
modalWindow.setTitle("Create Ad Hoc Task");
modalWindow.setBackdropStatic(true); //remain open when user clicks outside of the window
modalWindow.setWidth(600);
modalWindow.setPreference("warning", true);
modalWindow.setPreference("title", "There are unsaved changes. Do you wish to proceed?");
modalWindow.setPreference("onPromptComplete", uAcmeCreateAdHocTask);
//show the popup window for confirmation
modalWindow.render();
return;
}
//calling it from a function so the confirm dialog above can use the same code
uAcmeCreateAdHocTask();
function uAcmeCreateAdHocTask() {
//get the sys_id of the current record
var sysId = g_form.getUniqueValue();
var createTaskWindow = new GlideModal("u_acme_create_ad_hoc_task"); //UI Page to select Assignment Group
createTaskWindow.setTitle("Create Ad Hoc Task");
createTaskWindow.setBackdropStatic(true); //remain open when user clicks outside of the window
createTaskWindow.setWidth(600);
createTaskWindow.setPreference("sysparm_sys_id", sysId);
createTaskWindow.setPreference("sysparm_short_description", g_form.getValue("short_description"));
createTaskWindow.setPreference("sysparm_description", g_form.getValue("description"));
//show the popup window
createTaskWindow.render();
}
}
UI Page
HTML
<g:ui_form>
<!-- the details of the Requested Item -->
<input type="hidden" aria-hidden="true" name = "item_sys_id" value = "$[sysparm_sys_id]"/>
<input type="hidden" aria-hidden="true" name = "item_short_description" value = "$[sysparm_short_description]"/>
<input type="hidden" aria-hidden="true" name = "item_description" value = "$[sysparm_description]"/>
<!-- the missing mandatory fields error message text -->
<g2:evaluate jelly="true" object="true">
var mandatory_msg = "The following mandatory fields are not filled in:";
</g2:evaluate>
<input type="hidden" aria-hidden="true" id="mandatory_msg" name="mandatory_msg" value="$[HTML:mandatory_msg]" />
<!-- mandatory fields error message -->
<div style="display: none;" id="mandatory_error_msg_div" class="outputmsg_div" aria-live="polite" role="region" data-server-messages="false">
<div id="output_messages" class="outputmsg_container">
<button aria-label="Clear message" title="Clear message" id="close-messages-btn" class="btn btn-icon close icon-cross" onclick="uAcmeHideErrorMessage(); return false;" />
<div class="outputmsg_div" aria-live="polite" role="region" data-server-messages="false">
<div role="alert" class="outputmsg outputmsg_error notification notification-error">
<span class="notification-icon icon-cross-circle">
<span class="sr-only"></span>
</span>
<span id="mandatory_error_msg" class="outputmsg_text"></span>
</div>
</div>
</div>
<br/>
</div>
<!-- instructions -->
<div>
Select the Group to which the new task will be assigned.
</div>
<br/>
<div class="form-horizontal">
<!-- Group picker -->
<div class="form-group is-required" id="group_picker_wrapper">
<label class="col-sm-12 col-md-4 control-label" for="group_picker">
<span mandatory="true" class="required-marker label_description"/>
<span id="group_picker_label" title="Assignment Group">
Assignment group
</span>
</label>
<div class="col-sm-12 col-md-4 form-field input_controls">
<div class="is-required" style="width:350px">
<g2:ui_reference id="group_picker"
name="group_picker"
table="sys_user_group"
order_by="name"
show_popup="false"
completer="AJAXTableCompleter"
onchange="uAcmeFieldOnChange('group_picker')"/>
</div>
</div>
</div>
</div>
<!-- action buttons -->
<div class="modal-footer">
<span class="pull-right">
<g:dialog_buttons_ok_cancel ok="return uAcmeActionOk();"/>
</span>
</div>
</g:ui_form>
Client script
(function() {
//script that runs onload of the page
try {
//remove focus from the "x" button
document.activeElement.blur();
//try to set focus to the Group picker
document.getElementById("sys_display.group_picker").focus();
//and set the mandatory field display
uAcmeFieldOnChange("group_picker");
} catch (err) {}
})();
function uAcmeFieldOnChange(fieldName) {
var field = $(fieldName);
var wrapper = $(fieldName + "_wrapper");
if (!field.value.trim()) {
wrapper.removeClassName('is-filled');
} else {
wrapper.addClassName('is-filled');
}
}
function uAcmeHideErrorMessage() {
try {
document.getElementById("mandatory_error_msg_div").style.display = "none";
} catch(err) {}
}
function uAcmeActionOk() {
var result = true;
var missingData = [];
//verify the mandatory fields have been filled in
try {
gelObject = gel("group_picker");
if (gelObject.value.trim() == "") {
result = false;
missingData.push(document.getElementById("group_picker_label").innerHTML);
}
} catch (err) {
return false;
}
if (!result) {
document.getElementById("mandatory_error_msg").innerHTML = gel("mandatory_msg").value + " " + missingData.join(", ");
document.getElementById("mandatory_error_msg_div").style.display = "block";
}
return result;
}
Processing script
(function() {
//run on the server to create the new Catalog Task
var requestedItemId = typeof item_sys_id !== "undefined" ? item_sys_id : "";
var shortDescription = typeof item_short_description !== "undefined" ? item_short_description : "";
var description = typeof item_description !== "undefined" ? item_description : "";
var groupId = typeof group_picker !== "undefined" ? group_picker : "";
//add the Role to the selected Modules
if (groupId) {
var catalogTask = new GlideRecord("sc_task");
catalogTask.newRecord(); //initialize the new record with default values
catalogTask.setValue("request_item", requestedItemId);
catalogTask.setValue("u_ad_hoc_task", true);
catalogTask.setValue("assignment_group", groupId);
catalogTask.setValue("short_description", shortDescription);
catalogTask.setValue("description", description);
if (catalogTask.insert()) {
//redirect to the new task
response.sendRedirect(catalogTask.getLink());
} else {
//back to the Requested Item
gs.addErrorMessage("Could not create a new Catalog Task");
var urlOnStack = GlideSession.get().getStack().bottom();
response.sendRedirect(urlOnStack);
}
}
})();
It might seem complicated but I've got several templates that I used based on what I need so it's mostly copy/paste and tweak once you have it.
The end result looks like this:
If there are changes on the form...
If there are none, or the user selected "OK" to continue...
Mandatory fields are enforced
And the user is redirected to the new record after clicking "OK". There could be some extra tweaking for your needs like setting the condition or Role that can see the UI Action and the UI Page should have an ACL or two on it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-02-2025 07:10 AM
Totally agree! Now to reverse logic this... originally I started with just the create SC task UI action but then realized we would need something to ask the user which team they would like to assign to, so my brain instantly went to "add it to the current UI action." So can I ask - should I have the UI action call the GlideDialogWindow for the prompt first and then create the task after in the same UI action?
I am a newer SN developer coming from a different tool, so this is awesome advice and appreciated!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-02-2025 09:10 AM
Actaully, here was my dilemma and I may just be overthinking it - how do I save the prompted value if the task is not yet created? I think that was the issue I was running into before 🙂
Thanks again!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-02-2025 06:00 PM
Here is how I would do it...
UI Action (just the basics listed here):
Action name = u_acme_create_ad_hoc_task
Form button = checked
Show update = checked
Client = checked
Onclick = uAcmeConfirmAdHocTask();
Script
function uAcmeConfirmAdHocTask() {
//are there unsaved values?
if (g_form.modified) {
//the form data has been modified but not saved yet so warn the user
var modalWindow = new GlideModal("glide_confirm_standard"); //SN OOTB confirm dialog
modalWindow.setTitle("Create Ad Hoc Task");
modalWindow.setBackdropStatic(true); //remain open when user clicks outside of the window
modalWindow.setWidth(600);
modalWindow.setPreference("warning", true);
modalWindow.setPreference("title", "There are unsaved changes. Do you wish to proceed?");
modalWindow.setPreference("onPromptComplete", uAcmeCreateAdHocTask);
//show the popup window for confirmation
modalWindow.render();
return;
}
//calling it from a function so the confirm dialog above can use the same code
uAcmeCreateAdHocTask();
function uAcmeCreateAdHocTask() {
//get the sys_id of the current record
var sysId = g_form.getUniqueValue();
var createTaskWindow = new GlideModal("u_acme_create_ad_hoc_task"); //UI Page to select Assignment Group
createTaskWindow.setTitle("Create Ad Hoc Task");
createTaskWindow.setBackdropStatic(true); //remain open when user clicks outside of the window
createTaskWindow.setWidth(600);
createTaskWindow.setPreference("sysparm_sys_id", sysId);
createTaskWindow.setPreference("sysparm_short_description", g_form.getValue("short_description"));
createTaskWindow.setPreference("sysparm_description", g_form.getValue("description"));
//show the popup window
createTaskWindow.render();
}
}
UI Page
HTML
<g:ui_form>
<!-- the details of the Requested Item -->
<input type="hidden" aria-hidden="true" name = "item_sys_id" value = "$[sysparm_sys_id]"/>
<input type="hidden" aria-hidden="true" name = "item_short_description" value = "$[sysparm_short_description]"/>
<input type="hidden" aria-hidden="true" name = "item_description" value = "$[sysparm_description]"/>
<!-- the missing mandatory fields error message text -->
<g2:evaluate jelly="true" object="true">
var mandatory_msg = "The following mandatory fields are not filled in:";
</g2:evaluate>
<input type="hidden" aria-hidden="true" id="mandatory_msg" name="mandatory_msg" value="$[HTML:mandatory_msg]" />
<!-- mandatory fields error message -->
<div style="display: none;" id="mandatory_error_msg_div" class="outputmsg_div" aria-live="polite" role="region" data-server-messages="false">
<div id="output_messages" class="outputmsg_container">
<button aria-label="Clear message" title="Clear message" id="close-messages-btn" class="btn btn-icon close icon-cross" onclick="uAcmeHideErrorMessage(); return false;" />
<div class="outputmsg_div" aria-live="polite" role="region" data-server-messages="false">
<div role="alert" class="outputmsg outputmsg_error notification notification-error">
<span class="notification-icon icon-cross-circle">
<span class="sr-only"></span>
</span>
<span id="mandatory_error_msg" class="outputmsg_text"></span>
</div>
</div>
</div>
<br/>
</div>
<!-- instructions -->
<div>
Select the Group to which the new task will be assigned.
</div>
<br/>
<div class="form-horizontal">
<!-- Group picker -->
<div class="form-group is-required" id="group_picker_wrapper">
<label class="col-sm-12 col-md-4 control-label" for="group_picker">
<span mandatory="true" class="required-marker label_description"/>
<span id="group_picker_label" title="Assignment Group">
Assignment group
</span>
</label>
<div class="col-sm-12 col-md-4 form-field input_controls">
<div class="is-required" style="width:350px">
<g2:ui_reference id="group_picker"
name="group_picker"
table="sys_user_group"
order_by="name"
show_popup="false"
completer="AJAXTableCompleter"
onchange="uAcmeFieldOnChange('group_picker')"/>
</div>
</div>
</div>
</div>
<!-- action buttons -->
<div class="modal-footer">
<span class="pull-right">
<g:dialog_buttons_ok_cancel ok="return uAcmeActionOk();"/>
</span>
</div>
</g:ui_form>
Client script
(function() {
//script that runs onload of the page
try {
//remove focus from the "x" button
document.activeElement.blur();
//try to set focus to the Group picker
document.getElementById("sys_display.group_picker").focus();
//and set the mandatory field display
uAcmeFieldOnChange("group_picker");
} catch (err) {}
})();
function uAcmeFieldOnChange(fieldName) {
var field = $(fieldName);
var wrapper = $(fieldName + "_wrapper");
if (!field.value.trim()) {
wrapper.removeClassName('is-filled');
} else {
wrapper.addClassName('is-filled');
}
}
function uAcmeHideErrorMessage() {
try {
document.getElementById("mandatory_error_msg_div").style.display = "none";
} catch(err) {}
}
function uAcmeActionOk() {
var result = true;
var missingData = [];
//verify the mandatory fields have been filled in
try {
gelObject = gel("group_picker");
if (gelObject.value.trim() == "") {
result = false;
missingData.push(document.getElementById("group_picker_label").innerHTML);
}
} catch (err) {
return false;
}
if (!result) {
document.getElementById("mandatory_error_msg").innerHTML = gel("mandatory_msg").value + " " + missingData.join(", ");
document.getElementById("mandatory_error_msg_div").style.display = "block";
}
return result;
}
Processing script
(function() {
//run on the server to create the new Catalog Task
var requestedItemId = typeof item_sys_id !== "undefined" ? item_sys_id : "";
var shortDescription = typeof item_short_description !== "undefined" ? item_short_description : "";
var description = typeof item_description !== "undefined" ? item_description : "";
var groupId = typeof group_picker !== "undefined" ? group_picker : "";
//add the Role to the selected Modules
if (groupId) {
var catalogTask = new GlideRecord("sc_task");
catalogTask.newRecord(); //initialize the new record with default values
catalogTask.setValue("request_item", requestedItemId);
catalogTask.setValue("u_ad_hoc_task", true);
catalogTask.setValue("assignment_group", groupId);
catalogTask.setValue("short_description", shortDescription);
catalogTask.setValue("description", description);
if (catalogTask.insert()) {
//redirect to the new task
response.sendRedirect(catalogTask.getLink());
} else {
//back to the Requested Item
gs.addErrorMessage("Could not create a new Catalog Task");
var urlOnStack = GlideSession.get().getStack().bottom();
response.sendRedirect(urlOnStack);
}
}
})();
It might seem complicated but I've got several templates that I used based on what I need so it's mostly copy/paste and tweak once you have it.
The end result looks like this:
If there are changes on the form...
If there are none, or the user selected "OK" to continue...
Mandatory fields are enforced
And the user is redirected to the new record after clicking "OK". There could be some extra tweaking for your needs like setting the condition or Role that can see the UI Action and the UI Page should have an ACL or two on it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-05-2025 08:41 AM
Thank you so much! I ended up configuring something similar I worked on over the weekend (haha) but thanks to your idea of prompting first! I am actually going to look at his scripting because it looks to work even better than what I did! Thank you so much, I really appreciate all your help! 🙂