Fluent Commerce Logo
Docs
Sign In

UX Framework - Extending Existing Components

Essential knowledge

Authors:

Ben Harrison, Esma Tuzovic

Changed on:

22 July 2024

Overview

This article provides an overview of methods for configuring components within the UX framework. Customization is possible through configuring the various types of components, such as sub-components, wrapper components, and context components. Read on to find out how to use the above approaches.

Key points

  • Core components are highly extensible through configuration; check if your requirements can be met by updating the manifest or component properties (props in the configuration).
  • `DynamicAttribute`
    values in core components allow for the creation of small, specialized sub-components that enhance functionality.
  • Wrapper components can be used to modify existing components' props or styles, enabling more complex customizations beyond basic configurations.
  • Context components can override default data handling by performing additional queries, but be cautious as this can impact performance.

Fluent provides a library of components to support different use cases, but what happens when a retailer needs something slightly different?

Four different ways to customize and extend the core library are detailed below.

1. Configure

The first thing to check is whether the requirement is supported by configuration.

Core components are designed for extensibility, and many different use cases can be supported by simply updating the manifest (refer to 'How to Override the default manifest' for additional details regarding manifest updates) or, in certain instances, the component's settings. 

Various components utilize template strings to accept numerous string values. This functionality enables you to employ a Mustache syntax for generating dynamic values, thereby facilitating the mapping and transformation of data sourced from GraphQL or other origins directly into the UI. You can identify the Mustache template by the use of double quotes surrounding it.

You can retrieve some mustache template samples in UX Configuration Common Concepts, within the Template Strings paragraph.

For further information on the Mustache template, you can refer to the following article:

 See also Escaping/unescaping of values in UX Framework.

2. Sub-components

Some components accept

`DynamicAttribute`
values in their column or row configuration.

These create opportunities for developers to build small utility components that can co-exist with core library components.  Here are a couple of usage examples:

Scenario 1: Collapsible Attributes Component.  Refer to the provided code sample below.

1{
2    "component": "fc.list",
3    "props":{
4        "attributes": [{
5            "label": "i18n:fc.sf.ui.returns.orders.createReturnOrder.list.column.description.label",
6            "type": "component",
7            "options": {
8                "component": "fc.mystique.collapsible.attributes",
9                "dataSource": "node.product.attributes",
10                "props": {
11                    "exclude": [
12                        "imageUrl",
13                        "imageUrlRef"
14                    ],
15                    "collapseOn": "characters",
16                    "collapseLimit": 128
17                }
18            }
19        }]
20    }
21}

Language: json

Name: Collapsible Attributes Component

Description:

Sub-component sample

Scenario 2: Using an attribute to embed the print button component into a table column. Refer to the provided code sample below.

1{
2    "label": "i18n:fc.om.orders.index.list.column.orderValue.heading",
3    "type": "component",
4    "options": {
5        "component": "fc.button.print.download",
6        "props": {
7            "label": "Print",
8            "href": "api/v4/consignment/{{articleById.id}}/labelStream",
9            "filename": "pack-label.pdf"
10        }
11    },
12  "condition": "{{and articleById.id}}"
13}

Language: json

Name: Attribute is used to embed the print button component into a table column

Description:

Example of a

`DynamicAttribute`
 where the print button component is embedded into a table column. Check UX Configuration Common Concepts for details.  

3. Wrapper Component

There are cases where we might want to use an existing component but adjust its functionality to a certain degree. For those familiar with React, this is akin to higher-order components. 

These modifications could include modifying component props, or applying different styles to a standard component. This is particularly useful when building or extending field components, as those are not typically configurable in the manifest, but a wrapper component can be used to load a configuration from a setting and pass that into the underlying library component.

Here's a code sample for the wrapper component concept (utilized for

`PageDateFilter`
): 

1export const PageDateFilter: FC<PageDateFilter> = () => {
2  // data hook lets us see and modify URL parameters
3  const data = useData();  
4
5  // now load an existing component from the registry and display it
6  const DatePicker = FieldRegistry.get('fc.field.daterange');
7
8  return (
9    <PickerContainer
10        defaultValue={{ 
11            from: data.variables.current.from,
12            to: data.variables.current.to
13        }}
14        onChange={(value) => {
15            data.variables.setVariables(value, true);
16        }}
17    />
18  );
19};

Language: typescript

Name: pageDateFilter

Description:

Wrapper component sample

 4. Context Component

Finally, there are times when we might want to replace things that the UX framework (Mystique) will usually handle out of the box.

The most common of these is the data context. While it’s typically populated by the page query, there are cases where we want to do additional queries in a page, often because we want to use the response data from the page query to form the variables we pass into the second query.

Nevertheless, caution is essential since employing additional queries, especially those with varying degrees of complexity, can affect performance.

Here's a code sample for the context component concept (Rest provider use case):

1const RestProvider: FC<RestProviderProps> = ({data, endpoint, props}) => {
2  const [result] = useRest(endpoint, props);
3
4  // reset the data context with the result of the rest call
5  return (<Children dataOverride={result} />);
6}

Language: java

Name: Context component code sample

Description:

Rest provider use case 

The associated sample usage: 

1{
2  "component": "fc.provider.rest",
3  "props": {
4    "endpoint": "/events",
5    "props": {
6      "rootEntityType": "ORDER"
7    }
8  },
9  "descendents": [
10    { 
11      "component": "fc.dashboard.tile",
12      "props": {
13        "label":"{{events.length}}"
14      }
15    }
16  ]
17}

Language: json

Name: Sample usage

Description:

[Warning: empty required content area]


Ben Harrison

Ben Harrison

Contributors:
Esma Tuzovic

Copyright © 2024 Fluent Retail Pty Ltd (trading as Fluent Commerce). All rights reserved. No materials on this docs.fluentcommerce.com site may be used in any way and/or for any purpose without prior written authorisation from Fluent Commerce. Current customers and partners shall use these materials strictly in accordance with the terms and conditions of their written agreements with Fluent Commerce or its affiliates.

Fluent Logo