S
ervice-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.

//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 onclick="doSomething()" name="my_custom_macro" id="my_custom_macro"><img src="images/warning.gifx" alt="Show Macro" title="Show Macro" style="padding-right:4px"></a>'
});
}
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…
//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 onclick="doSomething()" name="my_custom_macro" id="my_custom_macro"><img src="images/warning.gifx" alt="Show Macro" title="Show Macro" style="padding-right:4px"></a>'
});
}
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.
//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';
}
}
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
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);
works a treat, much appreciated!!
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.
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.
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
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.
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
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.
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
It probably should, but I’ve never used that before. This is something I would probably take up with ServiceNow support.
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
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 :).
Thanks for confirming I wasn’t missing something.
I’ve raised the issue with support, I’ll feedback when I know more…
Hi Mark,
Is there any way to add a macro to a record producer variable?
Thanks,
Josh
Only by using the catalog client script method I show above. There’s no macro attribute for catalog items, just client scripts.
Yeah, thanks what I figured, but even with the client script method I can’t seem to get it working.
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;
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
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.
Thanks Mark, was reasonably easy in the end.
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
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
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
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.
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.
Take a look at this post for the correct setup for making this work with a catalog item. Towards the bottom you’ll find an example.
https://servicenowguru.wpengine.com/system-ui/ui-macros/add-me-ui-macro-user-group-fields/