Ruleset variables
Ruleset Variables is a new name for now deprecated User Settings concept.
Presentation rulesets have a concept called ruleset variables whose purpose is to allow modifying ruleset behavior during the session without having to change the ruleset itself. The values of ruleset variables can be accessed using ECExpressions in:
- Rule conditions (example).
- Instance filters (example).
- ECExpressions-based values, like LabelOverride.label (example).
The advantages of using ruleset variables over values hardcoded into the ruleset are:
When used for creating a hierarchy, changing a ruleset variable causes only affected parts of the hierarchy to be re-created. Changing a rule in a ruleset causes the whole hierarchy to be re-created.
It's much more convenient and effective to pass a large number of IDs through a ruleset variable than it is to hardcode them into a ruleset. Ruleset variables are sent to the backend separately from the ruleset and that allows us to compress them when needed.
Using variables in rule condition
Using a ruleset variable in rule condition allows enabling and disabling specific rules based on something that can't be determined at the point of creating the ruleset, e.g. a user action.
The below example creates either a models' or an elements' hierarchy based on the value of ruleset variable.
By default the ruleset value is not set, which means neither of the two root node rules pass the condition. The result is empty hierarchy:
// The ruleset has two root node rules - one for models and one for elements. The one actually used
// depends on the value of `TREE_TYPE` ruleset variable, which can be changed without modifying the ruleset itself.
const ruleset: Ruleset = {
id: "test",
rules: [
{
ruleType: "RootNodes",
condition: `GetVariableStringValue("TREE_TYPE") = "models"`,
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["Model"] },
arePolymorphic: true,
},
],
},
{
ruleType: "RootNodes",
condition: `GetVariableStringValue("TREE_TYPE") = "elements"`,
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["Element"] },
arePolymorphic: true,
},
],
},
],
};
Setting the ruleset value to models
creates a models' hierarchy:
await Presentation.presentation.vars(ruleset.id).setString("TREE_TYPE", "models");
Setting the ruleset value to elements
creates an elements' hierarchy:
await Presentation.presentation.vars(ruleset.id).setString("TREE_TYPE", "elements");
Using variables in instance filter
Using a ruleset variable in instance filter allows filtering instances at query time. This is useful when the filtering criteria depends on user actions.
The below example shows a hierarchy of elements grouped by class. When the element-ids
variable is not set, the whole hierarchy is displayed. When the value is set to specific element IDs, the hierarchy is created only for those elements.
By default the ruleset value is not set - a hierarchy for all elements is created:
// The ruleset has a root node rule which loads all bis.Element instances, optionally filtered
// by ECInstanceId. The filter is controlled through `ELEMENT_IDS` ruleset variable.
const ruleset: Ruleset = {
id: "test",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["Element"] },
arePolymorphic: true,
instanceFilter: `NOT HasVariable("ELEMENT_IDS") OR GetVariableIntValues("ELEMENT_IDS").AnyMatch(id => id = this.ECInstanceId)`,
},
],
},
],
};
Setting the ruleset value to specific IDs creates the hierarchy only for specific elements:
await Presentation.presentation.vars(ruleset.id).setId64s("ELEMENT_IDS", ["0x1", "0x74", "0x40"]);
Clearing the ruleset value brings us back to the initial unfiltered view:
await Presentation.presentation.vars(ruleset.id).unset("ELEMENT_IDS");
Using variables in ECExpression-based value
Using a ruleset variable in ECExpression-based value makes the value customizable by users.
The below example shows a hierarchy that loads Spatial View Definition elements as root nodes. By default, when prefix
variable is not set, node labels are created from CodeValue
property of the element. When the prefix
variable is set, it's value is used as a prefix for node labels.
By default the ruleset value is not set - CodeValue property value is used as the label:
// The ruleset has a root node rule which loads all bis.SpatialViewDefinition instances. There's
// also a label customization rule which optionally prefixes node labels with a ruleset variable value and
// an instance label override rule to clear default BIS label override rules. The prefix is
// controlled through the `PREFIX` ruleset variable.
const ruleset: Ruleset = {
id: "test",
rules: [
{
ruleType: "RootNodes",
specifications: [
{
specType: "InstanceNodesOfSpecificClasses",
classes: { schemaName: "BisCore", classNames: ["SpatialViewDefinition"] },
arePolymorphic: true,
groupByClass: false,
groupByLabel: false,
},
],
},
{
ruleType: "LabelOverride",
label: `IIF(HasVariable("PREFIX"), GetVariableStringValue("PREFIX") & " " & this.CodeValue, this.CodeValue)`,
},
{
ruleType: "InstanceLabelOverride",
class: { schemaName: "BisCore", className: "SpatialViewDefinition" },
values: [],
},
],
};
Setting the ruleset variable value makes it appear in front of every node's label:
await Presentation.presentation.vars(ruleset.id).setString("PREFIX", "test");
Last Updated: 13 May, 2024