- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-19-2023 05:48 PM
Hi everyone,
I've got a form that requires approval from specific users in certain states. If the issue is in state X and substate Y, and the user = approver1, they should see Approve/Reject/Cancel buttons. Each time an approver approves or rejects the issue, the state/substate will change, and the visibility of the buttons should change accordingly. The Approve/Reject/Cancel buttons have conditions that evaluate the status, substate and user to determine visibility.
In the backend, everything updates correctly. However, from the user's perspective, the form updates, but the buttons remain visible. If I refresh the page manually, everything displays as expected.
Theoretically, we try to refresh the page after doing the action using the following code:
current.update();//update the record
action.setRedirectURL(current);//Refresh the page
I was expecting this to refresh the page, recheck the UI Action's condition, and hide the buttons, but it is not achieving this.
Can anyone help with this? I could tell the users to just wait and refresh the page, but I'm hoping to make it smooth and dodge the complaints entirely.
Relevant questions:
1 - When are UI Action conditions evaluated?
2 - Can I force UI Action conditions to be re-evaluated?
3 - Are there ways to change the visibility of the buttons besides the UI action's condition?
I can provide examples if required.
Thanks!
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-20-2023 06:06 PM
Your script looks good to me!
There is a method in ServiceNow, "gs.sleep(microseconds)" , but it is not a recommended to use in the scripts
Also you can check this link
Can you try one thing, instead of calling the script include paste the code in UI action itself and try again
function serverMoveApprovalState()
{
//Driving the Approval Flow Through UI Action For Approve
var rec = new GlideRecord('sysapproval_approver');
rec.addQuery('state','requested');
rec.addQuery('approver',gs.getUserID());
rec.addQuery('sysapproval', current.sys_id).addOrCondition('document_id', current.sys_id);
rec.query();
if(rec.next()){
rec.state = 'approved';
rec.update();
}
if(current.state=='0' && current.u_substate=='55' && current.u_validator=='')
{
current.u_validator=gs.getUserID();
}
current.update();
action.setRedirectURL(current);
}
If my answer solved your issue, please mark my answer as ✅ Correct & 👍Helpful based on the Impact.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-19-2023 06:09 PM
lets just say, your UI action condition is mentioned below:
current.state =3; //lets say 3 is "in progress" state
Now here is the answer of your question:
1 - When are UI Action conditions evaluated? Every time form gets loaded, condition would be evaluated first and accordingly UI action hide or show
2 - Can I force UI Action conditions to be re-evaluated? You don't need to do that, it will evaluated during form load
3 - Are there ways to change the visibility of the buttons besides the UI action's condition? Yes
here are the ways:
1) if your condition is specific to single field let's say state you can mention current.state = 1/2/3 according to your needs or it would also be role specific gs.hasRole('itil');
2) if your condition is having complex logic to check, you can write script include and return true or false from the script and accordingly you can check in condition as
new ScriptIncludeName().functionName() == "true"
If my answer solved your issue, please mark my answer as ✅ Correct & 👍Helpful based on the Impact.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-19-2023 07:43 PM
Hey Prince, thanks for your reply.
The conditions for the buttons do as you suggest, calling a script include which does the complex logic to determine whether or not the buttons show. It sounds like I need to find a way to force a form load so that it will actually affect the form the user is looking at.
The condition function returns the correct answer, but I can verify that the condition function is not being evaluated after the button is pressed. From what I can find online, action.setRedirectURL() or window.location.refresh() are usually the way to do this, but when I tried these solutions, the user was taken away from the form after pressing the button.
I guess my most important question right now is: How do I force a form load from a UI Action?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-19-2023 09:07 PM
Yes correct for server side script use "action.setRedirectURL(current)" and for client side "window.location.reload()" for loading the form and came back to same page.
Could you please share your script behind UI action, it seems to be your code has broken somewhere in between and it doesn't reach to the action.setRedirectURL(for loading) line.
If my answer solved your issue, please mark my answer as ✅ Correct & 👍Helpful based on the Impact.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-20-2023 12:28 PM
Here's the code for the UI action:
function stateApproval()
{
if(g_form.getValue('comments')=='')
{
g_form.setMandatory('comments',true);
g_form.addErrorMessage(getMessage("Please provide your approval comments before approving the issue."));
return false;
}
gsftSubmit(null, g_form.getFormElement(), 'issue_appove');
}
if (typeof window == 'undefined')
serverMoveApprovalState();
function serverMoveApprovalState()
{
new sn_grc.WorkflowUtilities().setApprovalState(current);
if(current.state=='0' && current.u_substate=='55' && current.u_validator=='')
{
current.u_validator=gs.getUserID();
}
current.update();
action.setRedirectURL(current);
}
It checks for a comment, and if it does, calls gsftSubmit, which kicks off the approval process.
setApprovalState() looks like this:
setApprovalState:function(current)
{
//Driving the Approval Flow Through UI Action For Approve
var rec = new GlideRecord('sysapproval_approver');
rec.addQuery('state','requested');
rec.addQuery('approver',gs.getUserID());
rec.addQuery('sysapproval', current.sys_id).addOrCondition('document_id', current.sys_id);
rec.query();
if(rec.next()){
rec.state = 'approved';
rec.update();
}
},
I can tell that this code is running, all the way to the end (it hits the breakpoint on action.setRedirectURL and produces logs if I put them in). It actually works like I want it to if we sit on the breakpoint for a second. It looks to me like it's kicking off the approval process, then refreshing the page, but the approval process isn't finished so we get the wrong buttons displayed because the record status hasn't updated yet.
Is there a way to delay the refresh or wait for approval process to finish?
Thanks!
~Josh