Extended data rule

TypeScript type: ExtendedDataRule.

Extended data rule is used to inject some arbitrary data into presentation data objects (nodes, content records). See Extended data usage page for information on how to use injected data in our UI components.

Typical use case

Table is showing Models and Elements polymorphically and application wants to handle these two types of rows differently.

Problem

Each content record knows only it's exact ECClass, but there's no way to tell if that class is a subclass of a Model or an Element.

Solution

Extended data rule can be used to inject some flag that tells whether table row represents a model or an element. The flag can then be accessed on the frontend and used to determine how the row should be handled.

Attributes

Name Required? Type Default
Filtering
requiredSchemas No RequiredSchemaSpecification[] []
condition No ECExpression ""
Extended Data
items Yes { [key: string]: ECExpression }

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 rule that returns content of given input instances. Also there is an extended data rule
// to add additional data for `bis.ExternalSourceAspect` instances content. `bis.ExternalSourceAspect` 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: "Content",
      specifications: [
        {
          specType: "SelectedNodeInstances",
        },
      ],
    },
    {
      ruleType: "ExtendedData",
      requiredSchemas: [{ name: "BisCore", minVersion: "1.0.2" }],
      condition: 'ThisNode.IsOfClass("ExternalSourceAspect", "BisCore")',
      items: {
        iconName: '"external-source-icon"',
      },
    },
  ],
};

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 ruleset has root node rule that returns custom nodes "A" and "B". Also there is an extended data rule
// to add additional data to "B" nodes.
const ruleset: Ruleset = {
  id: "example",
  rules: [
    {
      ruleType: "RootNodes",
      specifications: [
        {
          specType: "CustomNode",
          label: "A",
          type: "A",
        },
        {
          specType: "CustomNode",
          label: "B",
          type: "B",
        },
      ],
    },
    {
      ruleType: "ExtendedData",
      condition: 'ThisNode.Type = "B"',
      items: {
        iconName: '"custom-icon"',
      },
    },
  ],
};
// Ensure only "B" node has `extendedData` property.
const nodes = await Presentation.presentation
  .getNodesIterator({
    imodel,
    rulesetOrId: ruleset,
  })
  .then(async (x) => collect(x.items));
expect(nodes)
  .to.be.lengthOf(2)
  .and.to.containSubset([
    {
      label: { displayValue: "A" },
      extendedData: undefined,
    },
    {
      label: { displayValue: "B" },
      extendedData: {
        iconName: "custom-icon",
      },
    },
  ]);

Attribute: items

A map of ECExpressions whose evaluation results are used as extended data values.

Type { [key: string]: ECExpression }
Is Required Yes
// The ruleset has root node rule that returns custom "A" node. Also there is an extended data rule
// to add additional data to node.
const ruleset: Ruleset = {
  id: "example",
  rules: [
    {
      ruleType: "RootNodes",
      specifications: [
        {
          specType: "CustomNode",
          label: "A",
          type: "A",
        },
      ],
    },
    {
      ruleType: "ExtendedData",
      items: {
        iconName: '"custom-icon"',
        fontColor: '"custom-font-color"',
        typeDescription: '"Node is of type " & ThisNode.Type',
      },
    },
  ],
};
// Ensure node has `extendedData` property containing items defined in rule.
const nodes = await Presentation.presentation
  .getNodesIterator({
    imodel,
    rulesetOrId: ruleset,
  })
  .then(async (x) => collect(x.items));
expect(nodes)
  .to.be.lengthOf(1)
  .and.to.containSubset([
    {
      label: { displayValue: "A" },
      extendedData: {
        iconName: "custom-icon",
        fontColor: "custom-font-color",
        typeDescription: "Node is of type A",
      },
    },
  ]);

Last Updated: 03 April, 2024