- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-02-2020 03:28 PM
Hello,
I have a record producer where you choose a user (reference field on sys_user table) you want to offboard. I would like to make the record producer more robust by alerting the submitter if the chosen user currently has a role and consequently prompting a follow up field for the submitter to select the user's replacement.
For the prompt(Catalog Client Script), I have the following script...
var usrRole = new GlideRecord('sys_user_has_role');
usrRole.addQuery('user', opened_for);
usrRole.addQuery('active', true);
usrRole.query();
if(usrRole == '') {
return;
} else {
g_form.showFieldMsg('opened_for', 'User has roles', 'error');
}
I am getting the prompt, however the problem is that it is appearing for users that do NOT have a role either. Can you suggest how I can edit this script so that it only applies to users that have a record in the sys_user_has_role table?
Secondly, I would like my follow up field for a replacement user to appear based on the same logic. For the Catalog UI Policy I have the following script...
function onCondition() {
var usrRole = current.variables.opened_for.hasRoles();
if(usrRole == 'true') {
return;
}
}
however this script is causing an Javascript error on the record producer. Can you provide some suggestions on these problems?
Thank you and be safe everyone.
Solved! Go to Solution.
- Labels:
-
Service Catalog
-
Service Portal
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-05-2020 04:12 PM
There's a bit of a logic error in your script. You perform a query but you don't actually look at the results. Kinda like getting a letter without looking inside. Changing your logic to:
//check to see if there are any roles returned for that user
if (usrRole.next()) {
g_form.showFieldMsg('opened_for', 'User has roles', 'error');
} else {
return;
}
...should fix it. HOWEVER, as Vikram mentioned, we shouldn't be using GlideRecord queries on the client-side. That is where AJAX calls come in.
To get what you want, you would need to either add a function to an existing custom Script Include, or create a new one:
Name: u_CatalogAjaxUtils
Client callable: checked
Script:
var u_CatalogAjaxUtils = Class.create();
u_CatalogAjaxUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
doesUserHaveARole: function() {
var result = false;
var userId = this.getParameter("sysparm_id");
if (userId == "") {
return false;
}
var count = 0;
//using GlideAggregate is more efficient
var ga = new GlideAggregate("sys_user_has_role");
ga.addAggregate("COUNT", "user");
//you'll probably want to exclude snc_internal and snc_external from your checks
ga.addEncodedQuery("role.name!=snc_internal^role.name!=snc_external^user=" + userId);
ga.query();
if (ga.next()){
count = ga.getAggregate("COUNT", "user");
}
if (count > 0) {
result = true;
}
return result;
},
type: 'u_CatalogAjaxUtils'
});
Then you call the Script Include from an onChange Catalog Client Script (on the opened_for variable):
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading) {
return;
}
//clear any previous messages
g_form.hideFieldMsg("opened_for", true);
//clear the Replacement field
g_form.setValue("replacement", "");
if (newValue == "") {
u_hideReplacementField();
return;
}
var ga = new GlideAjax("u_CatalogAjaxUtils");
ga.addParam("sysparm_name", "doesUserHaveARole");
ga.addParam("sysparm_id", newValue);
ga.getXMLAnswer(u_showOrHideReplacementField);
//callback function to process the response returned from the server
function u_showOrHideReplacementField(response) {
if (response == "true") {
//add a message
g_form.showFieldMsg("opened_for", "Please select a replacement", "info");
//show the Replacement field
g_form.setMandatory("replacement", true);
g_form.setDisplay("replacement", true);
} else {
//hide the Replacement field
u_hideReplacementField();
}
}
function u_hideReplacementField() {
//clear then hide the Replacement field
g_form.setValue("replacement", "");
g_form.setMandatory("replacement", false);
g_form.setDisplay("replacement", false);
}
}
So you end up with something like this when the selected user has a role:
...and this when the user does not have a role:
Adding a UI Policy to initially hide the Replacement field should finish things off for you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-02-2020 03:38 PM
Hi chrisds,
As a best practice it is not advised to use glide query in client script, instead create a GlideAjax that calls script include where you perform your validations and return value. You can reuse the same code in UI policy
Thank you,
Vikram
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-05-2020 04:12 PM
There's a bit of a logic error in your script. You perform a query but you don't actually look at the results. Kinda like getting a letter without looking inside. Changing your logic to:
//check to see if there are any roles returned for that user
if (usrRole.next()) {
g_form.showFieldMsg('opened_for', 'User has roles', 'error');
} else {
return;
}
...should fix it. HOWEVER, as Vikram mentioned, we shouldn't be using GlideRecord queries on the client-side. That is where AJAX calls come in.
To get what you want, you would need to either add a function to an existing custom Script Include, or create a new one:
Name: u_CatalogAjaxUtils
Client callable: checked
Script:
var u_CatalogAjaxUtils = Class.create();
u_CatalogAjaxUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
doesUserHaveARole: function() {
var result = false;
var userId = this.getParameter("sysparm_id");
if (userId == "") {
return false;
}
var count = 0;
//using GlideAggregate is more efficient
var ga = new GlideAggregate("sys_user_has_role");
ga.addAggregate("COUNT", "user");
//you'll probably want to exclude snc_internal and snc_external from your checks
ga.addEncodedQuery("role.name!=snc_internal^role.name!=snc_external^user=" + userId);
ga.query();
if (ga.next()){
count = ga.getAggregate("COUNT", "user");
}
if (count > 0) {
result = true;
}
return result;
},
type: 'u_CatalogAjaxUtils'
});
Then you call the Script Include from an onChange Catalog Client Script (on the opened_for variable):
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading) {
return;
}
//clear any previous messages
g_form.hideFieldMsg("opened_for", true);
//clear the Replacement field
g_form.setValue("replacement", "");
if (newValue == "") {
u_hideReplacementField();
return;
}
var ga = new GlideAjax("u_CatalogAjaxUtils");
ga.addParam("sysparm_name", "doesUserHaveARole");
ga.addParam("sysparm_id", newValue);
ga.getXMLAnswer(u_showOrHideReplacementField);
//callback function to process the response returned from the server
function u_showOrHideReplacementField(response) {
if (response == "true") {
//add a message
g_form.showFieldMsg("opened_for", "Please select a replacement", "info");
//show the Replacement field
g_form.setMandatory("replacement", true);
g_form.setDisplay("replacement", true);
} else {
//hide the Replacement field
u_hideReplacementField();
}
}
function u_hideReplacementField() {
//clear then hide the Replacement field
g_form.setValue("replacement", "");
g_form.setMandatory("replacement", false);
g_form.setDisplay("replacement", false);
}
}
So you end up with something like this when the selected user has a role:
...and this when the user does not have a role:
Adding a UI Policy to initially hide the Replacement field should finish things off for you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-06-2020 11:28 AM
Thanks a ton Jim. I have limited knowledge on GlideAjax and have been using GlideRecord. This use case has served as a good introduction to understanding Ajax. Much appreciated sir!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-06-2020 07:02 PM
You are very welcome.
Technically it will work in the "regular" UI, but the use of GlideRecord in the Service Portal will not. Your use case may not include the Service Portal right now but it's better using GlideAjax because if you want to use the Portal in the future, your work is already down, otherwise everything needs to be re-written. And it does give a better user experience by not locking up the page while the data is retrieved