L

ast week I had a request come in from a client where they wanted to require users to accept certain terms and conditions before ordering a specific catalog item. I have seen this type of request before, but I don’t think I’ve really seen an elegant solution to it…or anything that could really be called a solution at all :). Usually you end up with some combination of a wizard, some custom form, and some crazy scripts that make no sense to anyone but the person who created it. Then I realized that I had just written about a solution a week or so ago when I wrote about how to create a UI Page popup using GlideDialogWindow! The specific application of the solution I wrote about was a little bit different, but the basic pieces were identical. By making some basic tweaks to a solution I already knew about, I was able to come up with what I think is a really nice way to require acceptance of some terms before a user orders a catalog item. This same method could also be used on other forms and tables in ServiceNow.



The first part of this solution is to set up a client-side trigger for your terms dialog. For this example, we assume that the Terms dialog only needs to be displayed for a particular catalog item so our trigger can be in an ‘onLoad’ catalog client script set against the item in question. The script simply needs to create and render the dialog when the item (or potentially variables) load. It also needs to point to a UI Page (by name) that should load within the dialog. It’s the UI Page that will contain all of the specific form elements and terms. If you want your dialog to redirect to a specific location if the ‘Cancel’ button is clicked you can include the ‘cancel_url’ preference as shown below…

‘Load Terms’ Catalog Client Script
Name: Load Terms
Type: onLoad
Script:

function onLoad() {
   //Initialize and open the Dialog Window
   var dialog = new GlideDialogWindow('terms_and_conditions_dialog'); //Render the dialog containing the UI Page 'terms_and_conditions_dialog'
   dialog.setTitle('Terms and Conditions'); //Set the dialog title
   dialog.setSize(600,600); //Set the dialog size
   dialog.removeCloseDecoration(); //Remove the dialog close icon
   dialog.setPreference('cancel_url', 'catalog_home.do?sysparm_view=catalog_default'); //Set optional cancel redirect URL
   dialog.render(); //Open the dialog
}

Now that we’ve set up a trigger, we need to make sure that we have a UI Page with the correct name to be triggered. Notice in the script above that we’re looking for a UI Page named ‘terms_and_conditions_dialog’ in our dialog client script. The correct name is the only absolute in the UI Page. It needs to match the name given in the client script trigger.
The other elements of the UI Page are up to you. Typically when I’ve seen a terms and conditions page, the page contains the terms, an ‘Agree’ checkbox of some sort, and buttons to agree or cancel. I’ve commented those portions of code below. The buttons both trigger specific client-side functions that make sure the ‘Agree’ checkbox is checked (for the ‘OK’ button) and redirect back to the default homepage – or the homepage passed in via the ‘cancel_url’ parameter (for the ‘Cancel’ button). The only thing I haven’t provided is the actual terms and formatting. In order to produce that in a nice HTML format, I actually cheated and pasted my terms into the HTML editor on a blank KB article. Then I could get it formatted like I want and then just toggle to the code editor and copy the HTML into the correct place in my UI Page…

‘terms_and_conditions_dialog’ UI Page
HTML

<g:ui_form>
   <!-- Get values from dialog preferences passed in -->
   <g:evaluate var="jvar_cancel_url"
     expression= "RP.getWindowProperties().get('cancel_url')" />
   <input type="hidden" id="cancel_url" value="${jvar_cancel_url}" />
   <table width="100%">
     <tr>
       <td>
          <div style="width:584px; height:400px; overflow:auto; border: 1px solid gray;">
             ENTER YOUR TERMS HERE...
          </div>
       </td>
     </tr>
     <tr>
       <td>
         <div style="margin-top: 10px;">
           <!-- Pull in 'ui_checkbox' UI Macro for accept checkbox -->
           <g:ui_checkbox id="accept_terms" name="accept_terms" value="false"/>
           <label for="load_demo">I accept these terms and conditions.</label>  
         </div>
       </td>
     </tr>
     <tr>
       <td colspan="2">
       </td>
     </tr>
     <tr id="dialog_buttons">
        <td colspan="2" align="right">
           <!-- Pull in 'dialog_buttons_ok_cancel' UI Macro for submit/cancel buttons -->
           <g:dialog_buttons_ok_cancel ok="return termsOK()" cancel="termsCancel()" ok_type="button" cancel_type="button"/>
        </td>
     </tr>
  </table>
</g:ui_form>

Client Script

function termsOK(){
   //Gets called if the 'OK' dialog button is clicked
   //Make sure terms have been accepted
   var terms = gel('accept_terms').value;
   if(terms != 'true'){
      //If terms are false stop submission
      alert('Please accept the terms and conditions to continue your order.');
      return false;
   }
   //If accept checkbox is true do this...
   GlideDialogWindow.get().destroy(); //Close the dialog window
   //g_form.setValue('myvar', true); //Optionally set the value of a variable or field indicating acceptance
}

function termsCancel(){
   //Redirect gets called if the 'Cancel' dialog button is clicked
   if($('cancel_url').value != 'null'){
      window.location = $('cancel_url').value;
   }
   else{
      window.location = 'home.do'; //Redirect to default homepage
   }
}