
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on ‎04-06-2021 08:03 AM
Session: CCE5048 - Enhance your Catalog Items with Contextual Popups!
Hey There!
If you've wound up here after watching my session and wanted to see the nitty-gritty of how you can improve your service portal experience, keep reading. If you've found this article from the community, check out the session link above to see how you can use the spModal directive within catalogue client scripts to improve your end-user experience of your service portal.
The Bad & The Ugly
Calling this bad/ugly is probably a little harsh and hypocritical as I've used this option myself several times and it does the job. But that doesn't meet our needs of our customer nor does it fit in with the portal theming.
The window.alert() and window.confirm() options just don't allow for a good customer journey as they depend on the browsers' implementation of the functions to which you could have additional text added which adds confusion for the user.
The Good
spModal is a lightweight wrapper for Angular UI bootstrap $uibModal that is used frequently in Service portal widgets to present various forms of popups. But did you know it can be used within a catalog client script!
spModal Alert
This is one of the simplest implementations and is a direct replacement for the window.alert() method. It takes in a message and will display a popup with the instance theming.
function onLoad() {
spModal.alert("You're not authorised to do this")
.then(function(answer){
console.log(answer);
});
}
What's this .then() all about? All modals instantiate a promise which invokes the function within the .then() parameter on the closure of the modal. This allows you to do some funky things with the other spModal versions. For spModal.alert() this just returns true if the user clicks the ok button.
spModal Confirm
Similar to spModal.alert(), the confirm option has the same basic setup but with a cancel button in addition to the ok button.
function onLoad() {
spModal.confirm("You're not authorised to do this")
.then(function(answer){
//If they pressed ok
console.log(answer);
} , function(answer){
//If they pressed cancel
console.log("didn't accept/select ok");
});
}
spModal Prompt
As the name might suggest, this option gives you the ability to prompt the user for a value which is then passed back to the promise for you to use. You can pass a default value that the user can overtype.
function onLoad() {
spModal.prompt("What is your favourite colour?" , "Blue")
.then(function(answer){
//If they pressed ok - returns the prompt value or default value
console.log(answer);
} , function(answer){
//If they pressed cancel
console.log("didn't accept/select ok");
});
}
spModal Open
This is by far my favourite option as it gives you direct access to the functionality available in $uibModal and greater flexibility. It might seem a little intimidating due to the number of options but it's definitely worth it.
Key | Purpose | Default |
---|---|---|
title | A string that can be HTML that goes in the header of the modal | empty |
message | A string that can be HTML that goes in the body. | empty |
buttons | An array that contains the buttons to show on the modal | Cancel & Ok |
input | Boolean - whether an input box should appear similar to confirm | false |
value | A string default to appear in the input | empty |
widget | A string or sys_id of a widget that is embedded into the modal | empty |
widgetInput | An object to send to the embedded widget as the input parameter available in its server script | null |
shared | A client-side object to share data with the embedded widget client script | |
size | Size of the modal window. Options are here 'sm' or 'lg' | calculated based on content |
animate | specify whether the modal should ease in from the top of the window | true |
backdrop | Controls the presence of a backdrop.
| true |
keyboard | Indicates whether the dialog should be closable by hitting the ESC key | true |
noDismiss | Removes the header containing the X button to close the modal. Setting this to true also removes the header title | false |
License Confirmation
An example used in the session demonstration was the ability to ask the user to actively confirm whether a licensed product is required. This spModal open uses the following object key:value pairs:
- title - This sets the modal header text.
- message - Sets the descriptive value in the body of the modal. In this example, I'm passing in the newValue of the license_type variable.
- buttons - Ok & Cancel don't provide context and can be misinterpreted. The buttons used contain natural language along with using the primary option to set the button we want users to click.
- backdrop - Using static prevents the user from clicking outside the modal and dismissing it.
- keyboard - Setting this to false prevents the ESC key from closing the modal.
The promise sets the license_type to free if the primary button is selected. You can add another function to capture if the cancel/dismiss button is selected to perform another action.
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
if(newValue == 'free') return;
spModal.open({
"title" : "Licensed Product",
"message" : "Power BI " + newValue + " is a paid for product and will require approval",
"buttons" : [
{label: "✘ Downgrade to Free" , primary: true},
{label: "✔ I understand the cost" , cancel: true}
],
"backdrop" : "static",
"keyboard": false
}).then(function(){
g_form.setValue('license_type' , 'free');
});
}
Terms & Conditions
I often see people add a checkbox to a form to ask people to confirm whether they agree to some sort of T's & C's or EULA. It's functional but isn't pretty and customers aren't going to be clicking on your hyperlink to a knowledge article to read them. This method intercepts the user ordering/submitting and prompts them to read it. If they accept, it'll submit the order for them, else it'll take them back to the page.
function onSubmit() {
if (typeof spModal != 'undefined' && !g_form._hasConfirmed) {
spModal.open({
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ut consequat risus, vel maximus augue. Aliquam in velit ut justo consequat pharetra lacinia a magna. Donec egestas quis massa ut lobortis. Nullam non nisi dui. In euismod nisl at bibendum malesuada. Sed iaculis felis non iaculis viverra. Duis interdum felis mi, convallis porta lectus commodo quis. Nam aliquam nulla turpis, vitae mollis nisi facilisis et. Morbi vel augue vel enim pulvinar molestie in vitae neque. Ut eu vehicula odio, a condimentum tortor. Etiam viverra tincidunt nisi sed ultrices. Sed rutrum turpis non faucibus suscipit. Nunc aliquet ante non quam ullamcorper pulvinar. Ut sed dolor nec nulla euismod facilisis sed at eros. Ut in lectus et mauris consectetur vestibulum non sed magna.',
title: 'Agree to Terms & Conditions',
buttons: [
{label:'✘ Disagree', cancel: true},
{label:'✔ I Accept', primary: true}
]
}).then(function(confirm){
if (confirm){
g_form._hasConfirmed = true;
if (typeof g_form.orderNow != 'undefined') {
g_form.orderNow();
} else {
g_form.submit();
}
}
});
return false;
}
}
Popup Widget
A bit more advanced, and for those who like to create service portal widgets. spModal supports passing in a widget and input parameter that will be displayed inside the modal window. This uses a custom widget, that is attached, and is designed to make picking a hierarchy location a lot easier.
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
_callPopup();
function _callPopup(){
spModal.open({
"title" : "Select Device Location",
"widget" : "location-picker",
"widgetInput" : {"account" : g_form.getValue('account')},
"shared" : shared,
"buttons": [
{label:'✔ Confirm', primary: true}
]
});
}
}
Conclusion
spModal provides a great visual enhancement to your portal with only a small amount of effort required. If you're already creating a client script, you might as well use this instead of alert() or confirm()! If you any questions, don't hesitate to add them below and I'll endeavour to help out where I can.
- 13,057 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
How does spModal work in the desktop interface ?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Surpised you didn't show any code in your preso to highlight how simple & easy it is to implement!
I'd go further and show the UI16 example using GlideModal. The old Alert() makes for a terrible UX.
Nice work!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks
Is there anyway we can throw the spModal for portal and Glidemodal for U16 using the client script. We use both U16 and Portal and will need to handle for both UI.
I can build a script include that can identify and throw the message appropriately. Is there anyway to identify portal vs desktop ?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks for the spModal functionality . It is really helpful.
I was able to show the SpModal for location when the previous field changes.
Can you please let me know how the Location popup is shown by clicking on a reference field ?
How to set the value back to the Catalog variable ?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Kieran Anson Hi Kieran. Thank you so much for sharing all these, I love your work, so very helpful.
Kieran, please can I ask for your help. I have tried following exactly what you have displayed here in terms of script and also the uploaded the Location Picker xml to my instance.
But when I try it on my Catalog Item, I get the following error message on Service Portal:
'There is a JavaScript error in your browser console'
When I check the Console error details, it points to one line as follows:
'(g_env) [SCRIPT:EXEC] Error while running Client Script "Location Picker": ReferenceError: shared is not defined'
Can you help me determine what the issue could be. I have used only your scripts and custom Location Picker xml but it doesn't work on my Service Portal.
This is for the : 'Select Device Location' one.
Thanks so much Kieran, maybe you can help me with what I am doing wrong.
Kind Regards, Warwick
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@WazzaJC You can omit the "shared" property from the spModal.open() command if you're not planning to use it. Its an optional property allowing you to pass something if you need to. If you click the link to spModal.open docs, which Kieran included just above where he listed out the table of "Key, Purpose, Default" you'll see the example code doesn't even include the "shared" parameter, because (1) docs are not comprehensive enough, but (2) its only for advanced use cases.
I would just omit that and see how it goes.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks very much, I do appreciate your advice. I did try that but still having issues getting this script to work properly unfortunately. Hopefully oneday @Kieran Anson may respond to my query and be able to advise further.
I do appreciate all the help on this.
Kind Regards, Warwick.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Can data entered by a user into a client-side spModel window be processes server-side by the system? After a service catalog item is submitted on behalf of a user that has no rights or roles. That user without roles needs to answer a question with Yes, No, or Maybe from the Service Portal. I need ServiceNow to record the answer as a variable associated with the request item.
Modal buttons look perfect, except the user selecting the appropriate button won't have rights to update the request item record.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @Kieran Anson thank you for sharing this.
I have on questions:
How can I embed a link in the message? Also, a bullet point.
Thanks once again.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I am trying to show checkbox in pop up using spmodal, can you help me
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
How can I open Survey form using spmodal ?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Keiran, such a well written article, well done.
I just thought I would add some of my tips that I gathered from reading many an article, wish I had stumbled onto this one way sooner 😊
Tip 1: You can format the header using headerStyle.
spModal.open({
"title": 'Close Order: ' + currentOrder.number,
"message": 'Please confirm you wish to close this order.',
"headerStyle": {
'color': '#ffffff',
'background-color': '#d9534f',
'border-color': '#d9534f',
'border-top-left-radius': '.6rem',
'border-top-right-radius': '.6rem'
},
Tip 2: Add focus to a button using focus: true. By default it sets focus to the top right x. This would be OK except it has a hover message which ruins the look.
buttons: [
{ label: '${Cancel}', focus: true, cancel: true, class: "btn btn-default" },
{ label: '${Close Order}', primary: true, class: "btn btn-danger" }
]
Output: Red Header with focus on the cancel button
The code is mine but the ideas are not, I just can't remember who I stole them from, hopefully it was not Keiran😟. Either way I think it is a good place to put this for the next reader.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks so much for this!

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I tried the spModal.confirm in an onSubmit Client catalog script.
The dialog box displayed correctly but, it didn't pause the submission until one of the buttons were clicked.
I gave up and went back to the simple return confirm() I originally had.
From what read in you document above, the .then is needed because the spModal returns a promise so it's asynchronous. Is there a way to make it synchronous so it will wait for 1 of the buttons to be pressed?
This is my code.
spModal.confirm('Please do not include any Personal Identifiable Information (PII) in the Brief and Detailed Description fields. <br></br> Click the OK button to submit. <br></br> Click the Cancel button to go back to the form.')
.then(function(answer) {
//If they pressed ok
return answer; //true
}, function(answer) {
//If they pressed cancel
return answer; //false
});
Any suggestions?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Dave65 yes you can block the submission. We use the accessible g_scratchpad object to store the validity of the submit request. Within spModal we then alter this value and submit the item programatically
function onSubmit() {
//Allow submit
if (typeof g_scratchpad.canSubmit != 'undefined' && g_scratchpad.canSubmit == true) {
return true;
}
spModal.confirm(getMessage('PII_CAT_PROMPT'))
.then(function(answer) {
g_scratchpad.canSubmit = true;
g_form.submit();
}, function(answer) {
g_scratchpad.canSubmit = false;
});
return false;
}

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Kieran
Thanks for the help. You solution works great.
One more question; Is there a way to change the color of the text?
This is what I tried:
spModal.confirm(<font color="red">Please do not include any Personal Identifiable Information (PII) in the Brief and Detailed Description fields. <br><br> Click the OK button to submit. <br> Click the Cancel button to go back to the form.</font>)
But I get the following error:
Could not save record because of a compile error: JavaScript parse error at line (7) column (22) problem = syntax error (<refname>; line 7)
Please ignore, I finally figured it out, here's the code:
message: '<strong><font color="#c41230" size="+1">Please confirm that no Personal Identifiable Information (PII) has been included in the Brief and Detailed Description fields</font></strong> <br><br> <font size="+1">Click the Submit button to submit the request. <br> Click the Cancel button to go back to the form.</font>',
The end result looks like this:

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
just noticed something about the spModel.open ('m not sure if it's also true about the spModel.confirm)
When the dialog box is open, I can click on the page and the dialog box closes.
Is there a way to prevent this?
I need the dialog box to be 508 compliant.
Thanks again for you help.
Please ignore, I missed the backdrop:"static" command.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Kieran
I tried to access your session but there doesn't seem to be a way to get to it. Do you know if ServiceNow has pulled it?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Dave65 I believe ServiceNow only retain Knowledge presentations for a limited time. With K25 just around the corner, this is likely not available now.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
How can we close this spModal automatically?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@bsiva4567 this use case isn't supported via spModal unfortunately as it doesn't expose a function to allow you to destroy the modal.