I
had a colleague come to me recently for help on a client issue. The customer wanted two things; the first was to set up the capability to warn users when they were navigating away from a modified form without saving it, but to do this only on selected forms rather than globally. The second was to modify the text included in the alert dialog to be whatever they wanted. In this post I’ll explain some of the options that ServiceNow provides in this area and how you can get even more flexibility and control over this behavior through scripting.
The first thing to know about this functionality is that its main purpose is to identify that fields on a form have been modified, and alert the user if they try to navigate away from one of these forms if the record hasn’t been saved. I’ve touched on this topic before in an article I wrote about identifying modified fields. Because this is a common problem, ServiceNow actually includes a property (which is active by default) to present this alert. You’ve probably noticed this alert as you’ve worked in your ServiceNow instance…
The name of the property that controls this behavior is ‘glide.ui.dirty_form_support’ and can be changed by accessing the property through the ‘sys_properties’ table. This property works globally across an instance and causes the alert to display for any standard forms (meaning this isn’t going to work in the service catalog) so there’s not a whole lot you can do to control the functionality. One thing you can do easily is control part of the message contained in the alert. I say “part” because the dialog is actually a standard javascript/browser behavior so that limits your control a bit. The part you can customize is the line in the alert that looks like this…
Changes have been made. Continuing will discard the changes.
This text is actually accessed via a ‘Message’ record in the system that is passed from the server to the client when a form is rendered. You can find and modify this global message by navigating to ‘System UI -> Messages’ and looking for the entry as shown here…
Beyond the basics…
While the information above is useful, it still doesn’t solve the issues I described above…warning ONLY on selected forms to selected users, and controlling the text on these selective dialogs. As is often the case, a carefully-crafted client script can provide the needed flexibility.
When a form loads in your browser, it comes with a ‘window.onbeforeunload’ object that detects when the window is closed or navigated away from. In most cases there’s nothing associated with this event, but in cases like this, you can trigger specific things (like an alert). The way this works is kind of unique for javascript event handlers. In this case, the ‘window.onbeforeunload’ event gets attached to a function whose purpose is to return text to be inserted into the alert dialog. By attaching a function to this event in a client script you can override the default message and apply the message and alert selectively across different forms and for different roles and users.
The script below is the simplest example but you can add client-side checks for roles and other things if you want. All you have to do is change the ‘YOUR CUSTOM MESSAGE HERE’ line to
Name: Custom Dirty From Alert
Table: Wherever you want!
Type: onLoad
Script:
//Add the 'onbeforeunload' event
window.onbeforeunload = function() {
//If we're leaving a modified form without a submit
if (!g_form.submitted && g_form.modified) {
//Add the custom dialog message here
return 'YOUR CUSTOM MESSAGE HERE.';
}
}
}
Hi Mark,
I love the dirty form alert but it has been pointed out to me that it doesn’t work on Record Producers. I was going to research this but ran across your reference above to the property not working with the Service Catalog. Do you have any suggestions for how to prevent a user from navigating away from an unsubmitted record producer?
Thanks, Jim
Hey Jim, I wish I could give you a good answer, but it just isn’t possible in the catalog without 2 or 3 scripts per item to manage the interaction. The big issue is that ‘g_form.submitted’ isn’t set within the catalog. I’ve figured out a workaround for identifying changed fields, but without the ‘g_form.submitted’ check it will fire even if you submit the form.
https://servicenowguru.wpengine.com/scripting/business-rules-scripting/checking-modified-fields-script/
Thanks Mark. Do you know if SNC has any interest in setting g_form.submitted withing the catalog? Is this an obscure request? If you recall, we don’t use the service catalog except for record producers and I use more and more of those. I get complaints now and then about people forgetting to submit hot forms as some of the forms they ask me to create are pretty detailed.
Looking forward to your Asset Management webinar.
Happy Holidays, Jim
Thanks Jim! There’s nothing in the works that I’m aware of, but this seems like a pretty significant oversight to me. You’ll probably need to request an enhancement.
I know a ServiceNow partner called Aspediens implemented this feature for record producers. Here is a link to the corresponding post in their blog: http://www.aspediens.com/feature-coverage-confirmation-when-navigating-away-in-a-record-producer
Not sure if it can be reused for standard catalog items but you can try contacting them for more information about it.
Thanks Slava, this looks promising. I’ve written to them.
Jim
Due to a large demand about the way this was done, here is an example of Catalog Client Script to achieve the check described in the article above. Please note that each Variable of the Catalog Item/Record Producer must be checked individually (the example below has three Variables; each “” tag must be replaced by the real Variable name).
* Adds a confirmation message when exiting the Catalog
* Item or Record Producer with unsaved modifications.
*/
function onLoad() {
var u_g_form_dirty = false;
window.onbeforeunload = function () {
// All variables of the Record Producer must be checked individually
if(g_form.getValue("") != "") {
u_g_form_dirty = true;
} else if(g_form.getValue("") != "") {
u_g_form_dirty = true;
} else if(g_form.getValue("") != "") {
u_g_form_dirty = true;
} else {
u_g_form_dirty = false;
}
// Message that will be displayed to the user. Can be left blank.
var warningMessage = "CUSTOM TEXT: You will lose all unsaved changes!";
if(u_g_form_dirty) {
return(warningMessage);
} else {
return;
}
}
}
Thanks for sharing this! I think eventually I’d like to come up with a solution where you didn’t have to target each specific variable individually. This approach works for an individual catalog item fine, but it’s not something that’s practical to deploy across the entire catalog.
Hi Mark,
There is one problem with this dirty form alert message………
after getting alert messages/error messages from client script or business rules if we try to navigate away from user form this dirty form popup is not working….for eg:
1.user is filling incident form and had forgot to fill one mandatory field.
2.when he clicks the submit button an alert box will come saying that field is mandatory .
3.now if he tries to navigate away from the form ,it is allowing the user…. ..No dirty form popup alert is coming ….No alert message to the user saying “data has been modified and are you sure you want to leave this page..?”
Build date: 11-22-2011_1328
Build tag: glide-june2011-05-25-2011__patch3-11-14-2011
Can find anything describe in the images above, and I am wondering where the default message is stored and if there is any client script/business rule that is overriding it.
When I tried to code the client script nothing happens, i get no warning message at all, also when I when to look for some info in the service-now wiki website about ‘glide.ui.dirty_form_support’ the page was removed.
Any suggestions will be much appreciated.
Thanks
I just tested this on the ServiceNow demo site and it all works correctly there. I’m guessing that you don’t have the dirty form property turned on. Navigate to your ‘sys_properties’ table and make sure that the ‘glide.ui.dirty_form_support’ property exists and that it is set to a value of ‘true’.
It is Active under sys_properties.list, but when I went to look for the default message in “System UI” “Message” nothing like the stuff you show here appears. Maybe by Build tag: glide-june2011-05-25-2011__patch3-11-14-2011 has something to do with it, unfortunately no other sides
talk about glide.ui.dirty_form_support and there is not support for window.onbeforeunload in service-now site.
Can you at least send me the link to get to the service-now test site
Thanks……
You can just create that message record. As long as it has the correct ‘Key’ value, the message will show up however you want. You can access the ServiceNow demo environments at demo.service-now.com. By the way, if you’re on that old of a build, you’re in serious need of an upgrade. That should probably be your first priority.
Thanks a lot Mark, I already talked about upgrading but unfortunately management does not feel is necessary. If the key does not exist where
does it the message getting the text from, and how do I know what is the correct key value.
Your management needs to understand that they’re playing with fire being that far behind the curve on ServiceNow upgrades. I’m surprised you haven’t been forced to upgrade yet. The message comes from the underlying code (which you don’t have access to). It points to the message record, but if the message record doesn’t exist, it supplies the default. You can compare to the message record in the demo instance to make sure you’ve got the correct one.
One problem with your script is that it will completely replace any other onbeforeunload handler
It’s better to just subscribe to the event with:
if(window.addEventListener)
window.addEventListener(‘beforeunload’, myfunc, false);
else if(window.attachEvent)
window.attachEvent(‘onbeforeunload’, myfunc);
Hey Ben, thanks for the feedback. I understand what you’re saying, but in my testing the complete override/replacement is necessary so that you get the proper dialog message. Otherwise, the standard dialog still appears. I may be missing something so if you can get it to work in the way you describe I’d be happy to add it. I agree it’s the better way if it will work.