Adding a UI Macro to a Non-reference Field

As of the Winter 2011 release, this technique is no longer necessary for most standard form fields. If possible, you should use the ‘field_decorations’ attribute to point to the UI macro for the field. This post may still be useful for those on running instances on a release earlier than Winter 2011 or those needing to add macros to catalog variables. Click here to see an example of adding macros to catalog variables using client scripts. The client script technique for adding UI macro field decorations may still be preferable in certain situations.

Service-now reference fields allow you to add custom UI macros (which generally appear as icons) next to the input element for the field. A couple of common out-of-box examples of this are the ‘Show related incidents’ macro next to the ‘Caller’ field on the incident form and the ‘Show CI map’ icon next to the ‘Configuration item’ field. The main problem with these are that they are ONLY available to reference fields. So, if you want to do the same thing against a choice or string field you’re out of luck.

There is a way around this limitation though using JavaScript DOM manipulation. In Service-now terms, you can add the equivalent of a UI macro to any non-reference field by creating an onLoad client script to add the icon and corresponding onclick (or other) event. Here’s a simple example of an onLoad client script that you could use on the Incident table to display a macro next to the ‘Number’ field.



function onLoad() {
//Add a UI macro to a non-reference field
//Set the name of the field in the 'field' variable
var field = 'number';
//Append the table name to get the field id
field = g_form.tableName + '.' + field;

try{
//Create the image element and add to the dom
$(field).insert({
after: '<a id="my_custom_macro" name="my_custom_macro"></a><img style="padding-right: 4px;" title="Show Macro" src="images/warning.gifx" alt="Show Macro" />'
});
}
catch(e){
//alert('Error');
}
}

//onclick event to fire when the image is clicked
function doSomething() {
alert('You clicked me!');
}

Catalog client script example

The procedure for catalog client scripts is very similar. This is one area where you still need to add UI macros to reference fields via a script. Here’s an example of adding a macro to a catalog variable via a catalog client script…

function onLoad() {
//Add a UI macro to a non-reference field
//Set the name of the field in the 'field' variable
var field = 'caller_id';
//Append the table name to get the field id
field = g_form.getControl(field).id;

try{
//Create the image element and add to the dom
$('lookup.' + field).insert({
after: '<a id="my_custom_macro" name="my_custom_macro"></a><img style="padding-right: 4px;" title="Show Macro" src="images/warning.gifx" alt="Show Macro" />'
});
}
catch(e){
//alert('Error');
}
}

//onclick event to fire when the image is clicked
function doSomething() {
alert('You clicked me!');
}

Field lock example

Here’s another example of an onLoad client script that you could use on the Incident table to display a lock icon next to the ‘Category’ field. The lock icon will show/hide the ‘Subcategory’ field when it is clicked. You could use something like this to show/hide different elements with a click on the icon.

function onLoad() {
//Hide these fields by default
g_form.setDisplay('subcategory', false);

//Add a UI macro to a non-reference field
//Set the name of the field in the 'field' variable
var field = 'category';
//Append the table name to get the field id
field = g_form.tableName + '.' + field;

try{
//Create the image element and add to the dom
var img = document.createElement('img');
img.src = 'images/locked.gifx';
img.alt='Unlock Fields';
img.title='Unlock Fields';
img.id = 'customLock';
var link = document.createElement('a');
if (navigator.appName == 'Microsoft Internet Explorer'){
link.setAttribute('onclick', Function('toggleLockFields()'));
}
else{
link.setAttribute('onclick', 'toggleLockFields()');
}
link.name='lock_fields_macro';
link.id='lock_fields_macro';
link.appendChild(img);
document.getElementById(field).parentNode.appendChild(link);
}
catch(e){
//alert('Error');
}
}

//onclick event to fire when the image is clicked
function toggleLockFields() {
//Toggle the lock icon
var lock = document.getElementById('customLock');
if(lock.src.indexOf('images/locked.gifx') > -1){
//Show the hidden fields
g_form.setDisplay('subcategory', true);

//Change lock to 'unlocked
lock.src = 'images/unlocked.gifx';
lock.alt='Lock Fields';
lock.title='Lock Fields';
}
else{
//Hide all lock fields
g_form.setDisplay('subcategory', false);

//Change lock to 'locked'
lock.src = 'images/locked.gifx';
lock.alt='Unlock Fields';
lock.title='Unlock Fields';
}
}
I recently wrote a post describing the details of lock icon behavior throughout the tool. Check it out here!

Date Posted:

February 16, 2010

Share This:

27 Comments

  1. Marc March 4, 2010 at 12:07 am

    Love this and use it instead of a UI Macro even on a reference field for a customer who wants to only show the icons if the user has a certain role, however, one little thing they asked is why they float all the way to the right before any values are populated, I wondered if this code could be manipluated so that the icon goes all the way to the left instead of at the end of the ui macros

    I think it’s this line that is saying go sit on the end of the line, but is there a way to say sit at the front of the line?

    document.getElementById(field).parentNode.appendChild(link);

    }

    Shame I can’t upload an attachment to show it even better so but mail me if you would like know more or see what I’m talking about. thanks!

    Marc

    • Mark Stanger March 4, 2010 at 1:13 am

      You’re correct about the line that would need to be modified. I think you could get the result you are looking for on a reference field by replacing this…

      document.getElementById(field).parentNode.appendChild(link);

      with this…

      var fieldParent = document.getElementById(field).parentNode;

      var lookupIconSib = document.getElementById(‘lookup.’ + field).nextSibling;

      fieldParent.insertBefore(link,lookupIconSib);

  2. marc March 4, 2010 at 8:53 am

    works a treat, much appreciated!!

  3. Jay Pandya July 7, 2010 at 11:43 pm

    Hi, I’ve got a need for a UI Macro on the Change Reference (field) on a Change Task…I take it this will work for that too as Number is a reference field.

    • Mark Stanger July 8, 2010 at 7:50 am

      There is a different approach for reference fields (number is a string field by the way). You need to add an attribute to the dictionary of the field that you want to have the macro on. That attribute calls your UI macro. I don’t have this approach documented, but you could look at the ‘caller_id’ or ‘cmdb_ci’ fields on the incident table as an example.

  4. mathew May 4, 2011 at 7:55 am

    hai sir i am having some diffulty in understanding the client scripting stuff

    can to give a step by step approach for the second example

    • Mark Stanger May 4, 2011 at 8:30 am

      You should refer to the comments in the code for the steps taken and an explanation of the script. If you have questions about specific pieces of the code please post them and I’ll try to explain further.

  5. Russell Miller July 15, 2011 at 1:28 am

    Hi Mark,

    Love the site.

    After much hair pulling I noticed something while trying to use the ‘field_decoration’ attribute…

    It should actually be ‘field_decorations’ !!! I only worked this out as a hail mary attempt when I noticed that ref_contributions was a plural, and that it does not seem to work on journal fields (note the “most field types” mentioned in the wiki)

    Big shout out to the SNC wiki for having it wrong ;) I’m attempting to have the SNC wiki changed at the moment. Thought I’d post here too as this is my first point of call for SNC insight.

    Cheers

    • Mark Stanger July 15, 2011 at 7:16 am

      Great catch! You’ve probably guessed that the wiki article is exactly where I pulled that info. from. I’ve updated the post above with the change.

  6. Rosa November 21, 2012 at 9:37 am

    Should the field_decorations attribute work on the short_description field of the incident form for the ui_global_text_search macro?

    Many of our Service Desk Agents use the ‘Create New’ in a new window and do not have access to the global search in the heading so they requested to have it added to the Incident form. I’m trying to add it next to the Knowledge Search icon. I can get the search box but the functionality does not work.

    Rosa

    • Mark Stanger November 24, 2012 at 6:28 am

      It probably should, but I’ve never used that before. This is something I would probably take up with ServiceNow support.

  7. Dave March 27, 2013 at 9:05 am

    Hi Mark,

    On a related note, is there a way to make field-decorators on reference fields appear when the field has been made read-only?

    Thanks,

    Dave

    • Mark Stanger March 27, 2013 at 9:09 am

      Dave, there’s no way to do that with the ‘ref_contributions’ or ‘field_decorations’ attributes. The only way to get close to that is to use the client-script method from this article. I believe ServiceNow has identified this limitation as a defect however, so there’s a chance we could see this addressed in a future release. Wouldn’t hurt to open a support ticket with them to add some weight to that request :).

      • Dave March 27, 2013 at 10:18 am

        Thanks for confirming I wasn’t missing something.

        I’ve raised the issue with support, I’ll feedback when I know more…

  8. Joshua April 9, 2013 at 11:33 am

    Hi Mark,

    Is there any way to add a macro to a record producer variable?

    Thanks,

    Josh

    • Mark Stanger April 9, 2013 at 2:07 pm

      Only by using the catalog client script method I show above. There’s no macro attribute for catalog items, just client scripts.

      • Josh April 9, 2013 at 2:12 pm

        Yeah, thanks what I figured, but even with the client script method I can’t seem to get it working.

        • Josh April 15, 2013 at 12:54 pm

          I figured it out for the record producer variables.

          Change line to:

          var field = ‘IO:sysID’; // where sysID is the sysid of the catalog variable which can be found by inspecting the element.
          example: var field = ‘IO:7ba2f43d49ac8d00502a8447d8a49ab0’;

          and remove the line:

          field = g_form.tableName + ‘.’ + field;

  9. David Martin November 13, 2014 at 8:22 am

    Just wondering whether you could do something similar but insert the image from macro into an HTML field? No need for onclick or anything. Just the image into 1 field, what I’m trying to do in a wizard, if a variable changes to X then show an image, if it changes to Y show a different image.

    I can use macro’s in a wizard and can get the images to hide/show using UI Policies but formatting in the panel screen for 15/20 images to be hidden is not good. So just want to try and use 1 field and populate that field with an image dependent on the previous being selected.

    Thanks

    • Mark Stanger November 13, 2014 at 8:27 am

      You can, but that’s really just client-side javascript if you’ve got your macro already in place. You would just need to update the ‘src’ attribute on your image tag. If you’ve created your macro, just make sure your image tag has an ID you can target, then you can use a client script to change the image on change of something else.

      • David Martin November 14, 2014 at 5:17 am

        Thanks Mark, was reasonably easy in the end.

  10. Kevin Clark September 24, 2015 at 1:06 am

    Hi Mark,

    Relatively new to scripting in ServiceNow, so hopefully this isn’t a dumb question… We’ve been trying to adapt this method to bring back some images in a scoped application that we’ve created post-Fuji – we’re finding that the code works in the core Incident module as a client script, but that for some reason it doesn’t work in the scoped application. We’re not entirely sure why they should work differently, except that some scripting resources aren’t available in scoped apps. We can’t se a specific reason why your code shouldn’t work in the scoped app.

    Any thoughts would be appreciated!
    Kevin

    • Mark Stanger September 24, 2015 at 5:57 am

      Welcome to the wild world of scoped apps! :) I’ve found out that in general, they’re not all they’re cracked up to be. I try to avoid them wherever possible. For this situation, there is a workaround. Fuji restricts certain client-side script calls but allows you an app-by-app override if you want. To opt out of this setting create the following property in your application scope and set it to false.
      glide.script.block.client.globals

  11. Kevin Clark September 24, 2015 at 4:36 pm

    Hi Mark,

    That’s a really useful tip! We’ve managed to work around the problem using UI Macros and Formatters instead of a client script. I got the image back that I wanted, now I just need to figure out how to make the Jelly code reference the current record.

    Cheers,
    Kevin

    • Simon May 10, 2016 at 9:58 am

      Kevin, would you be able to share how you accomplished the UI Macro/Formatter combination to add the image?

      My end goal is to have a specific choice on a choice list show an image next to it, that is a button that would bring up a GlideWindow creating a new record on another table. The issue is that everything involved is in a scoped app, and the script at the top keeps catching an error.

  12. Gia March 22, 2017 at 3:07 pm

    This is really helpful! I was able to add an icon-add to a non referenced field through this script for the service catalog.

    My question is how come the icon is placed under the field and not actually beside it.

Comments are closed.

Categories

Tags

Loading

Fresh Content
Direct to Your Inbox

Just add your email and hit subscribe to stay informed.