Agent Workspace is built on the great new Now Experience UI Framework. For those used to developing on the traditional ServiceNow interface, things have changed a bit! One of those things that’s changed is how you would create a modal dialog box, meaning you can say goodbye to GlideModal
! This article describes how you can develop a Now UI Experience Framework component, and surface it in Agent Workspace in a modal in a way that’s connected to the form context you’re launching it from.
Prerequisites
Part of the answer is already covered on the official ServiceNow Documentation site, on the page “render a now component in a modal“. However, it covers only what to do once you have created a component, but not how to create a component that can interact with a modal itself.
Something worth noting is that it mentions you need to create a record in the sys_aw_registered_scripting_modal
table, however the ACL’s applied to this table at least in the Orlando release of ServiceNow are set to only allow users with the maint
role to do so. So the first thing you’ll need to do is modify those ACL’s. There’s one for each action (create, read, write, delete) you’ll need to modify. You can simply just enable the Admin overrides checkbox on each of these ACL’s for a quick-fix to allow users with the admin
role to edit records in this table, or specifically modify the ACL’s the allow more granular permissions.
Deployment
Let’s first see what we need to do to get an already-created component from our local machine into an instance, and associate it with an Agent Workspace UI Action.
- From the directory of the component, use the
now-cli deploy
command to deploy it to your instance. - As an admin, create a new record in the
sys_aw_registered_scripting_modal
table.- Component: point this reference field to the component you deployed in step 1.
- API: a function name which you will use to launch this modal from a UI Action, for example
openMyModalNow
oropenUserFeedbackModal
. It can be anything you want, but it must be unique for the scope you’re creating this record in.
- Copy the value from the automatically populated Public API field. This will contain a concatenation separated by periods of
g_modal
+ the scope you’re in + the API name you chose in the previous step, for exampleg_modal.global.openCompModalTest()
. You can use this code in an Agent Workspace UI Action client script to open your modal. - Create a UI Action applied to the table you want to open the modal from. Set an action name, and ensure one of the “workspace” options is enabled (button or menu). This will determined whether your UI action appears as a main button at the top right of the Agent Workspace screen, or hidden within the menu at the top right of the screen.
- In the workspace client script, use code similar to the below:
function onClick(g_form) {
// Build the data you want to pass to your component here.
// Example:
var myOptions = [{
id: 'it',
label: 'IT Workflows'
},{
id: 'customer',
label: 'Customer Workflows'
},{
id: 'employee',
label: 'Employee Workflows'
}];
g_modal.global.openCompModalTest({
title: 'Please select a workflow!',
confirmTitle: "OK",
cancelTitle: "Cancel",
size: 'sm',
height: 'md',
params:{
options: myOptions,
selectedValue: myOptions[0].id
}
}).then(function (modalResult) {
// Code to handle the result of your modal here.
// Example:
g_form.setValue('my_field', modalResult.selectedValue);
});
}
Registered Scripting Modal Parameter
As you can see in the example above, the auto-generated functions you use to call your modal (e.g. g_modal.global.openCompModalTest()
) accept an object as a parameter, which has a number of properties you can define on it.
title
: the title of the modal dialog windowconfirmTitle
: the label of the “OK” buttoncancelTitle
: the label of the “Close” buttonsize
: from testing I believesm
,lg
,xl
, andfw
are accepted valuesheight
: a height (in pixels) for the modalparams
: the parameters to pass in to the inner component
The params
property is probably the most important one to highlight. It’s how you can pass context from your form (for example, the sysId of the record you’re on, or the value from a form field obtained by g_form.getValue()
) into your component. In the example above, I’ve hard-coded an array containing a list of items (ServiceNow workflows) all having both an id
, and a label
. The object supplied as params
gets passed into the component inside the modal as it’s properties.
You can also see the auto-generated function returns a promise, and the function passed into then()
that’s called when the promise is resolved will get a parameter passed into it. This parameter I’ve called modalResult
in my example, and contains the data passed back to the UI Script from the modal.
Creating the Component
Now we know we can pass values into the component through the params
property, and receive data from the component using the first parameter of the callback function that executes when the modal closes (modalResult
in my example). We can now look into using these params
inside a component, and broadcasting data out of the component into the callback function.
The component shown in the screenshot above is one I created called snc-component-modal-test
. It simply accepts as properties two things:
- options:
- selectedValue
It shows a dropdown list of the options supplied to it (options
), and accepts a default selected value (selectedValue
).
import { createCustomElement } from '@servicenow/ui-core';
import snabbdom from '@servicenow/ui-renderer-snabbdom';
import '@servicenow/now-dropdown';
import styles from './styles.scss';
const handleSelect = ({action, dispatch}) => {
dispatch('SN_SCRIPTED_MODAL#DATA_SET', {
selectedValue: properties.selectedValue
});
}
const view = ({properties}, dispatch) => {
dispatch('SN_SCRIPTED_MODAL#DATA_SET', {
selectedValue: properties.selectedValue
});
return (
<div>
<now-dropdown
items={properties.options}
size="md"
select="single"
selected-items={[properties.selectedValue]}
/>
</div>
);
};
createCustomElement('snc-component-modal-test', {
renderer: { type: snabbdom },
view,
styles,
actionHandlers: {
'NOW_DROPDOWN#SELECTED_ITEMS_SET': handleSelect
},
properties: {
options: {
default: [{
label: 'First Option',
id: 'one'
}, {
label: 'Option 2',
id: 'two'
}]
},
selectedValue: {
default: 'one'
}
}
});
Some notes to explain the above:
- I’m using the
now-dropdown
component so that I didn’t need to create a dropdown myself. You can install this using the commandnpm install @servicenow/now-dropdown
. Other standard components are documented on the official ServiceNow Developer website. - The
now-dropdown
component has the actionNOW_DROPDOWN#SELECTED_ITEMS_SET
, which gets called when the selected item(s) change. To respond to this action, I have thehandleSelect
function being called. - The component built into Agent Workspace to create modals has the
SN_SCRIPTED_MODAL#DATA_SET
action, which you can dispatch to update the data that will be passed back to your client script.- I’m dispatching this action to set the the
selectedValue
property.
- I’m dispatching this action to set the the
- In the UI Action’s client script, I’m using this data from the
selectedValue
property to update my form usingg_form
as per a normal client script within the callback function that gets executed when the modal is closed.
Once you’ve created your component, you can deploy it to your instance as per the steps in the previous section. If you’ve already deployed the component, you’ll need to use the --force
option to overwrite the existing component on the instance.
Conclusion
If you have any questions, or you’ve discovered some additional information about using Modals in Agent Workspace, please leave a comment below or reach out to me on twitter using my handle @dylanlindgren!