Page event
A page may contain one or more widgets, and commonly, for rich-UI applications, there will be a need for a widget to respond to application events automatically. For example, when end-users select a new book in the book list, they want to subscribe to a change in the book list widget and refresh data in the book detail widget. However, widgets in Casewhere are independent entities, so it's not a good practice to have them calling each other. Hence, Casewhere offers the page events feature to provide a central place to orchestrate the widget communication while keeping them decoupled.
There are two types of events: built-in events and custom events. Basically, all events will share the information below:
- Event name: For built-in events, the event name is defined by Casewhere. For custom events, you, as the solution developer, will need to define the event name for your custom widgets.
- Event source: The entity emits the event. It could be a widget in a page or the page itself.
- Event data: The data encapsulated by the event. For example, the book object selected by end-users.
Built-in events
Built-in widgets will emit built-in events. An event object looks like below:
{
source: {
widgetId: '4c0a4156-b307-4a29-8f2e-27d59633c4f6',
widgetName: 'book-list',
widgetApi: // each widget has a set of Apis accessible through this object
},
data: // anything
}
Grid widget / List widget
cwWidget_ItemSelectChange
The event is emitted when the end-users select an item in the grid/list widget.
Event data is a list of selected items. For example:
[
{ Id: "Books/5b8a8b4a-18ae-496a-bdb3-8bd83da308d2", Name: "Book 1" },
{ Id: "Books/9047a790-7442-48f1-a7ac-3d744b3a151f", Name: "Book 2" }
]
cwWidget_ActionExecuted
The event is emitted when the end-users click an action button in the grid/list widget.
Event data is an object containing the action name. For example:
{
actionName: "Edit Book"
}
cwWidget_WidgetApiReady
The event is emitted after the widget object is initiated.
This event does not have data.
cwWidget_WidgetDataLoaded
The event is emitted after the widget data is loaded.
This event does not have data.
cwWidget_ItemDoubleClick
The event is emitted when the end-user double-clicks on the list item.
Event data for the grid widget is a ui-grid row, while it is a data object for the list widget.
Example for grid widget:
{
$$height: // the height of the row,
element: // a jQuery object that represents the DOM row element,
entity: {CaseId: 'b03ff96c-5e4d-464e-a58c-ae0500c5db0b', Title: 'Ulysses', Author: 'James Joyce', Year: '1922', …},
grid: // the grid that contains this row,
isFocused: false,
isSelected: false,
rowTemplate: "caseListRowTemplate.html",
uid: "uiGrid-000C",
visible: true
}
Example for list widget:
{
CaseId: "b03ff96c-5e4d-464e-a58c-ae0500c5db0b",
Title: "Ulysses",
Author: "James Joyce",
Year: "1922",
CaseState: "Created",
Id: "Book/43634984-7596-4bfc-aaae-ae0500c60d14",
selected: false
}
Tab container widget
cwWidget_OnTabSelected
The event is emitted when the end-user select a tab.
Event data contains information of the selected tab. For example:
{
id: "a671bb8a-5242-459f-9809-583d9ac9ff60",
title: "Adventure books",
template: {
html: // an escaped HTML string of a tab
},
clientVisibleRule: // an angularJs expression executed in the tab container scope,
showTab: true
}
Workflow container widget
cwWidget_WorkflowClosed
The event is emitted when the end-user clicks the button Save and close.
Event data contains information of the workflow in context. For example:
{
workflowDefinitionId: "9047a790-7442-48f1-a7ac-3d744b3a151f",
workflowId: "d6f75834-d380-425a-983d-16cf76f46a4c",
caseId: "8c43e3a1-ea20-4c12-b58e-25b1ec8b975f"
}
cwWidget_WorkflowCancelled
The event is emitted when the end-user dismiss the workflow dialog. It could be the Cancel button or the X
icon in the dialog.
Event data contains information of the workflow in context. For example:
{
workflowDefinitionId: "9047a790-7442-48f1-a7ac-3d744b3a151f",
workflowId: "d6f75834-d380-425a-983d-16cf76f46a4c",
caseId: "8c43e3a1-ea20-4c12-b58e-25b1ec8b975f"
}
cwWidget_WidgetApiReady
The event is emitted when the widget is initiated and ready.
This event does not have data.
Page
cwPage_OnLoad
The event is emitted when the page is loaded.
This event does not have data.
Example
In this example, we have a book-list page, and after the end-user selects a book, the book details will be shown on the right side.
To do that, we set up a page as below:
To handle the event from the book-list grid, we set up a page-event handler as below:
Below is the script for the event handler:
var bookDetailsApi = $scope.widgetApis['book-details'];
var selectedBooks = widgetEvent.data;
if (selectedBooks.length > 0) {
var bookId = widgetEvent.data[0].Id;
bookDetailsApi.loadBookDetail(bookId);
}
Custom events
Custom widgets will emit custom events. An event object looks like below:
{
source: {
widgetId: '4c0a4156-b307-4a29-8f2e-27d59633c4f6',
widgetName: 'book-list',
widgetApi: // each widget has a set of Apis accessible through this object
},
data: // anything
}
Emit custom event
To emit a custom event, you can use this method publishEvent(eventName, data)
where eventName
is a free text, data
is whatever information you think the handler will need. It can be a text, an object, etc.
The below method is embedded in all custom widget templates by default:
function publishEvent(eventName, data) {
var widgetEvent = {
source: {
widgetId: $scope.widgetModel.id,
widgetName: $scope.widgetModel.name,
widgetApi: $scope.widgetApi
},
data: data
};
$scope.$emit(eventName, widgetEvent);
}
Handle custom event
It's almost the same with handling a built-in event, just a difference, which is instead of selecting an event from a predefined list, you will need to input the custom event name manually in the Event name textbox.
Example
Let's continue the above example. We will add a button in the details pane, so when the end-user clicks this button, Casewhere will load the next book.
The script behinds this button:
function loadNextBookDetails() {
publishEvent("load_next_book_details");
}
And finally, handle this custom event in the page events.
The full script of the event handler is as below:
var bookListApi = $scope.widgetApis['book-list'];
var bookList = bookListApi.getWidgetData().data;
var currentBook = bookListApi.getSelectedDOs()[0];
var currentIndex = _.findIndex(bookList, function(book) {
return book.Id === currentBook.Id;
});
var nextBook = bookList[currentIndex + 1];
// Deselect the selected book
bookListApi.setSelectedDOs([]);
// Select the next book
bookListApi.setSelectedDOs([nextBook]);