T
his post comes in response to a question I saw this morning on the ServiceNow forum. The request was to be able to create ‘Add me’ icons for user and group fields that would act the same way as the ‘Add me’ field on list fields. This post shows you how!
This functionality can be created for both user and group fields by adding a UI macro and associating it to the field in question. UI macros are defined by navigating to ‘System UI -> UI macros’ in your left nav.
‘Add me’ UI macro for user fields
Name: add_me
XML:
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<j:set var="jvar_n" value="add_me_${ref}"/>
<span id="${jvar_n}" onclick="addMe('${ref}')" title="Add me" alt="Add me" tabindex="0" class="btn btn-default icon-user-add">
<span class="sr-only">Add me</span>
</span>
<script>
function addMe(reference) {
//Get the user reference field and populate the current user
var s = reference.split('.');
var referenceField = s[1];
g_form.setValue(referenceField, '$[gs.getUserID()]');
}
</script>
</j:jelly>
–Once you’ve created the macro you need to invoke it on your user field by adding the ‘ref_contributions=add_me’ attribute to the dictionary of the user field.
‘Add me’ UI macro for ‘Assigned to’ fields
–Based on the comments below I realized that this is probably going to be used pretty often for a field like the ‘Assigned to’ field for tasks, where the user field is actually dependent on a group field like ‘Assignment group’. The problem with the script above in these situations is that it doesn’t respect the dependency, allowing you to add yourself even though you’re not a member of the currently-selected group.
Implementing an elegant workaround for this scenario becomes difficult because ServiceNow doesn’t natively provide group membership information to client scripts. I’ve come up with a nice workaround that uses the UI macro to cache that information when it is rendered at the server. The following UI macro code will add the ‘Add me’ UI macro to a field like ‘Assigned to’, but will alert users if they are not a member of the current assignment group.
Name: add_me
XML:
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<j:set var="jvar_n" value="add_me_${ref}"/>
<span id="${jvar_n}" onclick="addMe('${ref}')" title="Add me" alt="Add me" tabindex="0" class="btn btn-default icon-user-add">
<span class="sr-only">Add me</span>
</span>
<g2:evaluate var="jvar_groups" expression="gs.getUser().getMyGroups()" />
<script>
function addMe(reference) {
//Hide any field messages
g_form.hideFieldMsg('assigned_to', true);
//Check to see if the user is a member of selected group
var aGrp = g_form.getValue('assignment_group');
var myGroups = '$[jvar_groups]';
if(aGrp){
if(myGroups.indexOf(aGrp) > -1){
//Get the user reference field and populate the current user
var s = reference.split('.');
var referenceField = s[1];
g_form.setValue(referenceField, '$[gs.getUserID()]');
}
else{
//Display a field error message
g_form.showFieldMsg('assigned_to','You are not a member of the current assignment group. Please select one of your groups and try again.','error');
}
}
else{
//Get the user reference field and populate the current user
var s = reference.split('.');
var referenceField = s[1];
g_form.setValue(referenceField, '$[gs.getUserID()]');
}
}
</script>
</j:jelly>
‘Add my group’ UI macro for group fields
The group scenario is a bit more complicated because there’s not a built-in system concept of a primary group. Since each user can be a member of multiple groups you’ll need to decide how to deal with this in your environment. I think if I was setting it up, I’d put a ‘Primary’ field on the ‘sys_user_grmember’ table. This field could be modified by list editing the ‘Groups’ related list on the user form.
For this example, I’ve just set up the code so that it looks at the group membership table (and optionally for a ‘u_primary’ field on that table). The script finds the first group that matches the query (member of a group or having a primary group defined) and populates that group in the reference field. Otherwise, an alert appears indicating that the user isn’t a member of any groups or that a primary group doesn’t exist. You can adjust the ‘addMyGroup’ function below to meet your specific needs.
Name: add_my_group
XML:
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<j:set var="jvar_n" value="add_my_group_${ref}"/>
<span id="${jvar_n}" onclick="addMyGroup('${ref}')" title="Add my group" alt="Add my group" tabindex="0" class="btn btn-default icon-user-group">
<span class="sr-only">Add my group</span>
</span>
<script>
function addMyGroup(reference) {
//Get the group reference field and populate the first group queried
var s = reference.split('.');
var referenceField = s[1];
var grpRec = new GlideRecord('sys_user_grmember');
grpRec.addQuery('user', '$[gs.getUserID()]');
//Uncomment the following line if using a 'Primary' boolean field on the 'sys_user_grmember' table
//grpRec.addQuery('u_primary', true);
grpRec.query(groupCallback);
//After the server returns the query recordset, continue here
function groupCallback(grpRec){
//Hide any previous field messages
try{
g_form.hideFieldMsg(referenceField, true);
}catch(e){}
//Check to see if the user is a member of a single group
if(grpRec.next()){
//Populate the first group found
g_form.setValue(referenceField, grpRec.group);
}
else{
g_form.showFieldMsg(referenceField,'You are not a member of any groups or have no primary group defined.','error');
}
}
}
</script>
</j:jelly>
–Once you’ve created the macro you need to invoke it on your group field by adding the ‘ref_contributions=add_my_group’ attribute to the dictionary of the group field.
The concepts above can also be applied to catalog variables. Unfortunately, ServiceNow doesn’t support field decorations or reference attributes for variables so the whole thing needs to be done with an ‘onLoad’ client script. Below is an example showing how to add the ‘Add me’ icon next to a user reference variable named ‘caller_id’. This concept can be extended to work with most catalog variables by changing the variable name and removing ‘lookup.’ from the script below for non-reference variables. Then you just have to adjust the various element attributes and ‘onclick’ function to use it in other ways.
//The variable name to put the icon next to
var varName = 'caller_id';
try{
//Add the icon decoration to the reference field
//If not reference variable, remove 'lookup.' below
var varEl = 'lookup.' + g_form.getControl(varName).id;
$(varEl).insert({
after: '<span><a id="add_me_macro" class="btn btn-default sc-ref-spacer icon-user sn-tooltip-basic" title="" data-original-title="Add me"></a></span>'
});
//Add the 'onclick' event
$('add_me_macro').observe('click', addMe);
}catch(e){}
function addMe(){
//Add current user to reference field
g_form.setValue(varName, g_user.userID);
}
}
That looks pretty good!!!
One small question, what happens if the assigned_to has a dependency on the assignment_group? Should that still “add me” even though I’m not a member of that group?
Cheers,
Johnny
Good question, and one I figured would come up. This functionality does not do any checks against the reference qualifiers for the user or group fields. It is possible to assign something to yourself even though the ref qual says you shouldn’t. My assumption is that the risk of allowing that to happen is pretty low so I didn’t include the extra complexity to try and check for that.
this is great functionality and took me no more than 10-15 mins to implement in our UAT so thanks heaps for this. However, we do have a dependency as Jonatan Jardi posted, the {assigned_to} is dependant on {assignment_group}. has anyone done any work on getting the add_me macro to check for dependency?
Here is what worked for us….
http://pastie.textmate.org/private/hxzc7f54kq4cepkjkpmxtq
Nice. Thanks for sharing!
We (Actually a Java Guru onsite) added the following onChange client script, which is configured to our environment against the assignment Group field
It is very similar to Patrick’s.
http://pastie.org/8400591
We also added a onLoad Client Script to Hide the Add_me
http://pastie.org/8400599
Thanks Patrick.
Hi Mark,
Slightly off this topic, but only just..
Is there a way to prevent the add me icon appearing? Like an attribute on the glide_list field?
Currently I have a client script which hides the icon, which works when the form is loaded, but after the user has unlocked and locked again, the icon appears.
any help appreciated.
Jason
There may be, but I’m not aware of it if it exists. Why not just remove the icon entirely in your client script on form load?
Hi Mark
Changed the hide() to remove() and that did the trick…
Cheers
Jason
I am a new user to SN and taking over some admin tasks.
Per the above article, To invoke UI Macro (add_me) on a user field by adding the ‘ref_contributions=add_me’ attribute to the dictionary of the user field: I am confused where and how to add ‘ref_contributions=add_me’ to invoke this ui macro. Does it need ot be added to assigned_to field on Task table or sys_user table, if sys_user table them on what field and where?
Thanks in advance.
Kumar
ref_contributions are added to the reference field that you want the macro to appear next to. For this example, you would add it to the ‘assigned_to’ field.
Thanks Mark for the quick reply. I added it to the assigned_to field as a dictionary overrides attibute. It worked. Thanks very much.
Used a client script to hide the addMe icon on load, when you click the lock it comes back again, I guess the only way to re-hide the lock is wait for the lock clicking event right? is that what you did to kill it completely jason?
Hi Marc
I used the following
[code]
$(‘add_me_locked.u_demand.u_vrm’).remove();
$(‘add_me.u_demand.u_vrm’).remove();
[/code]
this removes both add_me icons, when its locked and when its opened (unlocked).
nice one, works great.
Marc
Hi Mark,
Very nice and helpful article.
But the problem I noticed is when we selected some records from the recordlist and select the ‘Update Selected’ , table related (example incident) form will be shown on screen. On this form ‘Add me’ icons are visible but we click on it, it is not populating the data inot the related fields (assigned to or group).
Do you know the reason behind it?
Thank you
Krishna
Thanks for the feedback! The problem is that the ‘Update Selected’ and ‘Update All’ form doesn’t include the ‘g_user’ object like regular forms do. Because of this, you have to pass the user ID in from the macro itself. I’ve updated both of the UI Macros above with the new code. Give it a try and let me know how it goes.
Hi Mark,
Thanks for the updated macors. Now both of them are working fine.
One thing I noticed is for asignment group, if I add ref_contributions=add_my_group in the attribute after tree_picker=true (like this tree_picker=true;ref_contributions=add_my_group;) then ‘Add My Group’ icon is not showing up on the form. But If I changed it to (ref_contributions=add_my_group;tree_picker=true) then ‘Add My Group’ icon was visible and working but I am loosing the tree picker.
So I think treepicker and ref_contributions doesn’t work together. Is my undersatanding right?
Thank you
Krishna
They’ll work together. Try separating your attributes with a comma rather than a semicolon.
Sorry Mark, it’s my mistake I didn’t noticed that I actually used a ; instead of ,. By the way thanks for your the update.
One small update when we implemented this in our instance we found it possible for a user to get another users name out into the assigned to field when clicking this button. It looks like this occurred only when the accounts were identical(same groups and roles). It seems like the sysid was stored in the cache somehow. This was remedied by changing ${gs.getUserID()} to $[gs.getUserID()] the [ ] enable phase 2 processing
Thanks for the update! A perfect example of why you need to be careful with Jelly phases. 🙂 I just updated the code above to reflect this change.
HI
I am placing a ui macro ‘ok cancel form button’ on a form.. I am facing a problem that while clicking on any of the button by action is being performed but after that my form is being reload but i want that it should redirect to the parent form ….
Please anyone can help me on this
Regards
Akshat
Your question doesn’t really pertain to this article, but the solution can be found here…
https://servicenowguru.wpengine.com/system-ui/glidedialogwindow-advanced-popups-ui-pages/
You need to add ‘ok_type=”button’ to your buttons call.
So just getting around to implement this option. Having problems on the Assignment Group. We don’t use Primary Assignment Groups and most users are in two groups. We were hoping to to try something like: g_form.setDisplayValue(referenceField, “**”); Thinking this would insert the wildcards into the field on start the drop down feature. We find trying it this way is different than typing ** into that field.
Any idea how we can pass in the wildcards into the ‘referenceField’ field?
You can set those values like this…
g_form.getDisplayBox(‘assignment_group’).value = ‘**’;
The problem I’m running into is executing the right key press event to trigger the autocomplete. I’ll let you know if I find anything, but I don’t have an answer to that right now.
Mark,
Tried to combine both macros into one macro to be able to auto populate Assignment Group based on the Assigned To’s group membership. I did a g_form.setvalue(‘assigned_to’, ) and g_form.servalue(‘assignment_group’, ) for both, but it blanks out the Assigned To upon auto populating the Assignment Group.
Mark, I implemented this solution on my SN system and it works perfect. The only part that I have not been able to get working is the Primary group . I added the field on to the group membership table but I am not sure how to add the code to the UI Macro so it populated the Assignment Group from the Primary Field. Any Help you can provide will be great…
That should be as simple as adding a single line to your callback function then. Find this line…
and add a new query line directly below it…(note that this assumes the name of your field on the ‘sys_user_grmember’ table is ‘u_primary’)
Mark thank you for getting back to me. I added the line as you said…
//Get the group reference field and populate the first group queried
var s = reference.split('.');
var referenceField = s[1];
var grpRec = new GlideRecord('sys_user_grmember');
grpRec.addQuery('user', '$[gs.getUserID()]');
grpRec.addQuery('u_primary', true);
grpRec.query(groupCallback);
//After the server returns the query recordset, continue here
function groupCallback(grpRec){
//Check to see if the user is a member of a single group
if(grpRec.next()){
if(grpRec.rows.length == 1){
//Populate for a single group
g_form.setValue(referenceField, grpRec.group);
}
else{
alert('No primary group defined.');
}
}
else{
alert('You are not a member of any groups.');
}
}
}
But now I am getting the message “you are not a member of any groups.” for all users. My u_primary field in the sys_user_grmember table is a type boolean as it should be. I am not sure what I am doing wrong. Thank you in advance for all your help.
The last alert message should probably be changed in your case to be identical to the first one, but I have this working in demo003 right now. You can check out the working solution there. I do think the group script would probably be better if it just picked the first group in the event that a user had more than one primary group. I’ll change that in the code above. You should also make sure that your users have read permissions to the ‘sys_user_grmember’ table.
Hi, I would like to implement this on a service catalog form.. with a reference lookup field pointing to sys_user basically gives users the choice of choosing themselves or running the lookup to pick someone else.. how would I get to the dictionary to set the ref_contributions=add_me attribute ? thanks
I wish it were that simple. Unfortunately, ServiceNow doesn’t support reference attributes or macros for variables. You can accomplish the same thing with client scripts though. I’ve added an example script above showing how it can be done.
That’s fantastic, thanks so much for the quick response.
Hey Mark this is great thank you. But i have one question for some reason i can not get this icon to show on the Group List or Watch List is there a limitation of what type of field a ref_contributions can be shown on?
Thanks
They should be fine to add to the watch list fields. It will only show up next to the reference field portion though.
Mark thanks for the quick response. I was able to use your “Adding a UI Macro to a Non-reference Field” to do what I needed to do.
Thanks again!!
Does this functionality still work with Calgary, Berlin or Eureka?
Yes, it is fully-compatible with all ServiceNow releases.
thanks for post
– i have tried the exact code for ‘add_me’ while checking Assignment group in the Dublin version but var myGroups = ‘$[jvar_groups]’; is returning null
– also tried var myGroups = gs.getUser().getMyGroups(); but this also fails, probably for reasons you mentioned in the original post.
Could this be relying on another setting or configuration?
Although this doesn’t break with Fuji, the image used doesn’t fit the Fuji design. I’ve updated the code to use a ‘Fuji Icon’ instead of the old school image.
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<j:set var="jvar_n" value="add_me_${ref}"/>
<span id="${jvar_n}" onclick="addMe('${ref}')" title="" style="margin-right: 5px;" alt="Add me" tabindex="0" class="btn btn-default icon-user-add">
<span class="sr-only">Add me</span>
</span>
<g2:evaluate var="jvar_groups" expression="gs.getUser().getMyGroups()" />
<script>
function addMe(reference) {
//Hide any field messages
g_form.hideFieldMsg('assigned_to', true);
//Check to see if the user is a member of selected group
var aGrp = g_form.getValue('assignment_group');
var myGroups = '$[jvar_groups]';
if(aGrp $[AMP]$[AMP] myGroups.indexOf(aGrp) > -1){
//Get the user reference field and populate the current user
var s = reference.split('.');
var referenceField = s[1];
g_form.setValue(referenceField, '$[gs.getUserID()]');
}
else{
//Display a field error message
g_form.showFieldMsg('assigned_to','You are not a member of the current assignment group. Please select one of your groups and try again.','error');
}
}
</script>
</j:jelly>
Looks good. Thanks! One minor issue is that after clicking the Add Me button, the form is not considered as modified and I can go to other record without any warning prompt.
Brandon,
Do you have code for the group icon?
Here is the code for the Add_my_group with the Fuji icon
Add my group
function addMyGroup(reference) {
//Get the group reference field and populate the first group queried
var s = reference.split(‘.’);
var referenceField = s[1];
var grpRec = new GlideRecord(‘sys_user_grmember’);
grpRec.addQuery(‘user’, ‘$[gs.getUserID()]’);
//Uncomment the following line if using a ‘Primary’ boolean field on the ‘sys_user_grmember’ table
//grpRec.addQuery(‘u_primary’, true);
grpRec.query(groupCallback);
//After the server returns the query recordset, continue here
function groupCallback(grpRec){
//Hide any previous field messages
try{
g_form.hideFieldMsg(referenceField, true);
}catch(e){}
//Check to see if the user is a member of a single group
if(grpRec.next()){
//Populate the first group found
g_form.setValue(referenceField, grpRec.group);
}
else{
g_form.showFieldMsg(referenceField,’You are not a member of any groups or have no primary group defined.’,’error’);
}
}
}
The variable code doesn’t work on RITM and Task level as the id changes for the input box on a per RITM and Task basis. Ideas?
Mark,
I am trying this in Eureka – I have added the UI Macro – added the attribute as an override on the assigned to field on the incident table. However the image or functionality seems to be working. Am I missing something? I even tried changing the image i was referencing to see if it was not finding the image.
A follow on question. Would this work on a read only field/ For instance we have a self-service portal that shows the watch_list field so the user can see who else is receiving updates. However we have a request to enable the add_me button for that field so that users can only add themselves to the watch_list not remove anything from the watch list. Any help is greatly appreciated.
Kevin
The Pre-fuji version of the script above should work just fine for Eureka instances so just make sure you’re using that. I’ve tested it successfully on Eureka ServiceNow versions so I know it works there.
As for its ability to work on a read only field, it will work there just fine. In the case of the Watch list, that field already has this macro capability built in so you’d want to use whatever built-in behavior ServiceNow has. Mine isn’t designed to work with watch list fields for that reason, but you could always try it and see what you get.
If others are searching for the list of icons available I found two pages that may prove helpful:
https://marcoceppi.github.io/bootstrap-glyphicons/ – the visual list
https://community.servicenow.com/message/1067279#1067279 – the text list of icons
Enjoy!
Troy,
Do you know how to get this to work on the service catalog within the service portal?
Hi Mark, thanks for this post.
I have used this in assigned_to field to override in marketing request table and it is working fine with the group validation, the same attribute when i have overrided in marketing task table the validation doesn’t work and the assigned to poppulated with current user even though he is not the member of the group.
Can you please help on what could possibly be wrong. Its the same macro i am using.
just to add to that. it is not going inside the addme function as i have put an alert
Can this work on the Service Portal for the variables? The way we have it set up doesn’t work and before I try I wanted to see if it was even a possibility. Thanks.
Jelly scripts are not working in service portal, as a workaround you can create a widget that will do the same function.
<div id ="addme" ng-init="append()">
<button ng-click = "setVal()" type="button" class="btn btn-default" aria-label="Add me">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> Add me
</button>
</div>
Client Script:
function($scope) {
/* widget controller */
var c = this;
$scope.setVal = function(){
$scope.page.g_form.setValue('requested_for', c.data.userid);
}
$scope.append = function(){
jQuery("#addme").appendTo("#INSERTSYSIDOFREFERENCEFIELDHERE");
}
}
Server Script:
(function() {
/* populate the 'data' object */
/* e.g., data.table = $sp.getValue('table'); */
data.userid = gs.getUserID();
})();
You can then reference this in widget field of a macro type variable.
Mark,
I followed your above steps for adding the macro to the Assigned to Field but I don’t get the icon. I tried it in my developer instance (Jakarta) and it worked just fine but in my org’s instance (Helsinki) the macro doesn’t show next to the Assigned to field.
Any ideas why this might be?
Hey. I have used this to create button on a catalog item which works perfectly, apart from having to use a string field which has to show, but it doesn’t work on the portal. Any ideas:
function onLoad() {
//The variable name to put the icon next to
g_form.setReadOnly(‘u_ca’, true);
var varName = ‘u_ca’;
try{
//Add the icon decoration to the reference field
var varEl = g_form.getControl(varName).id;
$(varEl).insert({
after: ‘‘
});
//Add the ‘onclick’ event
$(‘icon-search’).observe(‘click’, checkAvailability);
}catch(e){}
function checkAvailability(){
//…the rest of my function code this button triggers
}
}
}
I’d guess it’s something to do with ‘sn-tooltip-basic’???