Composition File
The {widgetName}.json widget definition file is a required resource in every widget bundle. It defines the UI composition—specifying which components render, their layout hierarchy, ordering, and how they dynamically bind to widget attributes.
This table lists the properties that you can specify in a {widgetName}.json file.
| Property | Type | Required or Optional | Description |
|---|---|---|---|
type | String | Required | The content type identifier. Set this to lightning__agentforceWidget. This identifier applies to all supported Salesforce applications and platforms. |
contentBody | Object | Required | The root content object containing the composition structure. |
contentBody.widgetBody | Object | Required | The root component that holds the widget’s composition structure. |
This example shows a composition file for a hotel card widget (hotelCard.json) that defines the visual structure and data binding tokens. The {!$attrs.attributeName} expressions reference widget attributes defined in the widget’s schema.json file.
1{
2 "type": "lightning__agentforceWidget",
3 "contentBody": {
4 "widgetBody": {
5 "definition": "tile/widget",
6 "children": [
7 {
8 "definition": "tile/card",
9 "attributes": {
10 "padding": "lg",
11 "variant": "default",
12 "maxWidth": "full"
13 },
14 "children": [
15 {
16 "definition": "tile/image",
17 "attributes": {
18 "src": "{!$attrs.imageUrl}",
19 "alt": "{!$attrs.title}"
20 }
21 },
22 {
23 "definition": "tile/text",
24 "attributes": {
25 "text": "{!$attrs.title}",
26 "variant": "h3",
27 "weight": "semibold"
28 }
29 },
30 {
31 "definition": "tile/text",
32 "attributes": {
33 "text": "{!$attrs.price}",
34 "variant": "body",
35 "weight": "medium"
36 }
37 },
38 {
39 "definition": "tile/text",
40 "attributes": {
41 "text": "{!$attrs.description}",
42 "variant": "body"
43 }
44 }
45 ]
46 }
47 ]
48 }
49 }
50}Composition Building Blocks
To build the visual structure shown in the code example, understand these fundamental layout elements:
- Components: The atomic building units of a widget’s visual layout. Each component specifies a
definition. Depending on the component and its rendering behavior, it can also specifyattributes,children, andmeta.- definition: The specific component to render (such as
tile/card,tile/text, ortitle/image). - attributes: Configuration key-value pairs applied directly to the component. These pairs can be static values or dynamic token expressions.
- children: An array of nested child components rendered sequentially inside the parent component container.
- meta: Rendering instructions that control whether a component renders or repeats for items in a collection.
- definition: The specific component to render (such as
- Root Component Requirement: Every widget structure requires a root
widgetBodycomponent with its definition set to"tile/widget". This configuration serves as the primary wrapper holding all subsequent child components. - Data Binding Expressions: Use the token syntax
{!$attrs.attributeName}to reference widget attributes within component properties. The widget’sschema.jsondefines these attributes. Attributes receive their values at run time when you connect the widget to a Lightning type through attribute mapping.
Use Static Resources in Widgets
Widget attributes can reference external static resources, such as image URLs. To render, the static resource must be accessible without authentication.
To enable loading static resources from a specific domain via MCP servers, add the domain as a Trusted URL in your org. After you set up the Trusted URL, Salesforce automatically provisions the Content Security Policy setting for the MCP server.
Use Salesforce Formulas in Widgets
Widget composition supports a formula language based on the Salesforce formula engine. Use formulas to automatically generate live results based on computed values and conditional statements. You can use infix operators for math, comparison, and logic, and built-in functions for conditionals, string operations, and so on.
For example, the formula "text": "{!$order.subtotal * $order.taxRate}" computes the amount of tax on an order. See the HXL Playground for more examples of formulas.
Control Component Rendering with Meta Properties
Use the meta object in a widget composition to control whether a component renders and to repeat a component for items in a collection.
The meta object supports these properties.
| Property | Required or optional | Description |
|---|---|---|
if | Optional | References an expression that evaluates to a Boolean value. Includes the component only when the expression evaluates to true.The if expression can reference a Boolean widget attribute, such as {!$attrs.isVerified}, or a Boolean property of the current item, such as {!$amenity.isAvailable}. |
forEach | Optional | References the collection whose items the component renders. |
forItem | Optional | Defines the variable used to reference the current item. The value must begin with $. If omitted, the value defaults to $Item. |
forIndex | Optional | Defines the variable used to reference the current item’s index. The value must begin with $. |
Render a Component Conditionally
Use meta.if to control whether a component and its children render. The expression must evaluate to a Boolean value. If the expression evaluates to true, the component and its children render. If it evaluates to false, the component and its children aren’t included in the rendered output.
A non-Boolean result, such as a number, string, or empty array, isn’t supported and causes an evaluation error. A missing or null-valued reference is treated as false.
This example renders a message only when the isVerified widget attribute evaluates to true.
1{
2 "definition": "tile/text",
3 "meta": {
4 "if": "{!$attrs.isVerified}"
5 },
6 "attributes": {
7 "text": "Verified hotel",
8 "variant": "body"
9 }
10}In this example:
{!$attrs.isVerified}references theisVerifiedattribute defined in the widget’sschema.jsonfile.- The
tile/textcomponent renders only whenisVerifiedevaluates totrue.
If the component contains children, excluding the component also excludes all its child components.
Use Complex Conditions
Use supported comparison operators and expression functions to combine conditions.
1{
2 "definition": "tile/text",
3 "meta": {
4 "if": "{!AND($attrs.isAvailable, $attrs.price < 500)}"
5 },
6 "attributes": {
7 "text": "Available within budget",
8 "variant": "body"
9 }
10}Render a Component for Each Collection Item
Use meta.forEach to repeat a component for each item in a collection. Optionally, set meta.forItem to the variable that represents the current item. The forItem value must begin with $.If forItem is omitted, the current-item variable defaults to $Item.
This example renders a text component for each amenity in an amenities collection.
1{
2 "definition": "tile/text",
3 "meta": {
4 "forEach": "{!$attrs.amenities}",
5 "forItem": "$amenity"
6 },
7 "attributes": {
8 "text": "{!$amenity.name}",
9 "variant": "body"
10 }
11}In this example:
{!$attrs.amenities}references theamenitiescollection supplied through the widget’s attribute contract.$amenityrepresents the current item.{!$amenity.name}references the name property of the current item.- The
tile/textcomponent renders once for each item in the collection.
This example omits meta.forItem, so the current-item variable defaults to $Item. The {!$Item.name} expression references the name property of the current item.
1{
2 "definition": "tile/text",
3 "meta": {
4 "forEach": "{!$attrs.amenities}"
5 },
6 "attributes": {
7 "text": "{!$Item.name}",
8 "variant": "body"
9 }
10}The optional meta.forIndex property defines a variable that represents the current item’s index. The value must begin with $.
This example uses $amenityIndex to reference the current item’s index:
1{
2 "definition": "tile/text",
3 "meta": {
4 "forEach": "{!$attrs.amenities}",
5 "forItem": "$amenity",
6 "forIndex": "$amenityIndex"
7 },
8 "attributes": {
9 "text": "{!$amenity.name}",
10 "variant": "body"
11 }
12}You can nest components that use meta.forEach to render multidimensional collections. Each iteration creates a separate scope for its item and index variables.
Combine Conditional Rendering and List Iteration
When a component specifies both meta.forEach and meta.if, the condition is evaluated for each item in the collection. The component renders only for items whose condition evaluates to true.
This example renders only amenities whose isAvailable property evaluates to true.
1{
2 "definition": "tile/text",
3 "meta": {
4 "forEach": "{!$attrs.amenities}",
5 "forItem": "$amenity",
6 "if": "{!$amenity.isAvailable}"
7 },
8 "attributes": {
9 "text": "{!$amenity.name}",
10 "variant": "body"
11 }
12}In this example:
meta.forEachiterates over the items inamenities.$amenityrepresents the current item.meta.ifevaluates$amenity.isAvailablefor the current item.- The component renders for the current item only when
isAvailableevaluates totrue.
Reference a Widget-Level Attribute in the Condition
When the meta.if condition references a widget-level attribute (such as {!$attrs.showAmenities}) instead of the scoped forItem variable, the condition evaluates once for the entire collection. As a result, the whole list either renders or is hidden—rather than being evaluated per item.
This example renders the entire list of amenities only when the widget-level showAmenities attribute evaluates to true.
1{
2 "definition": "tile/text",
3 "meta": {
4 "forEach": "{!$attrs.amenities}",
5 "forItem": "$amenity",
6 "if": "{!$attrs.showAmenities}"
7 },
8 "attributes": {
9 "text": "{!$amenity.name}",
10 "variant": "body"
11 }
12}In this example:
meta.ifevaluates the widget-level{!$attrs.showAmenities}attribute, not a property of the current item.- Because the condition doesn’t reference the
forItemvariable ($amenity), it’s evaluated once for the whole collection. - If
showAmenitiesevaluates totrue, all amenities render. If it evaluates tofalse, none render.
The scope of the meta.if condition determines the rendering behavior. When the condition references the forItem variable (such as $amenity.isAvailable), it’s evaluated per item. When it references a widget-level attribute (such as $attrs.showAmenities), it’s evaluated once for the entire collection.
Note
See Also
Beta Feature