Discussion
Pegasystems Inc.
US
Last activity: 23 Sep 2024 16:25 EDT
How to implement the compare and select pattern in Constellation UI
Commonly, we provide users with a curated list of items for straightforward side-by-side comparison. Typically, this list is kept concise, featuring no more than three or four items to ensure ease of comparison. Each line succinctly presents the unique features and specifications of each item. Upon making a selection, the user can then choose one of these items to proceed in their workflow.
There are multiple examples of side-by-side comparisons that let you select computers, phones, or cars... Other examples include financial reports where you compare the performance of some financial metrics for different reporting periods.
The goal of this article is to showcase how to implement such functionality in Constellation UI.
For this article, we will use 2 custom DX Components: a FieldGroup rendered as a row, and a more advanced component called Compare Table Layout. The source code to implement these components is attached to this article.
1/ Implementing a basic transformation - no custom component
Let's focus first on implementing a financial report - These reports are well structured and grouped and the data are expected to be presented in a certain order.
It is relatively easy to create a data page sourced from a 3rd party system that will give you these details for each reporting period - the issue is that if you render these data directly in a list view, the UI is the reverse of what is expected:
A comparison table is a reverse matrix of a table where the rows become the columns and vice-versa. The transformation can be done using an activity that will take a data page as input and generate the new data page with an object with only some fields like Period, value1, value2... You can find a similar example of flattening the data with the field-level history page https://support.pega.com/discussion/how-enable-field-level-auditing-constellation-based-application
Using this pattern, you could then group the different rows by categories and achieve a report that would be similar to a financial report
Several issues with this approach make it unsuitable for generating financial reports:
-
The sorting of the different rows (group and individual line items) is alphabetical - It works in this case because 'Asset' comes before 'Liabilities' in alphabetical order
-
The categories are repeated on every line item (Assets, CurrentAsset for example)
-
It requires a specific data object to store and report the 4 quarters and this approach will not scale if you want to change the reporting period and/or the number of periods to report
While transforming the data might not work for this use case, this approach is still a valid tool to use when the ordering of the data is not relying on a text field - for example, if you want to show a list of events sorted by date/time (like the Field Level audit table), this transformation approach can be useful.
2/ Rendering a field group 'inline' using a custom component
Rendering the data as a field group would be a better starting point than using a table - The limitation of the field group is that they render as stacked by default and this would not work for a side-by-side comparison UI - You can workaround this limitation by creating a custom DX Component that wraps some CSS styles around the field group and change the display to render inline
The code of this custom component is very simple and creates a 'DIV' using the "styled component" library that will change the presentation of the child DOM elements generated by the field group to render them as 'inline'.
Here is how the same data shown above will look like when wrapped with this custom component:
With this approach, you can guarantee the order and the grouping of the presented data objects. The UI is responsive and wraps the columns if there is not enough space to show them side-by-side.
There are a couple of downsides to this approach:
- Too many repeats of the categories label
- The items might not aligned on the same line if a value is expanding on multiple lines
- From an accessibility standpoint - it is not easily readable - the data should be formatted in a table tag
Here is the same approach using the computer example - while the UI looks great, there are still issues with comparing line by line. For example, the media-engine field is not aligned (the lines in blue indicate how the DOM elements are rendered).
3/ Implementing a more advanced compare table component
The best approach to implement this pattern is to implement a custom component that will generate a table layout for each row - The component can also leverage the field group authoring approach to group the different properties - Here is how the authoring will look like
The financial data object has the following structure which is easy to maintain and extend
My view is configured to use an embedded data list property that will use the custom component as a template layout - the fields are added to the regions - you can use field groups to group these fields - each cell is rendered using the field rendering component.
Here is the output of the report. The report uses the financial formatting for the value (using parentheses for negative numbers), will show 2 types of categories (for example 'Assets' and 'Current Assets'), and will ensure that all the values are lined up in the same row. This UI is achieved using a regular table markup.
4/ Extending the component for the 'select' use case
While a financial report is read-only, most of the use cases will require the user to select something - the custom component demo code supports the ability to change the display format to either use a simple table, a financial report, or a radio button as a card - the selection is done by adding a property that will store the selected ID of the case - if this property is set, the component can display a radio-button on the table.
Here is a screenshot of the storybook demo for this component using the 'simpleTable' display format
For some simpler use cases, you don't need a table with a lot of rows and a better approach is to show a radiogroup card. You can achieve this UI by changing the displayFormat to 'RadioButtonCard'
Here is a screenshot of this presentation mode in the computer application demo used above:
For more details you can watch the video below.
Important note: The code was tested on a Pega Platform '23 build - Make sure to use the correct version of the DX Custom Component tool when using this code on a different version. The code is delivered 'as is' and is provided as an open-source license. If you have questions, feel free to reply to this post.
This post contains both the source of the custom DX components as well as a RAP that you can directly import into your Pega Platform if you don't want to build the custom DX components from source.