Getting displayed variables in service portal

robertyoung
Giga Contributor

We have long had a custom client script as part of a variable set that inspected the attributes of all of the options contained in: g_form.nameMap.

On submit this allowed us to construct a list of all of the field names that were visible at the time of submission. This list is important later in our business processes where we use it to decide which fields to send to one of our vendors over a web service call.

We've been using service portal for a while now and are currently in the process of moving all of our catalog items over. I need to re-create this "get visible variables" capability in portal but I can't figure out how the variables in portal relate to their counterparts attached to the catalog item. There is a GUID associated with the input on portal but it doesn't seem to match anything else I can think of.

I'm looking for anyone who has done anything similar or who has knowledge of how the variables are named (id) in portal to help me chip away at this.

1 ACCEPTED SOLUTION

ChrisBurks
Mega Sage

Hi Robert,



From the Service Portal side you could possibly embed a Service Portal widget into the catalog item and do something like this to capture all the necessary variables and their values:



Widget Client Controller Script:



function($scope, $rootScope) {


      /* widget controller */


      var c = this;


      $rootScope.$on('field.change', function(){


              c.variables = $scope.page.g_form.getFieldNames().filter(function(field){


                      return $scope.page.g_form.isVisible(field);


              }).map(function(field){


                      var obj = {};


                      obj.name = $scope.page.g_form.getLabel(field);


                      obj.value = $scope.page.g_form.getValue(field);


                      obj.display_value = $scope.page.g_form.getDisplayValue(field);


                      obj.isVisible = $scope.page.g_form.isVisible(field);


                      return obj;


              });


              console.log("Changed", c.variables)


      })


}



That script will search through and gather all the visible variables in the catalog item it's associate with when a field value changes. (input fields will trigger on blur and select fields will change after a selection). And then it's just console logging out the result. But you can have it do what's needed.


However, it will only get the values of the native side variables. If you have Service Portal side variables you can directly access them from the scope. If you have UI Macro variables using a UI macro or UI page of the sort then those would have to be handled on native side or duplicated Service Portal side.



Edit:



Thinking about this though I forgot to ask, Is it not working in the Service Portal or is the issue that you've added variables on the Service Portal side?



If it simply isn't working below are a couple of questions:


      What errors are you getting? (You might need to use "inspect element" to see the errors.


      Did you set the Client Script to run in both Desktop and Mobile? (Service Portal is considered mobile)


View solution in original post

8 REPLIES 8

ChrisBurks
Mega Sage

Hi Robert,



From the Service Portal side you could possibly embed a Service Portal widget into the catalog item and do something like this to capture all the necessary variables and their values:



Widget Client Controller Script:



function($scope, $rootScope) {


      /* widget controller */


      var c = this;


      $rootScope.$on('field.change', function(){


              c.variables = $scope.page.g_form.getFieldNames().filter(function(field){


                      return $scope.page.g_form.isVisible(field);


              }).map(function(field){


                      var obj = {};


                      obj.name = $scope.page.g_form.getLabel(field);


                      obj.value = $scope.page.g_form.getValue(field);


                      obj.display_value = $scope.page.g_form.getDisplayValue(field);


                      obj.isVisible = $scope.page.g_form.isVisible(field);


                      return obj;


              });


              console.log("Changed", c.variables)


      })


}



That script will search through and gather all the visible variables in the catalog item it's associate with when a field value changes. (input fields will trigger on blur and select fields will change after a selection). And then it's just console logging out the result. But you can have it do what's needed.


However, it will only get the values of the native side variables. If you have Service Portal side variables you can directly access them from the scope. If you have UI Macro variables using a UI macro or UI page of the sort then those would have to be handled on native side or duplicated Service Portal side.



Edit:



Thinking about this though I forgot to ask, Is it not working in the Service Portal or is the issue that you've added variables on the Service Portal side?



If it simply isn't working below are a couple of questions:


      What errors are you getting? (You might need to use "inspect element" to see the errors.


      Did you set the Client Script to run in both Desktop and Mobile? (Service Portal is considered mobile)


THANKS!!! I'll give that a shot. I never considered hooking into the change events on everything and just looking at all of the fields.



The error/issue is that that particular g_form property "g_form.nameMap" is undefined inside of the $scope.page context. Like it's just not exposed there. I may try getFieldNames() first in our existing script. Maybe I can get away with that. If not I'll implement your approach fully and see.



The actual error in our console specific "visibility inspector" doesn't come until we try to evaluate the length of the results of the nameMap call. That throws a null reference because the results of g_form.nameMap are undefined.



We'll be maintaining all of our services in both portal and the console. We've completely abandoned read-only HTML fields in favor of "MACRO" type fields configured with both a UI Macro and a Portal Widget. The framework seems to pick the correct flavor to display on the portal vs on the console which is great.



As far as handling widgets and/or macros, our old script didn't really deal with that either, fortunately the stuff we tend to put in UI Macros for services aren't the kinds of things we need to send to the vendor. We use them mostly for information specific to the person ordering the service.



I'm not sure what you mean by "Service Portal side variables" unless you just mean portal widgets added as Macro variable types.


So this is weird. In the console when I run this I get "g_form.getFieldNames is not a function" (When I say console in this context I mean the legacy "Normal" service now catalog item view, not sure what the correct jargon for it is if you don't work where I do)



console.log(g_form.getFieldNames());



I'm going to go ahead and implement your widget based solution. If that works we'll just keep both versions and move on for now


Hi Robert,



More than likely the .getFieldNames() is only available in Mobile view. In that case if you want to keep everything working on the Native/Legacy/Normal view of ServiceNow you can do this:



if (window === null)
  // Write your mobile compatible code here
  else
  // Write your desktop compatible code here



Unofficial Service Portal Documentation


or


Official Service Portal and client scripts Documentation



Where using the .getFieldNames would run if viewed in Portal (Mobile) and your original code when viewed in Native/Legacy/Normal view.