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

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>

 <j2:if test="${jvar_caller_available &amp;&amp; !empty(jvar_caller_email)}">
		
        <!-- 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>

I'm not much into Jelly, however I tried something like this, its not working.

How can we achieve this.

Unfortunately, my pdi is offline (it won't wake up) and I can't test this. But I would guess that it is due to the confusion between jelly phase 1 (p1) and jelly phase 2 (p2). The notation ${} is used for the p1 and $[] for p2. I built my example on p2 and so you should also use $[].

According to the ServiceNow docs the rest of the code should actually fit -> source.


Flying blind, I would rewrite the whole thing like this (as written, I couldn't test it, unfortunately):

<j2:if test="$[jvar_caller_available &amp;&amp; !empty(jvar_caller_email)]">		
        <!-- 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>