Creating Component Configurations with dynamic values
C3 AI Platform comes with a UI component library that deeply integrates with the rest of your application, making it easy to fetch data for entities and metrics. All components also expose an UiSdlComponentDataSpec#advancedDataSpec, which allow you to configure a UI component to fetch from any backend type for extra flexibility. Learn More
Both mechanisms allow you to configure how the UI component fetches data, but in their simpler form, they are static configurations. At development time, you define which type and method to call to fetch data and C3 AI Platform generates code to perform that action.
But for some use cases you need support for dynamic value binding. As an example, let's say the user navigates to a page, and you want the data to be on that page be filtered by a page parameter specified in the URL of that page.
To implement this, you need a way to get the value of a page parameter and use it in the UI component data spec, which is used to display the data. When the page parameter has a different value, the component uses that value to filter data.
Context variables
Context variables are a configuration on the UI component dataSpec. They allow you to define a variable, specify where to get that value from, and then use that variable in other parts of the dataSpec.
In the example below, you use the contextVars configuration to define the name context variable, you then bind that variable to machine-name variable in the page parameter. Then you can use the newly declared name variable as part of the dataSpec for various fields input fields on the dataSpec. You can do so by referencing the field in curly braces like so: ${name}.
{
"type": "UiSdlConnected<UiSdlDataGrid>",
"component": {
"paginationConfig": {
"pageSize": 10,
"pagination": true
},
"dataSpec": {
"dataType": "SDLDemoMachine",
"filter": "name == '${name}'",
"actionName": "fetch",
"columnFields": [
{
"fieldName": "id",
"label": "Id"
},
{
"fieldName": "name",
"label": "Name"
}
],
"contextVars": {
"name": {
"type": "UiSdlPageParam",
"path": "machine-name"
}
}
}
}
}Requesting data when context variables change
There a few ways contextVars can be configured to request new data for your application.
Ignoring context variable data requests based on resolved value
You can determine if you want the context variable resolution to trigger a data request based on whether or not the resolved context variables for the UiSdlComponentDataSpec values are undefined. This can be done at two levels, either for individual components through WithContextVars#sendRequestWithFalsyContextVars or at the application level through UiSdlConfig#ignoreRequestsWithFalsyContextVars.
WithContextVars#sendRequestWithFalsyContextVars allows a single UiSdlComponentDataSpec to determine if it will send the data request with an undefined resolution. If it is true, the data request will always be sent whether or not all context variables have resolved to an actual value. If it is false, the data request will only be sent when all of the context variables have resolved to actual values.
UiSdlConfig#ignoreRequestsWithFalsyContextVars is a configuration to set the same behavior as WithContextVars#sendRequestWithFalsyContextVars for many components at the same time. This field is a map of strings representing UiSdlRoute#targetModuleName, which is also the first half of each component's id, to a boolean that is true if all components that use that targetModuleName for the entire application should only request data with defined context variable resolutions and false if the context variables' resolution can request data even when they resolve to undefined.
If both WithContextVars#sendRequestWithFalsyContextVars and UiSdlConfig#ignoreRequestsWithFalsyContextVars are configured to affect a component's UiSdlComponentDataSpec then the configuration from WithContextVars#sendRequestWithFalsyContextVars will be used.
Using the undefined check used by these configurations is useful if you know that the contextVars of your components will always resolve to something. In that case, you can always avoid extra network requests during the transition stage of the component when the contextVars are not fully resolved yet.
Ignoring context variable data requests based on number of resolutions
You can also determine if a context variable's resolution should happen based on number of resolutions. With this form of calibration, you can either make it ignore the first resolution (no matter what it resolves to) via UiSdlComponentDataSpec#ignoreFirstContextVarResolution or ignore all resolutions via UiSdlComponentDataSpec#ignoreAllContextVarResolution.
Using the number based approach is useful if you are not sure that the contextVars will always be resolved to something other than undefined. A good use case for this would be when already using UiSdlComponentDataSpec#disableDataRequestOnFirstRender. Since contextVar related re-renders are considered separate from the "first render", ignoring the first contextVar resolution can allow you to not have any requests initially.
Recommendations
It is recommended to use UiSdlConfig#ignoreRequestsWithFalsyContextVars when every component for the application should behave the same way. This makes it much simpler to do a single configuration for every component using a single targetModuleName to behave the same.
It is generally recommended to use WithContextVars#sendRequestWithFalsyContextVars rather than UiSdlComponentDataSpec#ignoreFirstContextVarResolution since the latter has no opinion on the values that it is ignoring and could ignore a value that would be considered "valid" or allow through undefined. It is also recommended to use this in combination with UiSdlConfig#ignoreRequestsWithFalsyContextVars if a single component needs to behave differently from the rest.
It is recommended to use UiSdlComponentDataSpec#ignoreAllContextVarResolution when you would prefer to manually trigger the data request through UiSdlEpic or UiSdlEffectTrigger. One example where this is the default is UiSdlFormSubmitDataSpec, since it should only make the network request when a user explicitly submits the form, regardless of anything with the contextVars.
Context variables applied as default filters
Currently, context variables are applied as default as filters for the following components:
- UiSdlDiagramViewer
- UiSdlDateTimeRangeInput
- UiSdlCardList
- UiSdlDataGrid
- UiSdlGaugeChart
- UiSdlHistogram
- UiSdlCategoricalLineBarChart
- UiSdlArcMap
- UiSdlMap
- UiSdlMetricTile
- UiSdlAreaChart
This applies the Filter#intersects function by default and checks to see if the context variable is equal to the value specified within the context variable. In the example above, the default filter will generate a filter that looks like: intersects(name, '${name}').
If there is a filter field specified on the dataSpec similar to the example above, both filters will be applied in an and operation and will filter the data based on name == '${name}' && intersects(name, '${name}').
Limitations
Currently, context variables cannot be used to change the configuration of fields that affect how the API is configured. This means that context variables cannot be used as part of the dataType and actionName fields.
Context variables support inputs of type UiSdlDynamicValueSpecParam. See WithContextVars for more details.