I
f 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…
–Add the ‘checkMandatorySubmit’ function to the end of the ‘servicecatalog_cart_template’ UI Macro as shown below. 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: servicecatalog_cart_template
XML:
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<!--
assumption is that a cart exists
-->
<g2:evaluate var="jvar_item" expression="
sc_cart = new GlideRecord('sc_cart');
sc_cart.get('user', system.getUserID());
if(sc_cart.sys_id) {
var sc_cart_item = new GlideRecord('sc_cart_item');
sc_cart_item.addQuery('cart', sc_cart.sys_id);
sc_cart_item.addQuery('active', 'true');
var sc_cat_item = new GlideRecord('sc_cat_item');
sc_cat_item.initialize();
sc_cart_item.query();
}
" />
<j:set var="jvar_checkout" value="checkout" />
<j:if test="${jvar_two_step == true}">
<j:set var="jvar_checkout" value="checkouttwo" />
</j:if>
<j:if test="${sysparm_guide == 'true'}">
<g:inline template="com.glideapp.servicecatalog_guide_banner.xml" />
</j:if>
<form method="POST" action="service_catalog.do" name="service_catalog.do" id="sc_cart.do">
<input type="HIDDEN" name="sysparm_view" value="${sysparm_view}" />
<input type="HIDDEN" name="sysparm_action" value="${jvar_checkout}" />
<input type="HIDDEN" name="sys_action" />
<table class="wide" cellspacing="0">
<tr class="header" border="0" cellspacing="0">
<td style="width: 22px;">
<img name="not_important"
value="sysverb_back"
id="sysverb_back"
onClick="gel('sc_cart.do').sysparm_action.value ='sysverb_back';gel('sc_cart.do').submit();"
src="images/green_back.gifx"
title="${gs.getMessage('Back')}"
alt="${gs.getMessage('Back')}"
style="cursor:hand; margin-left: 4px;"/>
</td>
<td class="column_head" colspan="1">
<div class="caption">${gs.getMessage('Shopping Cart')}</div>
</td>
<td></td>
<td class="column_head" align="right" colspan="99">
<j:if test="${jvar_two_step != true}">
<button class="header" onclick="forms['service_catalog.do'].submit()">
${gs.getMessage('Check out')}
</button>
</j:if>
</td>
</tr>
<j2:set var="jvar_never_show_price" value="$[gs.getProperty('glide.sc.price.display') == 'never']" />
<j2:set var="jvar_show_price" value="false" />
<j2:set var="jvar_got_one" value="false" />
<tr>
<td></td>
<td><strong>${gs.getMessage('Item')}</strong></td>
<td><strong>${gs.getMessage('Delivery Time')}</strong></td>
<j2:if test="$[!jvar_never_show_price]">
<td><strong> $[sc_cat_item.price.sys_meta.label] (ea.)</strong></td>
</j2:if>
<td><strong>${gs.getMessage('Quantity')}</strong></td>
<j2:if test="$[!jvar_never_show_price]">
<td><strong>${gs.getMessage('Total')}</strong></td>
</j2:if>
</tr>
<j2:while test="$[sc_cart_item.next()]">
<j2:set var="jvar_got_one" value="true" />
<g2:evaluate var="jvar_cat_item" expression="
sc_cat_item = new GlideRecord('sc_cat_item');
sc_cat_item.addQuery('sys_id','$[sc_cart_item.cat_item]');
sc_cat_item.query();
sc_cat_item.next();" />
<g2:inline template="com.glideapp.servicecatalog_show_price_function.xml" />
<j2:if test="$[show_price]">
<j2:set var="jvar_show_price" value="true" />
</j2:if>
<g2:evaluate var="jvar_line_num" expression="$[jvar_line_num] + 1" />
<g2:evaluate var="jvar_price">
this_price = '--';
if ($[show_price]) {
var helper = new Packages.com.glideapp.servicecatalog.ScriptHelper();
this_price = helper.getCartItemPrice($[sc_cart_item]);
}
</g2:evaluate>
<g2:evaluate var="jvar_subtotal">
subtotal = 0;
if($[show_price])
subtotal = this_price * $[sc_cart_item.quantity];
else
this_price;
</g2:evaluate>
<g2:evaluate var="jvar_total_price" expression="$[jvar_total_price] + subtotal"/>
<j2:set var="jvar_line_color" value="odd" />
<j2:if test="$[jvar_line_num % 2 == 0]" >
<j2:set var="jvar_line_color" value="even" />
</j2:if>
<tr class="$[jvar_line_color]">
<td valign="top">
<a href="service_catalog.do?sysparm_action=cart_remove&sysparm_id=$[sc_cart_item.sys_id]"><img src="images/cart_delete.pngx" alt="Remove from cart"/></a>
<a href="com.glideapp.servicecatalog_cat_item_view.do?sysparm_view=${sysparm_view}&sysparm_id=$[sc_cart_item.cat_item]&sysparm_cart_edit=$[sc_cart_item.sys_id]"><img src="images/cart_edit_small.pngx" alt="Edit cart entry"/></a>
</td><td valign="top">
<g2:call function="variable_summary_cart.xml" question_name="$[sc_cart_item.sys_id]"
question_help_tag="$[sc_cat_item.name.getDisplayValue() + ' - ' +sc_cat_item.short_description.getDisplayValue()]"
sc_item_option_id ="$[sc_cart_item.sys_id]"
help_class="$[jvar_line_color]"/>
</td>
<td valign="top">
<j2:set var="jvar_wf" value="$[sc_cat_item.workflow]"/>
<j2:if test="$[!empty(jvar_wf)]">
<g2:evaluate var="jvar_wf_delivery_time" expression="new Workflow().getEstimatedDeliveryTime('$[jvar_wf]');" />
$[jvar_wf_delivery_time]
</j2:if>
<j2:if test="$[empty(jvar_wf)]">
$[sc_cat_item.delivery_plan.total_delivery_time.getDisplayValue()]
</j2:if>
</td>
<j2:if test="$[!jvar_never_show_price]">
<td valign="top"><g2:currency_format double="$[this_price]"/></td>
</j2:if>
<td valign="top">$[sc_cart_item.quantity]</td>
<j2:if test="$[!jvar_never_show_price]">
<td valign="top"><g2:currency_format double="$[jvar_subtotal]"/></td>
</j2:if>
</tr>
</j2:while>
<g2:evaluate var="jvar_subtotal_price" expression="if($[jvar_show_price])$[jvar_total_price];else '--';"/>
<tr>
<td><hr/></td>
<td><hr/></td>
<td><hr/></td>
<td><hr/></td>
<j2:if test="$[!jvar_never_show_price]">
<td><hr/></td>
<td><hr/></td>
</j2:if>
</tr>
<j2:if test="$[!jvar_never_show_price]">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td><strong>${gs.getMessage('Total')}:</strong></td>
<td><strong><g2:currency_format double="$[jvar_subtotal_price]"/></strong></td>
</tr>
</j2:if>
<j2:if test="$[jvar_got_one == false]">
<tr>
<td>${gs.getMessage('Cart is empty')}</td>
</tr>
</j2:if>
</table>
<j:if test="${jvar_two_step == true}">
<table class="wide" cellspacing="0" >
<j:set var="ref" value="sc_cart" />
<j:set var="jvar_skip_attachment_footer" value="true" />
<j2:set var="jvar_ref" value="$[sc_cart.requested_for]"/>
<j2:set var="jvar_ref_display" value="$[sc_cart.requested_for.getDisplayValue()]" />
<g2:evaluate var="jvar_can_delta_rf" expression="
var helper = new Packages.com.glideapp.servicecatalog.CalculationHelper();
helper.canViewRF();
"/>
<tr>
<td>$[SP]</td>
</tr>
<tr class="header">
<td width="30%" >
${gs.getMessage('Requested for')}:
</td>
<td width="70%">
${gs.getMessage('Deliver to')}:
</td>
</tr>
<tr><td>$[SP]</td></tr>
<tr>
<td valign="top">
<j2:if test="$[jvar_can_delta_rf == false]">
$[sc_cart.requested_for.getDisplayValue()]
</j2:if>
<j2:if test="$[jvar_can_delta_rf != false]">
<g2:catalog_requested_for />
</j2:if>
</td>
<td>
<textarea id="requestor_location" style="width: 100%" rows="4"
name="requestor_location" wrap="soft" >
$[sc_cart.delivery_address]
</textarea>
</td>
</tr>
<tr>
<td>$[SP]</td>
</tr>
<tr class="header" >
<td>
${gs.getMessage('Special instructions')}
</td>
<td align="right">${gs.getMessage('Add attachment...')}
<a onclick="saveCartAttachment('$[sc_cart.sys_id]');">
<img src="images/icons/attachment.gifx" width="16" height="16"
border="0" title="${gs.getMessage('Attachments')}"/>
</a>
</td>
</tr>
<tr>
<td colspan="2">
<g:inline template="attachment_list.xml" />
</td>
</tr>
<tr>
<td colspan="2">
<textarea id="special_instructions" style="width: 100%" rows="6"
name="special_instructions" wrap="soft" > $[sc_cart.special_instructions]
</textarea>
</td>
</tr>
<j:if test="${jvar_suppress_buttonbar != 'true'}">
<tr>
<td align="left" width="50%">
<j2:set var="jvar_show_back" value="$[gs.getProperty('glide.sc.checkout.twostep.back')]" />
<j2:if test="$[jvar_show_back == 'true']">
<j2:if test="$[sysparm_guide != 'true']">
<button class="catalog catalog_previous" onclick="window.location='catalog_home.do?sysparm_view=catalog_default';return false;">
${gs.getMessage('Back to Catalog');}
</button>
</j2:if>
<j2:if test="$[sysparm_guide == 'true']">
<button class="catalog catalog_previous" onclick="window.location='service_catalog.do?sysparm_action=restart_guide';return false;">
${gs.getMessage('Describe Needs');}
</button>
</j2:if>
</j2:if>
</td>
<td align="right" width="50%">
<button class="catalog catalog_next" type="submit" value="sysverb_insert" onClick="return checkMandatorySubmit();" id="sysverb_insert">
${gs.getMessage('Submit Order');}
</button>
</td>
</tr>
</j:if>
</table>
<j2:set var="jvar_address" value="$[sc_cart.delivery_address]"/>
<j2:set var="jvar_p2flow_all_visible_fields" value="requested_for" />
<g:client_script tableName="sc_cart" type="phase1"/>
<g2:client_script tableName="sc_cart" file="$[sc_cart]"/>
</j:if>
</form>
<script>
function checkMandatorySubmit(){
var manFields = '';
var si = gel('special_instructions').value;
if(si == ''){
manFields = 'Special Instructions';
}
if(manFields == ''){
gsftSubmit();
}
else{
alert('The following mandatory fields are not filled in: ' + manFields);
return false;
}
}
</script>
</j:jelly>
Here’s another example macro that makes the ‘Requested for’ field mandatory for ‘ITIL’ users.
Name: servicecatalog_cart_template
XML:
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<!--
assumption is that a cart exists
-->
<g2:evaluate var="jvar_item" expression="
sc_cart = new GlideRecord('sc_cart');
sc_cart.get('user', system.getUserID());
if(sc_cart.sys_id) {
var sc_cart_item = new GlideRecord('sc_cart_item');
sc_cart_item.addQuery('cart', sc_cart.sys_id);
sc_cart_item.addQuery('active', 'true');
var sc_cat_item = new GlideRecord('sc_cat_item');
sc_cat_item.initialize();
sc_cart_item.query();
}
" />
<j:set var="jvar_checkout" value="checkout" />
<j:if test="${jvar_two_step == true}">
<j:set var="jvar_checkout" value="checkouttwo" />
</j:if>
<j:if test="${sysparm_guide == 'true'}">
<g:inline template="com.glideapp.servicecatalog_guide_banner.xml" />
</j:if>
<form method="POST" action="service_catalog.do" name="service_catalog.do" id="sc_cart.do">
<input type="HIDDEN" name="sysparm_view" value="${sysparm_view}" />
<input type="HIDDEN" name="sysparm_action" value="${jvar_checkout}" />
<input type="HIDDEN" name="sys_action" />
<table class="wide" cellspacing="0">
<tr class="header" border="0" cellspacing="0">
<td style="width: 22px;">
<img name="not_important"
value="sysverb_back"
id="sysverb_back"
onClick="gel('sc_cart.do').sysparm_action.value ='sysverb_back';gel('sc_cart.do').submit();"
src="images/green_back.gifx"
title="${gs.getMessage('Back')}"
alt="${gs.getMessage('Back')}"
style="cursor:hand; margin-left: 4px;"/>
</td>
<td class="column_head" colspan="1">
<div class="caption">${gs.getMessage('Shopping Cart')}</div>
</td>
<td></td>
<td class="column_head" align="right" colspan="99">
<j:if test="${jvar_two_step != true}">
<button class="header" onclick="forms['service_catalog.do'].submit()">
${gs.getMessage('Check out')}
</button>
</j:if>
</td>
</tr>
<j2:set var="jvar_never_show_price" value="$[gs.getProperty('glide.sc.price.display') == 'never']" />
<j2:set var="jvar_show_price" value="false" />
<j2:set var="jvar_got_one" value="false" />
<tr>
<td></td>
<td><strong>${gs.getMessage('Item')}</strong></td>
<td><strong>${gs.getMessage('Delivery Time')}</strong></td>
<j2:if test="$[!jvar_never_show_price]">
<td><strong> $[sc_cat_item.price.sys_meta.label] (ea.)</strong></td>
</j2:if>
<td><strong>${gs.getMessage('Quantity')}</strong></td>
<j2:if test="$[!jvar_never_show_price]">
<td><strong>${gs.getMessage('Total')}</strong></td>
</j2:if>
</tr>
<j2:while test="$[sc_cart_item.next()]">
<j2:set var="jvar_got_one" value="true" />
<g2:evaluate var="jvar_cat_item" expression="
sc_cat_item = new GlideRecord('sc_cat_item');
sc_cat_item.addQuery('sys_id','$[sc_cart_item.cat_item]');
sc_cat_item.query();
sc_cat_item.next();" />
<g2:inline template="com.glideapp.servicecatalog_show_price_function.xml" />
<j2:if test="$[show_price]">
<j2:set var="jvar_show_price" value="true" />
</j2:if>
<g2:evaluate var="jvar_line_num" expression="$[jvar_line_num] + 1" />
<g2:evaluate var="jvar_price">
this_price = '--';
if ($[show_price]) {
var helper = new Packages.com.glideapp.servicecatalog.ScriptHelper();
this_price = helper.getCartItemPrice($[sc_cart_item]);
}
</g2:evaluate>
<g2:evaluate var="jvar_subtotal">
subtotal = 0;
if($[show_price])
subtotal = this_price * $[sc_cart_item.quantity];
else
this_price;
</g2:evaluate>
<g2:evaluate var="jvar_total_price" expression="$[jvar_total_price] + subtotal"/>
<j2:set var="jvar_line_color" value="odd" />
<j2:if test="$[jvar_line_num % 2 == 0]" >
<j2:set var="jvar_line_color" value="even" />
</j2:if>
<tr class="$[jvar_line_color]">
<td valign="top">
<a href="service_catalog.do?sysparm_action=cart_remove&sysparm_id=$[sc_cart_item.sys_id]"><img src="images/cart_delete.pngx" alt="Remove from cart"/></a>
<a href="com.glideapp.servicecatalog_cat_item_view.do?sysparm_view=${sysparm_view}&sysparm_id=$[sc_cart_item.cat_item]&sysparm_cart_edit=$[sc_cart_item.sys_id]"><img src="images/cart_edit_small.pngx" alt="Edit cart entry"/></a>
</td><td valign="top">
<g2:call function="variable_summary_cart.xml" question_name="$[sc_cart_item.sys_id]"
question_help_tag="$[sc_cat_item.name.getDisplayValue() + ' - ' +sc_cat_item.short_description.getDisplayValue()]"
sc_item_option_id ="$[sc_cart_item.sys_id]"
help_class="$[jvar_line_color]"/>
</td>
<td valign="top">
<j2:set var="jvar_wf" value="$[sc_cat_item.workflow]"/>
<j2:if test="$[!empty(jvar_wf)]">
<g2:evaluate var="jvar_wf_delivery_time" expression="new Workflow().getEstimatedDeliveryTime('$[jvar_wf]');" />
$[jvar_wf_delivery_time]
</j2:if>
<j2:if test="$[empty(jvar_wf)]">
$[sc_cat_item.delivery_plan.total_delivery_time.getDisplayValue()]
</j2:if>
</td>
<j2:if test="$[!jvar_never_show_price]">
<td valign="top"><g2:currency_format double="$[this_price]"/></td>
</j2:if>
<td valign="top">$[sc_cart_item.quantity]</td>
<j2:if test="$[!jvar_never_show_price]">
<td valign="top"><g2:currency_format double="$[jvar_subtotal]"/></td>
</j2:if>
</tr>
</j2:while>
<g2:evaluate var="jvar_subtotal_price" expression="if($[jvar_show_price])$[jvar_total_price];else '--';"/>
<tr>
<td><hr/></td>
<td><hr/></td>
<td><hr/></td>
<td><hr/></td>
<j2:if test="$[!jvar_never_show_price]">
<td><hr/></td>
<td><hr/></td>
</j2:if>
</tr>
<j2:if test="$[!jvar_never_show_price]">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td><strong>${gs.getMessage('Total')}:</strong></td>
<td><strong><g2:currency_format double="$[jvar_subtotal_price]"/></strong></td>
</tr>
</j2:if>
<j2:if test="$[jvar_got_one == false]">
<tr>
<td>${gs.getMessage('Cart is empty')}</td>
</tr>
</j2:if>
</table>
<j:if test="${jvar_two_step == true}">
<table class="wide" cellspacing="0" >
<j:set var="ref" value="sc_cart" />
<j:set var="jvar_skip_attachment_footer" value="true" />
<j2:set var="jvar_ref" value="$[sc_cart.requested_for]"/>
<j2:set var="jvar_ref_display" value="$[sc_cart.requested_for.getDisplayValue()]" />
<g2:evaluate var="jvar_can_delta_rf" expression="
var helper = new Packages.com.glideapp.servicecatalog.CalculationHelper();
helper.canViewRF();
"/>
<tr>
<td>$[SP]</td>
</tr>
<tr class="header">
<td width="30%" >
${gs.getMessage('Requested for')}:
</td>
<td width="70%">
${gs.getMessage('Deliver to')}:
</td>
</tr>
<tr><td>$[SP]</td></tr>
<tr>
<td valign="top">
<j2:if test="$[jvar_can_delta_rf == false]">
$[sc_cart.requested_for.getDisplayValue()]
</j2:if>
<j2:if test="$[jvar_can_delta_rf != false]">
<g2:catalog_requested_for />
</j2:if>
</td>
<td>
<textarea id="requestor_location" style="width: 100%" rows="4"
name="requestor_location" wrap="soft" >
$[sc_cart.delivery_address]
</textarea>
</td>
</tr>
<tr>
<td>$[SP]</td>
</tr>
<tr class="header" >
<td>
${gs.getMessage('Special instructions')}
</td>
<td align="right">${gs.getMessage('Add attachment...')}
<a onclick="saveCartAttachment('$[sc_cart.sys_id]');">
<img src="images/icons/attachment.gifx" width="16" height="16"
border="0" title="${gs.getMessage('Attachments')}"/>
</a>
</td>
</tr>
<tr>
<td colspan="2">
<g:inline template="attachment_list.xml" />
</td>
</tr>
<tr>
<td colspan="2">
<textarea id="special_instructions" style="width: 100%" rows="6"
name="special_instructions" wrap="soft" > $[sc_cart.special_instructions]
</textarea>
</td>
</tr>
<j:if test="${jvar_suppress_buttonbar != 'true'}">
<tr>
<td align="left" width="50%">
<j2:set var="jvar_show_back" value="$[gs.getProperty('glide.sc.checkout.twostep.back')]" />
<j2:if test="$[jvar_show_back == 'true']">
<j2:if test="$[sysparm_guide != 'true']">
<button class="catalog catalog_previous" onclick="window.location='catalog_home.do?sysparm_view=catalog_default';return false;">
${gs.getMessage('Back to Catalog');}
</button>
</j2:if>
<j2:if test="$[sysparm_guide == 'true']">
<button class="catalog catalog_previous" onclick="window.location='service_catalog.do?sysparm_action=restart_guide';return false;">
${gs.getMessage('Describe Needs');}
</button>
</j2:if>
</j2:if>
</td>
<td align="right" width="50%">
<button class="catalog catalog_next" type="submit" value="sysverb_insert" onClick="return checkMandatorySubmit();" id="sysverb_insert">
${gs.getMessage('Submit Order');}
</button>
</td>
</tr>
</j:if>
</table>
<j2:set var="jvar_address" value="$[sc_cart.delivery_address]"/>
<j2:set var="jvar_p2flow_all_visible_fields" value="requested_for" />
<g:client_script tableName="sc_cart" type="phase1"/>
<g2:client_script tableName="sc_cart" file="$[sc_cart]"/>
</j:if>
</form>
<script>
addLoadEvent(clearRequestedFor);
function clearRequestedFor(){
if(g_user.hasRole('itil')){
//Clear the 'Requested for' field
var rf = gel('sys_display.sc_cart.requested_for');
var rf1 = gel('sys_original.sc_cart.requested_for');
var rf2 = gel('sc_cart.requested_for');
var rfIcon = gel('view.sc_cart.requested_for');
rf.value = '';
rf1.value = '';
rf2.value = '';
rfIcon.style.display = 'none';
}
}
function checkMandatorySubmit(){
var manFields = '';
var si = gel('sc_cart.requested_for').value;
if(si == ''){
manFields = 'Requested for';
}
if(manFields == ''){
gsftSubmit();
}
else{
alert('The following mandatory fields are not filled in: ' + manFields);
return false;
}
}
</script>
</j:jelly>
Comments
Posted On
Feb 22, 2010Posted By
alliHi,
can you add other variables here? like a glide list? and pass it on the request?
thanks
alli
Posted On
Feb 23, 2010Posted By
Mark StangerIt 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.
http://www.servicenowguru.com/system-ui/adding-fi…
Posted On
Feb 23, 2010Posted By
alliI tried that one, but I can’t make the glide list work
Posted On
Dec 29, 2010Posted By
Jason StephensThis works great. You saved me a lot of work on this one. As always – thanks Mark!
Posted On
Jan 04, 2011Posted By
Jason StephensI 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.