Hide UI Macro

Abdul Musavvir
Kilo Guru

Hi Everyone,

I have created a UI macro to open Teams chat. Need to hide this UI macro based if the field value is empty. I have written something like below, however its not working .

Can anyone suggest how I can acheive this.

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core"
xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<a class="btn-default;" id="${jvar_n}" onclick="invokeChat('${ref}');">
              <img src="teams.png" width="30"  title="Teams Chat" alt="${gs.getMessage('Click to open Teams chat')}" />
</a>
    <span onChange="onChange('${ref}')"></span>
<script>
    function onChange(element, original, changed, loading) {
var visibility = 'visible';
var sysID = g_form.getValue('caller_id');
if (!sysID)
visibility = 'hidden';


var e = gel('${jvar_n}');
e.style.visibility= visibility;
}
    
function invokeChat(reference) {

var prefix = 'https://teams.microsoft.com/l/chat/0/0?users=';
var firstname = g_form.getReference('caller_id').first_name;
var user = g_form.getReference('caller_id').email;
var subject = '&amp;amp;message=Hi ' + firstname + ', this is regarding your Incident ' + g_form.getValue('number') + ': ' + g_form.getValue('short_description');

var w = getTopWindow();
var url = prefix + user + subject;
w.open(url);
}
</script></j:jelly>

 

Thanks in Advance.

Abdul

1 ACCEPTED SOLUTION

Roman Haas
Giga Guru

OK here are some thoughts:

  • I would fetch the necessary data from the backend in an evaluate tag and not work with "getReference" on client side (saves server calls and gives a better user experience).
  • I also like to do everything possible on server side and only what is absolutely necessary on client side. These are security considerations, since the server side cannot be manipulated, but the client side can.

  • I tried to put (excessive) comments in my code so you can understand everything.

 

The disadvantage of this solution is that this UI macro does not react to changes when the caller_id field is emptied or filled (until it gets saved, then the ui reloads anyways). If this is desired the UI macro would have to be changed again and everything done in the client side and then from an on-change client script a corresponding function in the ui macro would have to be called for recalculation. It depends on your use case, generally the caller is set when the incident is created and does not change anymore.

 

The following code is my version of how I would solve it currently. There is not one way. If you have any questions I am at your disposal.

 

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false"
    xmlns:j="jelly:core"
    xmlns:g="glide"
    xmlns:j2="null"
    xmlns:g2="null">

    <!-- ********** Server Stuff ************************************************************************************** -->

    <!-- Check if the caller_id field is not empty and save it into a variable -->
    <j2:set var="jvar_caller_available" value="$[Boolean(!current.caller_id.nil())]" />


    <!-- Set the caller first name variable if the caller is available (using the variable jvar_caller_available) -->
    <g2:evaluate var="jvar_caller_first_name" jelly="true">
        var jvar_caller_first_name = '';
        if(jelly.jvar_caller_available){
            jvar_caller_first_name = current.caller_id.first_name.getDisplayValue();
        }
        jvar_caller_first_name;
    </g2:evaluate>

    <!-- Set the caller email variable if the caller is available (using the variable jvar_caller_available) -->
    <g2:evaluate var="jvar_caller_email" jelly="true">
        var jvar_caller_email = '';
        if(jelly.jvar_caller_available){
            jvar_caller_email = current.caller_id.email.getDisplayValue();
        }
        jvar_caller_email;
    </g2:evaluate>

    <!-- Set the teams url variable if the caller is available (using the variable jvar_caller_available) -->
    <g2:evaluate var="jvar_teams_url" jelly="true">
        var jvar_teams_url = '';
        if(jelly.jvar_caller_available){
            var prefix = 'https://teams.microsoft.com/l/chat/0/0?users=';
            var subject = '&amp;message=Hi ' + jelly.jvar_caller_first_name + ', this is regarding your Incident ' + current.number.getDisplayValue() + ': ' + current.short_description.getDisplayValue();

            jvar_teams_url = prefix + jelly.jvar_caller_email + subject;
        }
        jvar_teams_url;
    </g2:evaluate>
    <!-- ************************************************************************************************************** -->


    <!-- ********** Client Stuff ************************************************************************************** -->
    <!-- Check if the caller is available or not -->
    <j2:if test="$[jvar_caller_available]">
        <!-- Caller field is available, display the teams anchor button -->
        <a class="btn-default;" href="$[jvar_teams_url]" target="_blank">
            <img src="teams.png" width="30" title="Teams Chat" alt="${gs.getMessage('Click to open Teams chat')}" />
        </a>
    </j2:if>
    <j2:if test="$[!jvar_caller_available]">
        <!--Caller field empty, we just want to do nothing :)-->
    </j2:if>
    <!-- ************************************************************************************************************** -->

</j:jelly>

View solution in original post

8 REPLIES 8

Ankur Bawiskar
Tera Patron
Tera Patron

@Abdul Musavvir 

this link has the solution

Hide / Show UI Macro on Case Form based on field data

Regards
Ankur

Regards,
Ankur
✨ Certified Technical Architect  ||  ✨ 9x ServiceNow MVP  ||  ✨ ServiceNow Community Leader

@Abdul Musavvir 

Did you get a chance to check the link I shared yesterday?

Regards
Ankur

Regards,
Ankur
✨ Certified Technical Architect  ||  ✨ 9x ServiceNow MVP  ||  ✨ ServiceNow Community Leader

I did tried that, and I'm not able to make it.

I have written something like below

Jelly:

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core"
xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
	<style>
		.hide_hosted_asset_flag {
			visibility: hidden;
			position: absolute;
			left: -1000px;
		}
		.show_hosted_asset_flag {
			visibility: visible;
			background-position: 50% 7px;
		}
	</style>
	<g2:evaluate var="jvar_caller" jelly="true">
        var caller = '';
            caller = current.caller_id.getDisplayValue();
        if(caller != ''){
        caller="true";
		}
		caller;
    </g2:evaluate>
	<j:if test="${jvar_caller}">
<a class="btn-default;" id="${jvar_n}" onclick="invokeChat('${ref}');">
              <img src="teams.png" width="30"  title="Teams Chat" alt="${gs.getMessage('Click to open Teams chat')}" />
</a>
	</j:if>
<script>
function invokeChat(reference) {

var prefix = 'https://teams.microsoft.com/l/chat/0/0?users=';
var firstname = g_form.getReference('caller_id').first_name;
var user = g_form.getReference('caller_id').email;
var subject = '&amp;amp;message=Hi ' + firstname + ', this is regarding your Incident ' + g_form.getValue('number') + ': ' + g_form.getValue('short_description');

var w = getTopWindow();
var url = prefix + user + subject;
w.open(url);
}
</script></j:jelly>

Here if statement not working.

Client Script:

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
	
	if (!newValue) {
		// Hide the UI Macro
		var elementToShowOrHide = 'teams_chat';
		var myMacro = $(elementToShowOrHide);
		myMacro.style.visibility = "hidden";
		myMacro.style.position = "absolute";
		myMacro.style.left = "-1000px";
		return;
	}
	g_form.getReference('caller_id', showHideMacro);
}

function showHideMacro(caller_id) {
	
	// Get the macro
	var elementToShowOrHide = 'teams_chat';
	var myMacro = $(elementToShowOrHide);
	
	//Check for asset hosted status
	var email = caller_id.email;
	if(email != ''){
		// Show the macro
		myMacro.style.visibility = "visible";
		myMacro.style.position = "static";
	} else {
		// Hide the macro
		myMacro.style.visibility = "hidden";
		myMacro.style.position = "absolute";
		myMacro.style.left = "-1000px";
	}
}

I got below error

find_real_file.png

The error gives you a pretty good hint where the problem is 🙂

This line in your client scripts seems strange to me:

var myMacro = $(elementToShowOrHide);

 

I guess you wanted to get the JQuery object for this DOM object. I think you need to use $j in a client script to access JQuery. And you also need to make sure that the field "isolate_script" is set to "false" in order to access the DOM at all.

 

Try this line of code (unfortunately, I could not test it due to my PDI being offline):

var myMacro = $j(elementToShowOrHide);

 

Another small suggestion: Why do you save the string "teams_chat" in a variable? I would definitely do that if I would use it more than once. But in your code example you only use that string once, so why not just write it directly?

var myMacro = $j('teams_chat');

 

 

I like to make guard clauses to not run into errors:

var myMacro = $j('teams_chat');

if(!myMacro){ return; }

//do all the stuff you want to do if the script found the DOM object.