This section describes the very heart of your application: the pages and their content. Each page is in its simplest version made up of an id
and a list of blocks
. Optionally, you can specify many other configuration options for your pages. Let's dive in.
Before starting, please ensure that you have set up the JSON schema for your configuration files. If you are working on a classic journey, refer to the classic journey guide. For a split journey and multi-tenant journey, follow the split journey guide.
You can customize the page title for each journey page via its corresponding configuration. Every field containing text is translatable, and you can include dynamic data coming from your application state using the {$.MY_STATE_KEY.SUBKEY"}
syntax.
It is possible to configure a simple title that just contains a headline:
// Page configuration
{
"id": "my-page-a",
"title": "My title for customer {$.customer.name}"
}
or a slightly more complex title which contains a headline and a subline:
// Page configuration
{
"id": "my-page-a",
"title": {
"headline": "My custom headline",
"subline": "Customer: {$.customer.name}"
}
}
In addition to that, you can show the page title as a stage. To do so, you need to add the showAsStage
property to the page title configuration:
{
// Page configuration
"id": "my-page-a",
"title": {
"headline": "My custom headline",
"subline": "Customer: {$.customer.name}",
"showAsStage": true
}
}
When the title is configured to be shown as a stage, you can optionally configure either a subline
or a topline
. Additionally, you can set different images for the stage. The following snippet shows how to configure such a page title to be shown as a stage:
{
// Page configuration
"id": "my-page-a",
"title": {
"headline": "My custom headline",
"topline": "My custom subline",
"showAsStage": true,
"startImage": "path/to/start-image.png",
"endImage": "path/to/end-image.png",
"narrowImage": "path/to/narrow-image.png"
}
}
The advanced property hideBackLink
also belongs to the stage configuration. For more information about it, please check its documentation here.
All Building Blocks and Dynamic Forms on the same page can be grouped in Page Sections. This is a way to group related Building Blocks and Dynamic Forms together. Each section is separated by specific separator (bigger spacer or dividing line).
To group Building Blocks and Dynamic Forms together, you need to specify a sections
property on the containing page. Each section is required to have an id
property for identification. Optionally, you can specify a translatable title
that will be rendered as a headline at the top of the section, as well as a dividerLineBelow
to render a divider line at the bottom of the section.
// Page configuration
{
"...": "...",
"sections": [
{
"id": "section-a",
"title": "My Section A",
"dividerLineBelow": true
}
]
}
To assign a Building Block or a Dynamic Form to a section, you need to specify the section
property with a previously declared section id
. You can assign as many Building Blocks and Dynamic Forms to a section as you need.
// Page configuration
{
"...": "...",
"blocks": [
{
"...": "...",
"section": "section-a"
}
]
}
💡 To be able to add a divider line between sections you need to group these Building Blocks and Dynamic Forms into sections.
TALY allows you to wrap any Building Block(s) and Dynamic Form(s) within a panel, offering collapsing and expanding functionality following the NDBX Accordion component. All panels that will be used on a page must be declared in the panels
property at the root level of the page configuration. The panels
list accepts an object containing the following properties for each panel:
// Page configuration
{
"...": "...",
"panels": [
{
"id": "collapsed-panel-1",
"title": "An expandable panel",
"section": "section-a",
"style": "EXTRA-LIGHT",
"collapsed": false
}
]
}
id
: The unique identifier for the panel. This id
will be used in the blocks
configuration to assign Building Blocks to the panel.title
: The title of the panel. This title is translatable by default.section
(optional): Identifies the section to which the panel belongs. If a panel is assigned to a section, it will be rendered within that section. If a panel is not assigned to any section, it will be rendered as a standalone panel.style
(optional): Configuration for the style of the panel. By default, TALY renders a panel using the light style for retail journeys and using the regular style for expert journeys.collapsed
(optional): Specifies whether the panel should be collapsed by default.To assign a Building Block or a Dynamic Form to a panel, you need to specify the panel
property with a previously declared panel id
. You can assign as many Building Blocks and Dynamic Forms to a panel as you need.
// Page configuration
{
"...": "...",
"blocks": [
{
"...": "...",
"panel": "collapsed-panel-1"
}
]
}
💡 Building Block can be assigned to either a section or a panel, but not both.
Different pages usually have different content & layout requirements. That's why we provide a set of properties that you can change per page. We call them the Taly Page Data
and it's a feature on every Building Block page. This is the current definition of that data.
export interface PageData {
navigation?: {
hidden?: boolean;
preventClickNavigation?: boolean;
};
pageActionConfig?: {
nextButtonHidden?: boolean;
backButtonHidden?: boolean;
nextButtonLabel?: string | PageActionButtonLabel[];
backButtonLabel?: string | PageActionButtonLabel[];
backButtonUseTertiaryStyle?: boolean;
extraActions?: string[];
cancelButtonLabel?: string | PageActionButtonLabel[];
};
}
export interface PageActionButtonLabel {
label: string;
condition: string;
}
On each page, you can do this:
i18n is automatically supported for all labels configured in the Page Data
. For the labels, you can either specify a string or an array of objects that displays the label text depending on a PFE Condition. If you do not specify, the default label text is used.
Here is an example configuration with all available features per page being used. Refer to the section in this documentation for details on the available properties.
// Page configuration
{
"id": "first-page",
"pageData": {
"navigation": {
"hidden": true,
"preventClickNavigation": true
},
"pageActionConfig": {
"nextButtonLabel": [
{
"label": "Conditional Next Button Label",
"condition": "{$['my-dynamic-form'].myCheckbox}"
},
{
"label": "Another Conditional Next Button Label",
"condition": "{$['my-dynamic-form'].firstName} === {$['my-dynamic-form'].lastName}"
}
],
"backButtonLabel": "Cancel",
"cancelButtonLabel": "Cancel",
"nextButtonHidden": false,
"backButtonHidden": true,
"backButtonUseTertiaryStyle": true,
"extraActions": ["SAVE_OFFER"]
}
}
}
The blocks
configuration allows you to define the content of your page. You have the option to add Building Blocks and/or Dynamic Forms to this area.
The decision of whether to use a Dynamic Form or a Building Block should be based on the complexity of the requirements as well as the level of customization needed for the component.
Dynamic Forms offer a no-code approach for creating standard forms, enabling quick prototyping, easy adaptation, and compliance with accessibility and tracking standards. Nevertheless, there are limited options available for customization.
On the other hand, Building Blocks are pre-implemented components designed for specific business needs. It's possible to embed complex logic and completely customize the visual appearance of Building Blocks. They provide an extension mechanism for cases that cannot be covered via configuration only and allow sharing of functional units across various journeys.
💡 Dynamic Forms are currently an experimental feature. To enable them, please follow the experimental feature documentation.
To utilize Dynamic Forms in your journey, you can simply add a form
object along with an id
. Within the form
object, you have the option to specify layout
, fields
, and acl
as needed.
// Page configuration
{
"id": "page-a",
"blocks": [
{
"id": "my-dynamic-form",
"form": {
"layout": "ONE_COLUMN",
"fields": [],
"acl": []
}
}
]
}
The Dynamic Form was also presented as a part of the ScaleUp! Initiative. A recording of that session, with a demo of the Dynamic Form, can be found here.
The following playgrounds allow it to configure a Dynamic Form in real-time directly in the browser:
The editor in the playground provides a full JSON-Schema integration. Trigger the autocomplete (Either via Ctrl/Cmd+Space or Ctrl/Cmd+i) to get support for the configuration.
A configuration from the playground can directly be used in the form
attribute inside a journey configuration.
Dynamic Forms support various layout options, including the ability to apply the same size to all elements in a form and the option to mix different sizes. Everything inside Dynamic Forms is left-aligned by default, regardless of whether it's an expert or retail journey. If the layout
option is not provided, form elements will be rendered as one column.
You can use the options ONE_COLUMN
, TWO_COLUMN
, THREE_COLUMN
, or FOUR_COLUMN
to equally divide form elements into specified columns.
// Page configuration
{
"id": "page-a",
"blocks": [
{
"id": "my-dynamic-form",
"form": {
"layout": "ONE_COLUMN",
"fields": []
}
}
]
}
If you want to mix different sizes within a form, the CUSTOM_COLUMN
option allows you to specify how many column(s) each element should span. The number can be 1-12, following the 12-column grid system.
// Page configuration
{
"id": "page-a",
"blocks": [
{
"id": "my-dynamic-form",
"form": {
"layout": "CUSTOM_COLUMN",
"fields": [
{
"id": "firstInput",
"type": "INPUT",
"inputType": "text",
"label": "First input",
"columnSpan": 3
},
{
"id": "secondInput",
"type": "INPUT",
"inputType": "text",
"label": "Second input",
"columnSpan": 9
}
]
}
}
]
}
The CUSTOM_COLUMN
layout allows configuring complex layouts like in the following form (The Figma version is available here):
Open this form in the Dynamic Form playground.
The fields
configuration allows you to add elements to a form. Each element requires a different configuration depending on its type
. However, all elements need to have an id
and type
set.
// Page configuration
{
"id": "my-page",
"blocks": [
{
"id": "my-dynamic-form",
"form": {
"fields": [
{
// The field's id should be written in camel case to make it easier to locate the state key
"id": "myInput",
// Type of the element which influences the rest of the configuration
"type": "INPUT",
"inputType": "text",
"label": "This is a dynamic input field"
}
]
}
}
]
}
The configuration details of each element can be found below:
Type | Configuration |
---|---|
CHECKBOX |
DfCheckboxConfig |
CIRCLE_TOGGLE_GROUP |
DfCircleToggleGroupConfig |
DATE |
DfDateConfig |
DROPDOWN |
DfDropdownConfig |
HEADLINE |
DfHeadlineConfig |
INPUT |
DfInputConfig |
PARAGRAPH |
DfParagraphConfig |
RADIO |
DfRadioConfig |
TEXT_AREA |
DfTextAreaConfig |
SWITCHER |
DfSwitcherConfig |
LINE_BREAK |
DfLineBreakConfig |
💡 Dynamic Form validators are similar to Building Block validators. More details about validators configuration can be found in the Building Block section.
To force a new line for the following form fields, you can add a LINE_BREAK
field. In the example below, the field "another field" will appear on the next line, regardless of the form layout:
// Page configuration
{
"id": "my-page",
"blocks": [
{
"id": "my-dynamic-form",
"form": {
"fields": [
{
"id": "some-field"
// ...
},
{
"type": "LINE_BREAK"
},
{
"id": "another-field"
// ...
}
]
}
}
]
}
The LINE_BREAK
field does not require an id
.
You can use custom Dynamic Form components if the above list of built-in Dynamic Form fields is not enough for your use-case. Custom Dynamic Form components are provided through TALY plugins. If you want to provide your own custom component, take a look at the corresponding Plugins documentation.
A journey configuration that's using an imaginary TALY plugin library my-plugin-library
that provides a custom Dynamic Form component called MyCustomComponent
in a module called CustomDynamicFormComponentModule
could look like this:
// pages.jsonc
{
"libraries": [{ "package": "my-plugin-library", "version": "13.3.7" }],
"plugins": [
{
"package": "my-plugin-library",
"modules": [{ "name": "CustomDynamicFormComponentModule" }]
}
],
"pages": [
{
"id": "my-page",
"blocks": [
{
"id": "my-form",
"form": {
"fields": [
{
"type": "CUSTOM_COMPONENT", // has to be "CUSTOM_COMPONENT" if you want to use a custom component
"name": "MyCustomComponent", // the name of the custom component that was added by the TALY plugin
"label": "Label for my custom component",
// ... further field configuration. Use the autocompletion in your IDE.
// See the schema here: https://taly.frameworks.allianz.io/interfaces/DfCustomComponentConfig.html
"config": {
// any additional configuration for this custom component
}
}
]
}
}
]
}
]
}
To make Dynamic Form configurations portable, TALY supports setting ACL rules directly at the form and field levels.
The form-level ACL configuration allows path
, state
and condition
properties. If you are not familiar with them, please take a look at our ACL documentation.
// Page configuration
{
"id": "my-page",
"blocks": [
{
"id": "my-dynamic-form",
"form": {
"acl": [
{
//The path can be an asterisk (*) to target all children fields
// or an id of the child field.
"path": "myHeadline",
"state": "hidden",
// The condition must be written in this format.
// Please be careful of the usage of single and double quotes.
"condition": "s(\"$['my-dynamic-form'].myRadioButtons\") == \"first\""
}
],
"fields": []
}
}
]
}
The field-level ACL configuration allows only state
and condition
properties. All ACL rules are applied to the attached field by default.
// Page configuration
{
"id": "my-page",
"blocks": [
{
"id": "my-dynamic-form",
"form": {
"fields": [
{
"id": "myInputField",
"type": "INPUT",
// All rules are applied to "myInputField"
"acl": [
{
"state": "disabled",
// The condition must be written in this format.
// Please be careful of the usage of single and double quotes.
"condition": "s(\"$['my-dynamic-form'].myRadioButtons\")"
}
]
}
]
}
}
]
}
Dynamic Form configurations allow controlling what should happen when the value of a form field changes and when the form element loses the focus. You can either configure a PFE action or service activator as event handlers.
The following examples show how to configure the event handlers for a form field by providing the ID of the global PFE action or service activator. Alternatively, you can provide a full PFE action or service activator configuration.
// Dynamic Form's input field
{
"id": "my-input",
"type": "INPUT",
"inputType": "text",
"label": "This is an input field",
"onValueChangesEvent": {
"handlerType": "PFE_ACTION",
"config": {
"globalConfigId": "myPfeAction"
}
},
"onBlurEvent": {
"handlerType": "PFE_SERVICE_ACTIVATOR",
"config": {
"globalConfigID": "myServiceActivator"
}
}
}
You can also configure events for custom components. The following example shows how to configure the event handler for a custom component:
// Dynamic Form's input field
{
"type": "CUSTOM_COMPONENT",
"name": "MyCustomComponent",
"label": "Label for my custom component",
"config": {
"myCustomEvent": {
"handlerType": "PFE_ACTION",
"config": {
"globalConfigId": "myPfeAction"
}
}
}
}
For more information about PFE actions and service activators, please check their respective docs here and here.
All string properties that are visible to the user are translatable by default. You can follow the internationalization guide for translation instructions.
Additionally, you can use interpolation within string properties to display a value from the PFE state. For example:
// Dynamic Form's input field
{
"id": "myInput",
"type": "INPUT",
"inputType": "text",
"label": "Hello {$['my-bb'].person.firstName}!",
"placeholder": "Hello {$['my-bb'].person.firstName}!"
}
When providing an initial value
for a field, you can provide a JSONPath expression (like for field nickName
in the snippet below).
The value of your Dynamic Form field will update whenever the state at the given JSONPath expression changes but changing the value of the field will not update the state at the given JSONPath expression.
{
"id": "nickName",
"type": "INPUT",
"inputType": "text",
"label": "Nick Name",
"value": "$.thisForm.firstName"
},
{
"id": "firstName",
"type": "INPUT",
"inputType": "text",
"label": "First Name"
}
This example in the playground demonstrates a few possibilities of interaction.
As mentioned in the Building Block Development, resources can be configured as static values as well as dynamic values based on values from the PFE state.
In the following example, we are telling the journey that our Building Block expects a resource called resourceA
, and it should be filled with the value of $['resource-a-information']
from the PFE state. We know that is the content of another Building Block that had some state that got saved under this key.
// Page configuration
{
"id": "page-a",
"blocks": [
{
"id": "block-a",
"resources": {
"resourceA": {
"type": "PFE_STORE_QUERY",
"query": "$['resource-a-information']"
}
}
}
]
}
If your Building Block requires a string as a resource, then this string will most likely need to be translatable. To prepare a string resource to be translatable you need to prefix it with @localize.
. The following snippet shows a message
resource that will be translatable in the generated application:
// Page configuration
{
"id": "page-a",
"blocks": [
{
"id": "block-a",
"resources": {
"message": "@localize.This is a translatable message"
}
}
]
}
⚠️ Please use (translatable) string resources with caution. Most of the time, passing a string as a resource is not the best idea. Providing a place for consumer-defined content in your Building Block probably makes the Building Block more reusable but also less specific. Remember this tradeoff when you consider adding a string resource.
The TALY framework provides the ability to configure the validation of a Building Block form. Multiple validator configs can be specified as the objects inside validators
list. Each item in this list assigns a validator to a concrete form field. It consists of:
id
- a form control path.type
- the validator type to be assigned to the form field.errorMessage
- a custom error message to be displayed to the user. This message is translatable for the different locales supported by TALY. If it is not configured, TALY will provide the default message for you.Validation config example:
// Page configuration
{
"id": "page-a",
"blocks": [
{
"id": "block-a",
"package": "@allianz/taly-core",
"module": "PlaceholderModule",
"selector": "taly-placeholder-bb",
"validators": [
{
"id": "legalConsent",
"type": "REQUIRED_TRUE"
}
]
}
]
}
TALY provides a set of basic validators that aim to cover common use cases for the different Building Blocks, and are mostly plain native Angular validators. Please see the available validators details below:
Type | Extra parameter | Default error message |
---|---|---|
REQUIRED | - | This field is required! |
REQUIRED_TRUE | - | This field is required to be true! |
MIN | min: number | This field needs to have a minimal value of ${min}. |
DYNAMIC_MIN | min: ResourceObject | This field needs to have a minimal value of ${min}. |
MAX | max: number | This field needs to have a maximum value of ${max}. |
DYNAMIC_MAX | max: ResourceObject | This field needs to have a maximum value of ${max}. |
MIN_LENGTH | minLength: number | This field can only have a min length of ${minLength} characters. |
MAX_LENGTH | maxLength: number | This field can only have a max length of ${maxLength} characters. |
- | This field requires a valid email | |
PATTERN | pattern: string | This field has invalid format. |
MIN_DATE | minDate: string | This field requires a more recent date |
MAX_DATE | maxDate: string | This field requires a older date |
If the TALY validators listed above do not meet your requirement, you can also create a custom validator from a plugin in your own library. Please refer to the Plugin document for more details.
You can apply special styles to your Building Blocks using the buildingBlockStyle
property in the Building Block configuration. The following subsections explain what is possible with this property.
💡 Building Blocks that are part of a
panel
or asection
can't be styled.
You can set a background color for a Building Block that spans over the full browser width. To achieve this behavior you need to set the buildingBlockStyle.backgroundColor
property in Building Block configuration like so:
// Page configuration
{
"blocks": [
{
"id": "building-block-id",
"...": "...",
"buildingBlockStyle": {
"backgroundColor": "DarkSlateBlue"
}
}
]
}
In certain situations, a Building Block might require less space. By marking it as compact
, vertical paddings will be reduced.
The compact
option is only applicable to non-sticky Building Blocks with background color.
// Page configuration
{
"blocks": [
{
"id": "building-block-id",
"...": "...",
"buildingBlockStyle": {
"compact": true,
"backgroundColor": "blue"
}
}
]
}
This mechanism allows a TALY journey to run either a service activator or a PFE action when the Building Block triggers a specific event. See the Building Block Business Event section to learn more about how to trigger a business event from a Building Block.
The business event configuration requires specifying the handlerType
property to signal if the business event configuration corresponds to a PFE service activator or a PFE action.
For PFE service activators, this is how a possible configuration would look like:
// Page configuration
{
"id": "my-page-a",
"blocks": [
{
"...": "...",
"businessEvents": {
"countries-loaded": {
"handlerType": "PFE_SERVICE_ACTIVATOR",
"config": {
"path": "cities/names",
"serviceActivatorMethod": "GET"
}
},
"...": "..."
}
}
]
}
Alternatively, you can just map to a PFE global service activator by providing the globalConfigID
field in the config
object.
// Page configuration
{
"id": "my-page-a",
"blocks": [
{
"...": "...",
"businessEvents": {
"countries-loaded": {
"handlerType": "PFE_SERVICE_ACTIVATOR",
"config": {
"globalConfigID": "citiesNames"
}
},
"...": "..."
}
}
]
}
For historical reasons, it is also possible to bind a PFE service activator to a business event by just providing the service activator id. This method assumes the service activator is already defined as a global service activator in the navigation configuration:
// Page configuration
{
"id": "my-page-a",
"blocks": [
{
"...": "...",
"businessEvents": {
"country-selected": "getAddressFields"
}
}
]
}
// Global service activator
{
"getAddressFields": {
"serviceActivatorMethod": "GET",
"path": "address-fields"
}
}
We strongly recommend to not use this method for configuring service activators as business events. Please use the approach described at the beginning of this section instead.
For more information about service activators, please see the PFE documentation.
As mentioned before, it is also possible to bind a PFE action to a TALY business event. This is an example of how to do so:
// Page configuration
{
"id": "my-page-a",
"blocks": [
{
"...": "...",
"businessEvents": {
"countries-loaded": {
"handlerType": "PFE_ACTION",
"config": {
"type": "HELLO_WORLD_LOG",
"conditions": [
{
"value1Expression": "$.showLogs",
"operator": "==",
"value2Expression": "true"
}
]
}
},
"...": "..."
}
}
]
}
In the example above we are using the custom PFE action HELLO_WORLD_LOG
. Alternatively, you could also use one of the pre-registered PFE actions. Please note that custom actions need to be registered by the journey, for example via a TALY plugin.
In addition to that, you can just provide the globalConfigId
field in your business event configuration to map to a global PFE action:
// Page configuration
{
"id": "my-page-a",
"blocks": [
{
"...": "...",
"businessEvents": {
"countries-loaded": {
"handlerType": "PFE_ACTION",
"config": {
"globalConfigId": "helloWorld"
}
}
},
"...": "..."
}
]
}
It is possible to run several service activators and/or PFE actions by just triggering a single business event. This can be done thanks to PFE nested actions. This is an example of how to do so:
// Page configuration
{
"id": "my-page-a",
"blocks": [
{
"...": "...",
"businessEvents": {
"payment-received": {
"handlerType": "PFE_ACTION",
"config": {
{
"type": "PFE_NESTED_ACTIONS",
"actions": [
{
"type": "TRIGGER_SERVICE_ACTIVATORS",
"...": "..."
},
{
"type": "UPDATE_STATE_VALUES",
"...": "..."
}
]
}
}
}
}
}
]
}
To learn more about PFE actions and how to register them, please see the PFE documentation.
Building Blocks can request navigation to certain pages. The Building Block, however, does not know anything about the page IDs of your specific journey. To allow the Building Block to navigate to the desired pages you need to provide page aliases in the Building Block configuration. A Building Block's documentation will likely mention if it requires such configuration (i.e. if it intends to trigger navigation(s)).
Example: If a Building Block in your journey wants to navigate to a generic payment
page, you need to let the Building Block know what this page is called in your specific journey. To do this, use the navigation
property of the Building Block configuration:
// Page configuration
{
"id": "my-page-a",
"blocks": [
{
"id": "building-block-id",
"...": "...",
"navigation": {
"payment": "my-journeys-payment-page"
}
}
]
}
Now, if the Building Block requests a navigation to payment
, your journey's my-journeys-payment-page
page will appear.
If you want to trigger a navigation from inside of your Building Block, take a look at the corresponding documentation about Building Block Development.
TALY-generated journeys can display overarching notifications above the page content. All NDBX notification types are supported. When TALY detects a new notification, it will immediately scroll to it.
The notifications are sorted based on their type. From top to bottom: 'error', 'warning', 'info' and 'success'. There are no constraints to the amount or types of notifications displayed simultaneously. For example, it is possible to show 1 error, 2 warnings, and 1 success notification simultaneously. As a journey creator, you are in control of the notifications that are displayed at any given point in time.
In terms of content, the notifications have a message and optionally a title. Both of them can display dynamic content based on the state of the application. Additionally, the notification message can contain lists and links in the Markdown format, which TALY will transform to the corresponding NDBX components. You can also link to internal pages by using the page://
prefix and the pageId
inside a Markdown link, e.g. [internal link](page://second-page)
. Please note that navigation to internal pages will still run even if there are invalid forms on the current page.
In addition, by default non-error notifications can be dismissed by the user, and you can configure them to be non-dismissible.
Apart from that, you can determine the visibility of each notification via a visibleIf
property. This property can contain a JSONPath expression or a PFE_EXPRESSION condition that references one or more values from the application's state. The notification will then only be shown if that value is truthy.
You can define the notifications in the page configurations as follows:
// Page configuration
{
"id": "first-page",
"notifications": [
{
"message": "A simple message with no markdown and no dynamic data",
"context": "success",
"closable": false,
"visibleIf": "$.customerName.email"
},
{
"title": "Important information",
// message with dynamic content
"message": "All policy documents will be sent to {$.customer.name} at {$.customerName.email}",
"context": "info",
"visibleIf": "$.customerName.email"
},
{
// title with dynamic content
"title": "Warning with dynamic data {$['bb-1'].someKey} ",
// message with dynamic content, a list and links
"message": "text with [link](http://example.com) and list\n- item 1\n- [list link](http://example.com). Also supports dynamic data like: {$['bb-pgr-simple'].person.firstName}",
"context": "warning"
}
]
}
The error notifications have a slightly different configuration and behavior compared to other notifications.
They are designed to not allow the closable
option. Differently from other notification types, if a page is showing multiple error messages, they will be displayed as part of the same error notification.
In addition, if an error notification is displayed, the navigation to the next page will be blocked.
This is an example of a page configuration with an error notification:
// Page configuration
{
"id": "first-page",
"notifications": [
{
// title (optional)
"title": "The policy number does not exist",
// message containing Markdown links and list
"message": "Please contact us:\n - Hotline: [+49 111](tel:492111) \n- E-mail: [email@allianz.com](mailto:email@allianz.com)",
// type of the notification
"context": "error",
// when the notification should be displayed on a page
"visibleIf": "{$.errorFromPlugin}"
}
]
}
The error notifications work seamlessly in combination with the PFE validation message feature. Error messages coming from that source will be displayed as an error notification in TALY-generated journeys as well. To use this PFE feature, you can rely on the default PFE state key for the error message (validationErrorData
) or override that with another key by setting validationErrorStateKey
in pfe.json[c]
for classic journey like this:
// pfe.json[c]
{
"appConfiguration": {
"pfeConfig": {
"validationErrorStateKey": "customErrorDataKey"
}
}
}
Or in application.json[c]
for split journey like this:
// application.json[c]
{
"validationErrorStateKey": "customErrorDataKey"
}
and like this in the service activator configuration:
// Service activator configuration
{
"SomeResourceRequest": {
"serviceActivatorMethod": "GET",
"path": "some-resource-that-throws-error",
"errorHandling": {
"errorCases": [
{
"disableErrorPageNavigation": true,
"errorResponseDataMapping": [
{
"responseDataExpression": "$.message",
"stateKeyExpression": "$.validationErrorData"
}
]
}
]
}
}
}
Note that disableErrorPageNavigation
is set to true
to stay on the current page instead of navigating to the error page.
You can optionally display a single Building Block in the overarching details area using the configuration below. You can configure the overarchingDetailsBlock
just like any other Building Block, with the exception that this special Building Block doesn't accept a section
, a panel
, or a buildingBlockStyle
property. The Building Block developers are responsible for including all the required styles.
// Page configuration
{
"id": "first-page",
"overarchingDetailsBlock": {
"id": "my-overarching-bb",
"selector": "bb-example",
"module": "ExampleModule",
"package": "@allianz/example-package",
"resources": {
"productType": { "type": "PFE_STORE_QUERY", "query": "$.product.type" },
"productName": { "type": "PFE_STORE_QUERY", "query": "$.product.name" }
}
}
}
To add "small print" like legal information to a page you can use the smallPrint
property of a page. This property accepts an array of strings:
// Page configuration
{
"id": "my-page-with-small-print",
"smallPrint": [
"Each Party agrees to keep the [Confidential Information](http://example.com) of the [...]",
"This Agreement shall commence on the [...]\nThis Agreement shall [...]",
"Special details in a list:\n- Detail 1\n- Detail 2"
]
}
This is what a similar configuration would look like on your page:
💡 Note that you can only use this limited set of Markdown features in your small print:
[label](url)
to add a link- You can also link to internal pages by using the
page://
prefix and thepageId
inside a Markdown link, e.g.[internal link](page://second-page)
. Please note that navigation to internal pages will still run even if there are invalid forms on the current page.\n
to add a line-break- list item
to add a list (item)
The-
needs to be the first non-whitespace character of the line, so it's best to always preceed it with a\n
, like so:\n- list item 1\n- list item 2
.
You can add a single Banner Building Block to a page by configuring it as the bannerBlock
in your page configuration. A Banner Building Block will be placed on the top of the page (above the Page Title if it exists) until they hit the top end of the screen where they will stay when the user scrolls further down. You can use this for example to make a Package Banner
very prominent on the page.
💡 If there is more than one sticky element on a page (either a Banner Building Block or an element inside a regular BB) they will overlap. Ideally there should always only be a single sticky element on a page. If you absolutely need more than one sticky element make sure that the first sticky element is the smallest one (in terms of height) to avoid any visible overflow from underneath the other sticky element(s).
Here is what a page configuration with a Banner Building Block could look like:
{
// Page configuration
"id": "first-page",
"bannerBlock": {
"id": "package-banner",
"selector": "bb-example",
"module": "ExampleModule",
"package": "@allianz/example-package",
"buildingBlockStyle": { "backgroundColor": "#4a79af" },
"...": "..."
}
}
You can add content in the sidebar by marking specific Building Blocks to be shown with the sidebar
flag in the respective building block configuration. The sidebar will only be shown on pages that contain building blocks with the sidebar
flag.
// Page configuration
{
"id": "my-page",
"title": "My page",
"blocks": [
{
"id": "my-sidebar-block",
"selector": "taly-placeholder-bb",
"package": "@allianz/taly-core",
"module": "PlaceholderModule",
"sidebar": true
}
]
}
You can have a look at the data model for a journey page configuration here.