Child node rule

TypeScript type: ChildNodeRule.

Child node rules are used to define child nodes in a hierarchy.

The rules have two types of attributes: for defining placement and for defining branch content. Placement attributes can make the whole rule return no nodes (e.g. when condition evaluates to false). In that case branch content attributes have no effect.

Attributes

Name Required? Type Default
Placement attributes
condition No ECExpression ""
requiredSchemas No RequiredSchemaSpecification[] []
priority No number 1000
onlyIfNotHandled No boolean false
stopFurtherProcessing No boolean false
Branch content attributes
specifications No ChildNodeSpecification[] []
customizationRules No CustomizationRule[] []
subConditions No SubCondition[] []

Attribute: condition

Defines a condition which needs to be met in order for the rule to be used. The condition is an ECExpression which has to evaluate to a boolean value.

Type ECExpression
Is Required No
Default Value ""

The most commonly used symbols are:

  • ParentNode — refers to the parent node. This is often used to create child nodes under specific parents.

    // This ruleset defines a tree with node "A" at the top and node "B" as child of "A".
    const ruleset: Ruleset = {
      id: "example",
      rules: [{
        ruleType: RuleTypes.RootNodes,
        specifications: [{
          specType: ChildNodeSpecificationTypes.CustomNode,
          type: "A",
          label: "A",
        }],
      }, {
        ruleType: RuleTypes.ChildNodes,
        condition: `ParentNode.Type = "A"`,
        specifications: [{
          specType: ChildNodeSpecificationTypes.CustomNode,
          type: "B",
          label: "B",
        }],
      }],
    };
    

    Example of using ParentNode symbol in rule condition

  • Ruleset variables — values that can be set and changed at runtime to affect rule outcomes.

    // This ruleset defines two rules that can be enabled or disabled by setting variable DISPLAY_A_NODES and
    // DISPLAY_B_NODES values.
    const ruleset: Ruleset = {
      id: "example",
      rules: [{
        ruleType: RuleTypes.RootNodes,
        condition: `GetVariableBoolValue("DISPLAY_A_NODES")`,
        specifications: [{
          specType: ChildNodeSpecificationTypes.CustomNode,
          type: "A",
          label: "A",
        }],
      }, {
        ruleType: RuleTypes.RootNodes,
        condition: `GetVariableBoolValue("DISPLAY_B_NODES")`,
        specifications: [{
          specType: ChildNodeSpecificationTypes.CustomNode,
          type: "B",
          label: "B",
        }],
      }],
    };
    
    Ruleset variable values Result
    DISPLAY_A_NODES = false
    DISPLAY_B_NODES = false
    Example of using ruleset variables in rule condition
    DISPLAY_A_NODES = false
    DISPLAY_B_NODES = true
    Example of using ruleset variables in rule condition
    DISPLAY_A_NODES = true
    DISPLAY_B_NODES = true
    Example of using ruleset variables in rule condition

Attribute: requiredSchemas

A list of ECSchema requirements that need to be met for the rule to be used.

Type RequiredSchemaSpecification[]
Is Required No
Default Value []
// The ruleset has one root node rule that returns `bis.ExternalSourceAspect` instances. The
// ECClass was introduced in BisCore version 1.0.2, so the rule needs a `requiredSchemas` attribute
// to only use the rule if the version meets the requirement.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    ruleType: RuleTypes.RootNodes,
    requiredSchemas: [{ name: "BisCore", minVersion: "1.0.2" }],
    specifications: [{
      specType: ChildNodeSpecificationTypes.InstanceNodesOfSpecificClasses,
      classes: [{
        schemaName: "BisCore",
        classNames: ["ExternalSourceAspect"],
      }],
    }],
  }],
};

Attribute: priority

Defines the order in which rules are handled, higher number means the rule is handled first. If priorities are equal, the rules are handled in the order they're defined. The attribute may be especially useful when combined with onlyIfNotHandled attribute.

Type number
Is Required No
Default Value 1000
// The ruleset has two root node rules that return nodes "A" and "B" respectively. The rules
// have different priorities and higher priority rule is handled first - it's node appears first.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    ruleType: RuleTypes.RootNodes,
    priority: 1,
    specifications: [{
      specType: ChildNodeSpecificationTypes.CustomNode,
      type: "A",
      label: "A",
    }],
  }, {
    ruleType: RuleTypes.RootNodes,
    priority: 2,
    specifications: [{
      specType: ChildNodeSpecificationTypes.CustomNode,
      type: "B",
      label: "B",
    }],
  }],
};

Example of using priority attribute

Attribute: onlyIfNotHandled

When true, the rule takes effect only when all other child node rules with higher priority are ruled out. This attribute is most useful for defining fallback rules.

Type boolean
Is Required No
Default Value false
// The ruleset has two root node rules that return nodes "A" and "B" respectively. The "A" rule has
// lower priority and `onlyIfNotHandled` attribute, which allows it to be overriden by higher priority rules.
// The "B" rule does exactly that.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    ruleType: RuleTypes.RootNodes,
    priority: 1,
    onlyIfNotHandled: true,
    specifications: [{
      specType: ChildNodeSpecificationTypes.CustomNode,
      type: "A",
      label: "A",
    }],
  }, {
    ruleType: RuleTypes.RootNodes,
    priority: 2,
    specifications: [{
      specType: ChildNodeSpecificationTypes.CustomNode,
      type: "B",
      label: "B",
    }],
  }],
};

Example of using onlyIfNotHandled attribute

Attribute: stopFurtherProcessing

Stop processing rules that have lower priority. Used in cases when recursion suppression is needed.

Note: If this flag is set, specifications and subConditions are not processed.

Type boolean
Is Required No
Default Value false

Attribute: specifications

A list of hierarchy specifications that define what nodes are going to be returned. There are 4 types of specifications:

  • Instance nodes of specific classes specification returns nodes for instances of given ECClass(-es) without attempting to join them to the parent node using some relationship or attribute. This is mostly useful when specifying root nodes.
  • Related instance nodes specification returns nodes for instances that are related to the parent instance node through given ECRelationship. This is the most commonly used specification to create child nodes.
  • Custom query instance nodes specification returns nodes for instances based on a given ECSQL query. Generally, this specification is rarely needed as majority of cases can be handled by Instance nodes of specific classes specification which is more performant and easier to set up.
  • Custom node specification returns a single node that's not based on data in the iModel. Instead, the specification itself specifies all the attributes (type, label, description, image, etc.) of the node.

Multiple specifications can contribute to the same branch by specifying multiple specifications in a single rule or specifying multiple rules that match the same parent node.

Note: grouping and sorting is done at specification level which means nodes generated from different specifications do not get grouped and sorted together.

Type ChildNodeSpecification[]
Is Required No
Default Value []

Attribute: customizationRules

A list of customization rules that apply only to nodes produced by this rule. Specifying customization rules at this level (as opposed to specifying them at ruleset root level) helps them isolate from other rules, which is useful when same type of nodes need to be customized differently based on what rule creates them.

Type CustomizationRule[]
Is Required No
Default Value []
// The ruleset has a global label override rule and two root node rules that return nodes "A" and "B"
// respectively. The "B" rule has a label override of its own.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    // This label override applies to all nodes in the hierarchy
    ruleType: RuleTypes.LabelOverride,
    label: `"Global: " & ThisNode.Label`,
  }, {
    ruleType: RuleTypes.RootNodes,
    specifications: [{
      specType: ChildNodeSpecificationTypes.CustomNode,
      type: "A",
      label: "A",
    }],
  }, {
    ruleType: RuleTypes.RootNodes,
    specifications: [{
      specType: ChildNodeSpecificationTypes.CustomNode,
      type: "B",
      label: "B",
    }],
    customizationRules: [{
      // This label override applies only to nodes created at its scope and takes
      // precedence over the global rule
      ruleType: RuleTypes.LabelOverride,
      label: `"Nested: " & ThisNode.Label`,
    }],
  }],
};

Example of using customizationRules attribute

Attribute: subConditions

A list of sub-rules which share placement attributes and nested customization rules of the hierarchy rule. This means the attributes of hierarchy rule are still in effect and the sub-rules can add additional condition of their own.

Type SubCondition[]
Is Required No
Default Value []
// The ruleset has a root node rule with a schemas requirement and 2 sub-conditions. The latter are only used if schemas
// requirement is met. Each sub-condition can have additional conditions.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    ruleType: RuleTypes.RootNodes,
    // the schemas requirement gets applied to both sub-conditions
    requiredSchemas: [{ name: "BisCore", minVersion: "1.0.1" }],
    subConditions: [{
      condition: `TRUE`,
      specifications: [{
        specType: ChildNodeSpecificationTypes.CustomNode,
        type: "A",
        label: "A",
      }],
    }, {
      condition: `FALSE`,
      specifications: [{
        specType: ChildNodeSpecificationTypes.CustomNode,
        type: "B",
        label: "B",
      }],
    }],
  }],
};

Example of using subConditions attribute

Last Updated: 20 May, 2022