If you’ve used the two-step catalog checkout before you’ve noticed the few fields on the final checkout screen. Users can provide information about the Requester and their location, along with some special instructions for the processing of the request. These fields are all optional however, so there’s no way to force a user to fill any of this information out. If you did need to force one or more of these fields to be mandatory, you could accomplish this by making a couple of modifications to the ‘servicecatalog_cart_template’ UI Macro.

Because we’re working in the Service Catalog interface, making a field mandatory will work a little bit differently than in other places in the system. For this modification we will intercept the submission of the form and check each field to see whether it is empty or not. This can be done by making changes to the following lines in the ‘servicecatalog_cart_template’ UI Macro.
–In the ‘servicecatalog_cart_template’ UI Macro, change the onClick event of the submit button in this line…
to this…
–Note that in Eureka instances of ServiceNow you’ll be changing this line…
to this…
–Add the ‘checkMandatorySubmit-CatalogCheckout’ global UI script function by navigating to ‘System UI -> UI Scripts’. You can modify this function to check any field(s) on the checkout form.
This UI Macro script can be pasted directly into the ‘servicecatalog_cart_template’ UI Macro to make the ‘Special Instructions’ field mandatory on checkout.
Name: checkMandatorySubmit-CatalogCheckout
Script:
var manFields = '';
var si = gel('special_instructions').value;
if(si == ''){
manFields = 'Special Instructions';
}
if(manFields == ''){
gsftSubmit($('sysverb_insert'));
}
else{
alert('The following mandatory fields are not filled in: ' + manFields);
return false;
}
}
Here’s another example UI script that makes the ‘Requested for’ field mandatory for ‘ITIL’ users.
Name: checkMandatorySubmit-CatalogCheckout
Script:
var manFields = '';
var si = gel('sc_cart.requested_for').value;
if(si == ''){
manFields = 'Requested for';
}
if(g_user.hasRole('itil')){
if(manFields == ''){
gsftSubmit($('sysverb_insert'));
}
else{
alert('The following mandatory fields are not filled in: ' + manFields);
return false;
}
}
else{
gsftSubmit($('sysverb_insert'));
}
}
Hi,
can you add other variables here? like a glide list? and pass it on the request?
thanks
alli
It is possible, but it’s kind of tricky if you want to do a watch list. 🙂 Here’s a link to an article describing how to add fields to the checkout form.
https://servicenowguru.wpengine.com/system-ui/adding-fi…
I tried that one, but I can’t make the glide list work
This works great. You saved me a lot of work on this one. As always – thanks Mark!
I think I may have found an issue. If I order something as an ITIL user, fill in my name, and go ahead with the order, my assignment rules will not pick up the “requested for” value. So – my task does not assign correctly. Works fine if I follow the same process as a non-ITIL user. I’m thinking the “requested for” is not populated at the time my rules are running.
Hi,
I tried this madification and it did not work for me. Although, I did get the message “‘The following mandatory fields are not filled in: ” .. but the request is being submitted.
I have this modification done in a demo instance
https://demo018.service-now.com/
Could you please let me know if there is a way to fix this.
Kind Regards,
Ashwin
I just tested in 2 separate browsers on demo018 and it’s working perfectly for me there. The alert appears and you can’t submit the order unless you have the additional comments filled in.
Hi Mark,
thank you for the quick reply.
The steps I have taken is
1. Self Service -> Service Catalog
2. Select “New Employee Hire” under On Boarding Services.
3. Fill in all the details and click “Choose Option” button at the bottom.
4. Click “Check Out”
%. Do not fill in the “Special Instructions” and click “Submit Order”.
6. Now, we will get a alert message “The following mandatory fields are not filled in: Special Instructions”.
7. Click OK.
8. Now, in couple of seconds, the page will navigate to another page which says “Thank you, your request has been submitted”.
I am currently using this in IE 9. Please let me know if I am doing something incorrect.
Kind Regards,
Ashwin
I followed the exact same steps in IE9 and it’s working perfectly for me. I don’t know what the issue is in your case, but you might try on a different computer or a different browser. There’s not much more I can do to assist you on this.
Mark,
Just figured out that, this issue is happening in IE9 but works fine in chrome…
Any fix you can suggest for IE9 please?
Regards,
Ashwin
Hi Mark,
Can we autopopulate the Requested For’s value (rather than the currently logged in user) on the checkout screen with the variable set – Requested For’s value which I am using in my order guide.
Regards/Neetu
I don’t know of a simple way to do that. Even if you could, I think it would cause problems in the Service Catalog since you can have multiple request items in a request. The various ‘requested_for’ variables would potentially conflict and override each other when trying to populate the final value for the request.
Thanks for prompt reply!!
My requirement is – for eg: There is an order guide – New Employee Hire (out of the box ). There is a variable named “Employee’s Name?” on form. I want to make it reference type and let the user to choose any value from it. Then, whatever the value user choose should get autopopulated into the “Requested For” field on the checkout Page.
So Is there any way to get it work..
Regards/Neetu
There’s no way to do that that I’m aware of. Order guide variables are only used to populate request item variables. You’re still going to have the problem of many request items in a cart and having them conflict.
Hi Mark,
Has this stopped working on Calgary ? If I leave the requested_for empty I get the alert. But when it’s populate clicking on the submit button does nothing .. Thanks
Russ,
Same here, not working for me at all in Calgary. For starters:
– The button is not a button anymore, it’s an HTML link.
– Adding gsftSubmit(); to checkMandatorySubmit causes an error:
— Uncaught TypeError: Cannot read property ‘sys_action’ of undefined js_includes.jsx?v=07-22-2013_1931&lp=Wed_Jul_24_13_07_09_PDT_2013&c=5_62:10475
I am curious if Mark has a solution for this.
The solution Russ is this:
return checkMandatorySubmit(); in the button should be return checkMandatorySubmit(this);
Then in the function, do these 2 changes:
function checkMandatorySubmit(thiz) {
…
if(manFields == ”){
gsftSubmit(thiz);
}
…
That should work. You will have to close your browser or clear the cache. I found that out the hard way.
The key here is that the html element must be a Button, not an anchor tag. If anyone has a solution to get the anchor tag to work I sure would love to learn what it is. It’s styling capabilities are much more dynamic.
This worked for me. Thanks Chris! It also appears that Mark has updated his example, but still uses the . This will also work with …
I’d like to make the ‘Deliver to’ section a list of choices instead of free text. How would I go about doing this? I can’t seem to find the table containing the ‘Deliver to’ variable.
Hi
Currently on Eureka and seem to have hit a problem, when clicking on Submit its not doing anything anymore. Get the following error.
ReferenceError: checkMandatorySubmit is not defined
Any Ideas
Thanks
Looks like SN changed a few things in Eureka. You should be able to fix this by creating a global UI script. I’ve modified the instructions above to reflect this workaround.
Mark, works a treat. Thanks
Have you planned any updates for this to work in Fuji without editing the base system code?
Paul, in the cart layouts, just remove the OOTB macro and create a new one, copy/pasting the OOTB macro’s contents. Then you can edit it freely without stepping on the protection levels.
I think your issue here is that the code has further changed with fuji. Now the onlick is this: “onclick=”checkout(this, forms[‘sc_cart.do’]);””
I’m not sure exactly what all is being done, but it definitely deviates further from what Mr. Stanger had. I am trying to figure this out myself right now, hopefully will find a solution shortly.
Okay, I got it working in Fuji. This is very long and involved, so if Mr. Stanger wants to format it to make it more pretty, that’s fine.
First step, navigate to cart layouts and find the proper screen. I’m using the two-step, so I go to Maintain Cart Layouts -> Browser Screen -> Cart Preivew Screen (Two Step). This is the cart screen, and it’s made up of UI Macros which compose each section. Now, you don’t want to (and you cannot) update these UI Macros, or you own them. The great thing they’ve done with Fuji is make it easier to update the cart without invalidating upgrade paths, we just have to figure out the rest now. So, take the ui macro sc_cart_view_buttons at order 800. This is the footer buttons, one of which is checkout. Create a new UI Macro, and copy the XML from the sc_cart_view_buttons ui macro over to the new macro (I called my sc_cart_view_buttons_new). Now, go back to the cart screen, select Edit, and remove the sc_cart_view_buttons, then add the sc_cart_view_buttons_new ui macro. Now, make sure you set it to order 800 or 900 or whatever to have it last. Now you can edit this macro (make sure you didn’t just do insert and stay on the OOTB one or it will be protected and read only as well). So, open this macro, find the line for the checkout button:
Change it to this:
Notice the change in the onClick property. We are calling a function, and if that function returns true, then we perform the checkout method.
Now, we have to capture that new function, so go to System UI -> UI Scripts, create a new UI Script. I called mine, much like Mark did above, checkMandatorySubmit. Here, you will actually check to see if the fields you want are populated. I am checking the special_instructions as well as a custom field I’ve added called sc_cart.approver. Make sure to tick the Global checkbox, and below is the code you will need:
//g_form.getValue('sc_cart.approver'),g_form.getValue('special_instructions')
//alert("Here");
var manFields = '';
var si = gel('sc_cart.approver');
//alert("parm1.value is: " + si.value);
if(si.value == ''){
manFields = 'Approver';
}
var si2 = gel('special_instructions');
//alert("parm2.value is: " + si2.value);
if (si2.value == ''){
if (manFields == ''){
manFields = 'Business Justification';
} else {
manFields = manFields + " and Business Justification";
}
}
if(manFields == ''){
return true;
}
else{
alert('The following mandatory fields are not filled in: ' + manFields);
return false;
}
}
Now, that UI Script uses GlideAjax to call a script include. You will need to create this as well. Below is the information on the script include:
Name: cartAjaxProcessor_Custom
Client Callable: Make sure you check this
Script:
var cartAjaxProcessor_Custom = Class.create();
cartAjaxProcessor_Custom.prototype = Object.extendsObject(AbstractAjaxProcessor, {
updateApprover: function(){
var approver = this.getParameter(‘sysparm_value’);
gs.log(“Approver is: ” + approver);
var cart = new GlideRecord(‘sc_cart’);
cart.addQuery(‘user’, gs.getUserID());
cart.addQuery(‘active’, ‘true’);
cart.orderBy(‘sys_created_on’);
cart.query();
if(cart.next()) {
cart.u_approver = approver;
cart.update();
}
}
});
This script include updates the cart so that the cart will grab the new values. For the custom approver field I added, I had to add a field to the cart to hold this. Now that the cart is updated, we need to get this data over to the request. So, on the request, you create a new business rule to pull the data in from the cart. Below is the information on that Business Rule:
Name: Set Approver from Cart
Table: Request [sc_request]
Insert: True
When: before
Script:
function onBefore(current, previous) {
//This function will be automatically called when this rule is processed.
var user = gs.getUserID();
gs.addInfoMessage(“user is: ” + user);
var gr = new GlideRecord(‘sc_cart’);
gr.addQuery(‘user’, user);
gr.addQuery(‘active’, ‘true’);
gr.orderBy(‘sys_created_on’);
gr.query();
if(gr.next()) {
gs.addInfoMessage(“approver is: ” + gr.u_approver);
current.u_approver = gr.u_approver;
} else {
gs.addInfoMessage(“couldn’t find cart”);
}
}
This should just about do it. I hope this helps you all out, as I know that I spent a very long time figuring this all out.
Junior
I found our reply to “Mandatory Fields on Service Catalog Checkout Form” about getting this to work in FUJI. I would like to use it but you seemed to have omitted something I need. You stated
” So, open this macro, find the line for the checkout button:
Change it to this:
Notice the change in the onClick property. We are calling a function, and if that function returns true, then we perform the checkout method.”
Can you please provide the rest of the what “Change it to this:” actually is?
Okay, so I was half-way asleep whenever I posted my above post. I added a LOT more in there than just making it mandatory. To make it mandatory, all you need is to update the UI Macro, create the UI Script. That’s it. The rest is for copying fields to the cart then the request in the event you add additional fields. I couldn’t figure out how to edit my old post, so if someone can enlighten me on how to edit my own post, that would be awesome 🙂
Junior
I found our reply to “Mandatory Fields on Service Catalog Checkout Form” about getting this to work in FUJI. I would like to use it but you seemed to have omitted something I need. You stated
” So, open this macro, find the line for the checkout button:
Change it to this:
Notice the change in the onClick property. We are calling a function, and if that function returns true, then we perform the checkout method.”
Can you please provide the rest of the what “Change it to this:” actually is?
Junior,
Thanks for the info you’ve posted. However, there is still some piece missing in your post. You did not mention which part of the sc_cart_view_buttons macro has to be edited and how the UI script can be called from it. I’m also working over Fuji version and finding it difficult to edit the xml.
Thanks!
Mark
I using FUJI and have read through all the postings. While Junior’s post was very helpful it appears to be missing something. I can get the checkMandatorySubmit to fire and receive the message “‘The following mandatory fields are not filled in: ” .. but the request is still being submitted.
Any solutions for this