Replicate Conditions field type for Service Portal variables
For table fields, ServiceNow provides a very useful Conditions field type which essentially adds a condition builder to a form and stores the corresponding encoded query as its value. However, there is no OOTB equivalent Conditions variable type for record producer/catalog item variables. In this article, I will demonstrate how to replicate the Conditions field type for Service Portal variables (I will be configuring a record producer, but the same can be applied to catalog items as well).
1. Create record producer (RP) which will display the Conditions variable, include detailed instructions in the RP's Description to reduce potential end-user confusion:
2. Navigate to the OOTB widget: SN Desktop Filter, and click Clone Widget (this will automatically add the necessary SN Filter dependency to your new widget):
3. Rename your newly cloned widget accordingly, for example I named mine Location Manager Query Builder.
4. Add a new variable to your RP with Type = Custom with Label, and set the variable's Widget = your newly cloned widget from step 3:
5. Add a new variable to your RP with Type = Multi Line Text and Read only = true, this is where we will store the encoded query generated from your new Query Builder widget:
6. Update the Server script of your new Query Builder widget to set data.table and data.initialQuery according to your requirements (in my example I am querying the cmn_location table and I have an initial query of Country is USA):
(function() {
/* populate the 'data' object */
/* e.g., data.table = $sp.getValue('table'); */
data.table = 'cmn_location';
data.initialQuery = 'country=USA';
})();
7. Optional: If you are providing an initial query in your Query Builder widget, be sure to set the default value of your Multi Line Text variable to match:
8. Update the Client controller of your new Query Builder widget to set c.config.closeFilter = false (removes the X button from the widget since it doesn't work in this context), and add an event listener to update your Multi Line Text variable with the encoded query value of the Query Builder when user clicks Run:
function($scope) {
/* widget controller */
var c = this;
c.config = {
outputType: "encoded_query",
closeFilter: false, //remove X button since it doesn't work in this context
encodedQuery: massageEncodedQuery(c.data.initialQuery),
manageFiltersLink: "?id=lf&table=sys_filter"
};
//add event listener to update Multi Line Text variable with the encoded query value of the Query Builder when user clicks Run
$scope.$on("snfilter:update_query", function(e, query) {
$scope.page.g_form.setValue('encoded_query', massageEncodedQuery(query));
});
function massageEncodedQuery(encodedQuery) {
return (encodedQuery) ? encodedQuery.replace(/CONTAINS/g, "LIKE").replace(/DOES NOT CONTAIN/g, "NOT LIKE") : encodedQuery;
}
}
9. At this point, the basic Conditions field type functionality is in place for the RP from Service Portal. The end-user can build a query with the familiar condition builder UI, and the resulting encoded query can be accessed from the Multi Line Text variable to perform whatever operations are needed after submission:
All steps that follow are to further enhance the end-user's experience:
10. It may be useful for the end-user to validate which records are returned by their query before submitting. To allow them to do so, begin by adding a new variable to your RP with Type = HTML and Read only = true:
11. Create new client-callable script include to retrieve the number of records returned by the query:
var queryBuilderUtils = Class.create();
queryBuilderUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getMatchingCount: function(sysparm_encQuery) {
var encQuery = global.JSUtil.nil(sysparm_encQuery) ? '' + this.getParameter('sysparm_encQuery') : '' + sysparm_encQuery;
var recordCount = new GlideAggregate('cmn_location');
recordCount.addEncodedQuery(encQuery);
recordCount.addAggregate('COUNT');
recordCount.query();
return (recordCount.next() ? recordCount.getAggregate('COUNT') : 0);
},
type: 'queryBuilderUtils'
});
12. Add new onLoad catalog client script to RP for populating HTML variable from step 9 when form loads. Be sure to set UI Type = Mobile / Service Portal:
function onLoad() {
//Type appropriate comment here, and begin script below
var encQuery = g_form.getValue('encoded_query') ? g_form.getValue('encoded_query') : '';
var ga = new GlideAjax('global.queryBuilderUtils');
ga.addParam('sysparm_name', 'getMatchingCount');
ga.addParam('sysparm_encQuery', encQuery);
ga.getXMLAnswer(function(answer) {
var url = '<h4><a href="/cmn_location_list.do?sysparm_query=' + encQuery + '" target="_blank">' + answer + ' Locations found</a></h4>';
g_form.setValue('matching_locations', url);
});
}
13. Add new onChange catalog client script to RP for populating HTML variable from step 9 when the encoded_query variable changes. Again be sure to set UI Type = Mobile / Service Portal:
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
//Type appropriate comment here, and begin script below
var encQuery = newValue;
var ga = new GlideAjax('global.queryBuilderUtils');
ga.addParam('sysparm_name', 'getMatchingCount');
ga.addParam('sysparm_encQuery', encQuery);
ga.getXMLAnswer(function(answer) {
var url = '<h4><a href="/cmn_location_list.do?sysparm_query=' + encQuery + '" target="_blank">' + answer + ' Locations found</a></h4>';
g_form.setValue('matching_locations', url);
});
}
14. Now your end-user has a way to validate the records returned by their query via form-generated link:
15. It may be useful to not allow the end-user to Submit the RP if their query does not return any records. It may also be useful to require a "double-check" for the end-user to confirm before Submitting the RP. Both of these requirements can be accomplished by adding a new onSubmit catalog client script to your RP. Again be sure to set UI Type = Mobile / Service Portal:
function onSubmit() {
//Type appropriate comment here, and begin script below
if (g_scratchpad.isFormValid) {
return true;
}
var encQuery = g_form.getValue('encoded_query');
var ga = new GlideAjax('global.queryBuilderUtils');
ga.addParam('sysparm_name', 'getMatchingCount');
ga.addParam('sysparm_encQuery', encQuery);
ga.getXMLAnswer(setAnswer);
return false;
function setAnswer(answer) {
if (answer == '0') {
g_form.addErrorMessage('At least 1 ServiceNow Location must be returned by your query. Request not submitted.');
return false;
} else {
var popup = confirm(answer + ' Locations will be processed with xyz operations. Do you want to continue?');
if (!popup) {
return false;
} else {
g_scratchpad.isFormValid = true;
g_form.submit(g_form.getActionName());
}
}
}
}
I hope you will find this article helpful! Please let me know if there are any questions or feedback.
If this article helped you , then please bookmark it or mark it as helpful.
Regards,
Christopher Perry
https://www.servicenow.com/community/developer-articles/replicate-conditions-field-type-for-service-portal-variables/ta-p/2297385