Modal components
Introduction
Modal components are Angular components of various kinds that are displayed in a modal (pop-up) window. Some of them have a fixed layout in terms of fields that are rendered, while others can be completely custom.
They are triggered programmatically and the triggering operation can be in any code that runs client side - and therefore any client script. They are most often found in the client scripts of Table Operations or Workflow Transitions.
Use case examples/when modal or pop-up window is used:
To show a configurable set of fields that can be populated and submitted to either create/update related record(s). Please refer to: Modal components | Component Modals
To show a catalog item. Please refer to: Modal components | Question Modals
To show Change’s risk assessment question. Please refer to: Risk Assessment
Component Modals
Component Modal API
This type of modal lets you have full control on what is displayed on the modal plus any automation you need it to do such as automatically updating a record. The primary method to invoke a component modal is Navigate.showComponentModal()
which in older usage was known as Navigate.componentModal()
. You can invoke it in client side functions like Table Operation or Workflow Transition.
It takes a single options object with the following shape:
{
modalPage?: string,
modalComponent?: string,
modalComponentParams?: any,
modalOptions?: {
cssClass?: string,
showCloseIcon?: boolean,
closeOnEscape?: boolean,
showCloseButton?: boolean,
title?: string,
closeCallback?: (closeReason: 'button' | 'icon' | 'escape') => void,
modalButtons?: {
isFlat?: boolean,
buttonModel: {
iconPosition?: 'Left' | 'Right;
iconCss?: string;
disabled?: boolean;
isPrimary?: boolean;
cssClass?: string;
content?: string;
isToggle?: boolean;
locale?: string;
enableHtmlSanitizer?: boolean;
created?: EmitType<Event>;
},
type?: 'Button' | 'Submit' | 'Reset',
click?: (event: any) => void,
}[],
referenceQualifierContext?: {
syntheticRelatedRecordId: string,
syntheticRelatedRecordTableName?: string,
syntheticRelatedRecordRelationName?: string
},
}
}
Component Modal Options
Option | Meaning |
---|---|
modalPage | ID or key of a Portal Page |
modalComponent | ID or key of a Portal Component or Modal Component |
modalComponentParams | Parameters of the Portal or Modal Component. These have to match the parameters defined in the component form |
cssClass | Extra CSS class on the underlying modal |
showCloseIcon | Show the X in the corner |
closeOnEscape | Close the modal when ESC is pressed |
showCloseButton | Show a Close button at the bottom of the modal. This is an alternative to modalButtons |
title | Title to display at the top of the modal |
closeCallback | Function called when the modal is closed |
modalButtons | Buttons to display at the bottom of the modal |
modalButtons.isFlat | Style of the button |
modalButtons.buttonModel | Button specification with icons, etc |
modalButtons.buttonModel.content | Label of the button |
modalButtons.type | Type of the button |
modalButtons.click | Function called when the button is clicked |
referenceQualifierContext | Support for reference qualifiers in modals |
Component Modal Usage Examples
In an Action of a Table Operation
Navigate.showComponentModal({
modalComponent: '845d311f516111ecb88a0270361181df',
modalComponentParams: { _current: id, _table: tableName },
modalOptions: {
showCloseIcon: false,
showCloseButton: false
}
});
In the Before of a Table Operation or Workflow Transition
A Promise is returned so that the table operation is blocked until the modal is closed. This avoids clicking the table operation button twice.
return new Promise((resolve, reject) => {
Navigate.showComponentModal({
modalComponent: 'e7139deb51ac11ecbcfaaecf14abe23e',
modalComponentParams: { _current: id, _table: tableName },
modalOptions: {
showCloseIcon: true,
modalButtons: [
{
'click': (props) => {
// Do action code here
resolve(true);
},
buttonModel: {
content: 'Submit',
isPrimary: true,
}
}
]
}
});
});
Configuring the modal
After you have created a Modal component record, to create and display a field onto a Modal:
Create the field on the Modal’s Component script using the examples provided on the respective field type, as shown on the Example column. E.g. below screenshot showing the creation of a String field, named “stringField” (but you can name it whatever you want). For list of available field types you can use, please refer to: Modal components | Available fields
Then, reference the field(s) on the Modal’s Template HTML script
You will reference the Modal’s Component “stringField” variable (or whatever you call the variable), like below (note line 11 on the screenshot):
<sb-knockout-field [field]="stringField"></sb-knockout-field>
Available fields
The following are the available field types you can configure on a Modal component and how you can create them. The examples show you how you can configure the field definition you need.
To note:
The field name that the
FieldService
functions return to, can be anything you want. However, ensure that whatever name you give a field, that it is used on the Modal’s Template script accordingly.The
onChange
function is what you can configure to do something when a field is updated by users, e.g. set a variable that can later be used for data processing/record update.
Field type | Examples |
---|---|
String (single line text) | stringField: any = FieldService.createStringField(
'String field',
'String field',
{
onChange: (value: any) => {
this.data.stringValue = value;
},
mandatory: true
}
); |
Text area (multi line text) | textAreaField: any = FieldService.createTextAreaField(
'Text area field',
'Text area field',
{
onChange: (value: any) => {
this.data.textAreaValue = value;
}
}
); |
Choice (Dropdown) | Note: The dropdown choices are defined in the availableValues parameter. Every choice has ‘value’, ‘displayValue’ and ‘i18nKey’. For each choice, they are respectively, the actual choice value that can be used for scripting, the default label and the localised message key of the choice label. choiceField: any = FieldService.createChoiceField(
'Choice field',
'Choice field',
{
onChange: (value: any) => {
this.data.choiceValue = value;
},
mandatory: true,
availableValues: [
{ value: 'choice1', displayValue: 'Choice1', i18nKey: 'Choice1' },
{ value: 'choice2', displayValue: 'Choice2', i18nKey: 'Choice2' },
{ value: 'choice3', displayValue: 'Choice2', i18nKey: 'Choice3' }
]
}
); If you want to set a default value for the choice field
choiceField: any = FieldService.createChoiceField(
'Choice field',
'Choice field',
{
onChange: (value: any) => {
this.data.choiceValue = value;
},
mandatory: true,
availableValues: [
{ value: 'choice1', displayValue: 'Choice1', i18nKey: 'Choice1' },
{ value: 'choice2', displayValue: 'Choice2', i18nKey: 'Choice2' },
{ value: 'choice3', displayValue: 'Choice2', i18nKey: 'Choice3' }
],
data: {
defaultValue: { value: 'choice2', displayValue: 'Choice2', i18nKey: 'Choice2' },
defaultValueSource: 'script'
}
}
); |
HTML | htmlField: any = FieldService.createHtmlField(
'HTML field',
'HTML field',
{
onChange: (value: any) => {
this.data.htmlValue = value;
}
}
); |
Boolean (Yes/No) | booleanSwitchField: any = FieldService.createBooleanSwitchField(
'Boolean switch field',
'Boolean switch field',
{
onChange: (value: any) => {
this.data.booleanSwitchValue = value;
}
}
); |
Checkbox | checkboxField: any = FieldService.createBooleanCheckboxField(
'Checkbox field',
'Checkbox field',
{
onChange: (value: any) => {
this.data.checkboxValue = value;
}
}
); |
Acknowledgement | acknowledgementField: any = FieldService.createAcknowledgementField(
'Acknowledgement field',
'Acknowledgement field',
{
onChange: (value: any) => {
this.data.acknowledgementValue = value;
}
}
); |
Integer | integerField: any = FieldService.createIntegerField(
'Integer field',
'Integer field',
{
onChange: (value: any) => {
this.data.integerValue = value;
}
}
); |
Decimal | decimalField: any = FieldService.createDecimalField(
'Decimal field',
'Decimal field',
{
onChange: (value: any) => {
this.data.decimalValue = value;
}
}
); |
Date | dateField: any = FieldService.createDateField(
'Date field',
'Date field',
{
onChange: (value: any) => {
this.data.dateValue = value;
}
}
); |
Date and time | dateTimeField: any = FieldService.createDateTimeField(
'Date/time field',
'Date/time field',
{
onChange: (value: any) => {
this.data.dateTimeValue = value;
}
}
); |
Duration | durationField: any = FieldService.createDurationField(
'Duration field',
'Duration field',
{
onChange: (value: any) => {
this.data.durationValue = value;
}
}
); |
Reference | Note: “name” parameter must be the same as “referenceTable” parameter referenceField: any = FieldService.createReferenceField(
'User',
'Reference field',
'User',
{
onChange: (value: any) => {
this.data.referenceValue = value;
}
}
); |
Multi reference | Note: “name” parameter must be the same as “referenceTable” parameter multiReferenceField: any = FieldService.createMultiReferenceField(
'Location',
'Multi reference field',
'Location',
{
onChange: (value: any) => {
this.data.multiReferenceValue = value;
}
}
); |
Question Modals
Question Modal API
A question modal contains a Catalog Item or a Risk Assessment Item. The primary method to invoke a question modal on a client side script like UI Event, is Navigate.showQuestionModal()
It takes a single options object with the following shape:
{
questionItem?: string,
questionItemParams?: {
recordId?: string,
recordTable?: string,
sourceRec?: any,
sourceIsNewRecord?: boolean,
submittedEventOnly?: boolean
},
modalOptions?: modalOptions?: {
cssClass?: string,
showCloseIcon?: boolean,
closeOnEscape?: boolean,
showCloseButton?: boolean,
title?: string,
closeCallback?: any,
}
}
Question Modal Options
Option | Meaning |
---|---|
questionItem | ID or key of a Catalog Item or a Risk Assessment Item |
questionItemParams | Parameters of the Question Item |
questionItemParams.recordId | ID of the target record that is created by the question item in the modal |
questionItemParams.recordTable | Unused |
questionItemParams.sourceRec | JSON object containing the fields of the record |
questionItemParams.sourceIsNewRecord | True if sourceRec is a new record |
questionItemParams.submittedEventOnly |
|
cssClass | Extra CSS class on the underlying modal |
showCloseIcon | Show the X in the corner |
closeOnEscape | Close the modal when ESC is pressed |
title | Title to display at the top of the modal |
closeCallback | Function called when the modal is closed |
Question Modal Usage
To Show a Risk Assessment Item
This is the Before of a table operation. A Promise is returned so that the table operation is blocked until the modal is closed. This avoids clicking the table operation button twice.
// We need to find the risk assessment record we created last time we ran this so that we can find the answers.
let q = Table("RiskAssessmentAnswers").EQUAL("Record", id + ":" + tableName).query();
let recordId = q.hasNext() ? q.next().ID() : null;
return new Promise((resolve, reject) => {
// Context contains the id of the generated RiskAssessmentAnswers record
let closeCallback = (closeReason, context) => {
resolve(true);
};
let questionItemParams = {
recordId: recordId, // id of the generated RiskAssessmentAnswers if it exists
recordTable: null, // not used
sourceRec: {
TableClass: tableName, // tableName of the change record
id: id // id of the change record
},
sourceIsNewRecord: current.isNewRecord()
};
let modalOptions = {
showCloseIcon: true,
showCloseButton: false,
closeCallback: closeCallback,
title: "Risk assessment"
};
Navigate.showQuestionModal({
questionItem: 'RiskAssessment',
questionItemParams: questionItemParams,
modalOptions: modalOptions
});
});
Servicely Documentation