Custom Epics
The goal for this guide is to show an example of how custom epics are created and used in the UI Framework. This guide shows an example of a modal that uses an epic. Epics are powerful and can do many things, and this is one example of the usage of an epic.
For information on Epics, go to redux observable under 2.1 Epics.

Create a custom epic

This guide provides an example epic. For this guide, the epic:
  • opens a modal
  • updates the header of the modal.
In Custom reducers and actions, we build on top of this guide and use an epic to delete the object.
In order to open a modal, we add a trash icon to each row of the table. In order to update the modal's header. we retrieve the name of the object that is populated in the table.
An example image of the modal is provided:

Step 1 - Create the modal

Notice that the header's text does not matter because we update the header text in the custom epic.
exampleUI.customHeaderModal.json
{
"type": "UiSdlConnected<UiSdlModal>",
"component": {
"size":"SMALL",
"header": {
"text": "doesntmatter_confirmationHeader"
},
"modalType": {
"type": "UiSdlTwoButtonModal",
"primaryButtonLabel": "Delete",
"primaryButtonStyle": "danger",
"secondaryButtonLabel": "Cancel",
"secondaryButtonStyle": "danger-secondary"
}
}
}

Step 2 - Add the table

The table provides us with the data that is used to populate the header of the modal. In our case, the modal's header is populated with the data's name.
{
"type": "UiSdlConnected<UiSdlDataGrid>",
"component": {
"paginationConfig": {
"pageSize": 5,
"pagination": true
},
"reorderableColumns": false,
"filterBar": false,
"dataSpec": {
"dataType": {
"typeName": "SDLDemoMachine"
},
"columnFields": [
{
"fieldName": "name",
"label": "SDLDemoMachine.name",
"searchable": true
},
{
"fieldName": "category",
"label": "SDLDemoMachine.category",
"searchable": true
},
{
"fieldName": "location.id",
"label": "SDLDemoMachine.location"
},
{
"fieldName": "statusLabel",
"label": "SDLDemoMachine.status"
}
]
},
"rowActions": [
{
"type":"UiSdlViewSDLGridRowAction",
"name":"Delete Example Modal",
"actionSuffix":"DELETE_CUSTOM",
"iconSuffix":"trash"
}
]
},
"effectTriggers": [
{
"trigger":"exampleUI.customTableTypesBasic.ROW_ACTION_CLICK_DELETE_CUSTOM",
"effectType": "UiSdlEpicDeleteExample",
"payload": {
"modal": "exampleUI.customHeaderModal"
},
"payloadStrategy":"MERGE"
}
]
}
Notice the rowAction and effectTriggers.
The ROW_ACTION_CLICK is an internal action that is sent off once the user clicks on the icon that the iconSuffix refers to. When the user clicks on the icon, the epic is triggered. Inside the effectTriggers, the trigger key has the ROW_ACTION_CLICK_DELETE_CUSTOM appended to the end of the current file name. This indicates that the action ROW_ACTION_CLICK_DELETE_CUSTOM triggers the desired epic. The desired epic is referenced in the effectType.
For more available icons for iconSuffix or information, run in the static console: c3ShowType(UiSdlAction).

Step 3 - Create the custom epic

The action that we set up triggers an epic. The following code block shows an example of a custom epic:
UiSdlEpicDeleteExample.c3typ
UiSdlEpicDeleteExample.ts
/*
* UiSdlEpicDeleteExample.c3typ
* Custom epic that will update the header of the modal.
*/
@typeScript
type UiSdlEpicDeleteExample extends UiSdlEpic {
// Override the epic method
@typeScript(env='client')
epic: ~
}
import { concat,of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
// Import the methods needed from the UiSdl component
import { updateModalHeaderAction } from '@c3/ui/UiSdlModalBody'
import { openCloseModalAction } from '@c3/ui/UiSdlModal'
////Where we write to the storeRowRecord the event ID
//import { storeRowRecordAction } from '@c3/ui/UiSdlApplicationStateEUI'
// Overrides the epic method
export function epic(actionStream, _stateStream) {
return actionStream.pipe(
mergeMap(function (action) {
const componentId = action.payload.componentId;
//meter event id to store in application state
const eventId = action.payload.obj.id;
//event id to store in application state
const eventName = action.payload.obj.name;
//id of the modal to update and open
const modalToOpen = action.payload.modal;
return concat(
of(updateModalHeaderAction(modalToOpen ,createHeaderText(eventName))),
of(openCloseModalAction(modalToOpen , true)),
//of(storeRowRecordAction(componentId, eventId))
);
}
)
)}
function createHeaderText (entityId: any) {
return "Are you sure you want to delete " + entityId + "?";
}
This epic does not write to the application state or delete the event.
At this point, we created a custom epic that:
  • Opens the modal
  • Updates the modal's header
In Custom Reducers, we create custom reducers that the epic calls in order to write into the application state. This allows future epics to grab the correct data from the application state. This is useful for many instances, one example is deleting an event. We show how to do this in custom reducers.

Troubleshoot Epics in Developer Tools

  1. 1.
    Open Developer Tools>Sources to find source code for the custom epic.
  2. 2.
    Search for a custom epic by name using Command + P on a Mac or Control + P on Windows/Linux.
    • If you do not find the custom epic, check to see if you connected the custom epic to the component correctly.
  3. 3.
    Set a breakpoint in the code and trigger the custom epic.
  4. 4.
    Hover over variables to view their values after the breakpoint is hit.