Calculated properties specification
TypeScript type: CalculatedPropertiesSpecification.
This content modifier allows including additional calculated properties into the content.
Attributes
Attribute: label
Specifies label of the calculated property. Supports localization.
|
|
Type |
string |
Is Required |
Yes |
// There's a content rule for returning content of given `bis.Subject` instance. The produced content is customized to
// additionally have a calculated "My Calculated Property" property.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "Content",
specifications: [
{
specType: "SelectedNodeInstances",
calculatedProperties: [
{
label: "My Calculated Property",
value: `123`,
},
],
},
],
},
],
};

Attribute: value
Defines an expression to calculate the value. The expression can use ECInstance
and Ruleset Variables symbol contexts.
// There's a content rule for returning content of given `bis.GeometricElement3d` instance. The produced content is
// customized to additionally have a calculated "Element Volume" property whose value is calculated based on
// element's `BBoxHigh` and `BBoxLow` property values.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "Content",
specifications: [
{
specType: "SelectedNodeInstances",
calculatedProperties: [
{
label: "Element Volume",
value: "(this.BBoxHigh.x - this.BBoxLow.x) * (this.BBoxHigh.y - this.BBoxLow.y) * (this.BBoxHigh.z - this.BBoxLow.z)",
},
],
},
],
},
],
};

Attribute: type
Specifies return type of the calculated property. Presentation library tries to map the type of the evaluated expression to the requested type.
If evaluated expression cannot be converted to the specified type, an error will be thrown when requesting content with the error
message: Calculated property evaluated to a type that couldn't be converted to requested type
. For example, if the specified type is dateTime
for the expression 2 * 2
,
an error would be thrown, since evaluated expression would have a type of int
.
|
|
Type |
"string" | "int" | "long" | "dateTime" | "boolean" | "bool" | "double" |
Is Required |
No |
Default Value |
"string" |
// There's a content rule for returning content of given `bis.GeometricElement3d` instance. The produced content is customized to
// additionally have a calculated "My Calculated Property" property with a custom return "type"
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "Content",
specifications: [
{
specType: "SelectedNodeInstances",
calculatedProperties: [
{
label: "My Calculated Property",
value: "2+2",
type: "int"
},
],
},
],
},
],
};

Attribute: categoryId
The attribute allows moving the property into a different category. There are several options:
Reference a category by ID used in PropertyCategorySpecification
in the current context.
The current context contains categories specified in the same content specification or
content modifiers that are applied on the same or base ECClass as this property specification.
Move to DefaultParent
category. This is useful when using with related properties, to
avoid putting them inside a special related class category and instead show them next to properties of the source class.
Move to Root
category. This is useful when using with related properties, to
avoid putting them inside a special related class category and instead show them in the root category.
See property categorization page for more details.
|
|
Type |
string | CategoryIdentifier |
Is Required |
No |
Default Value |
No override |
// There's a content rule for returning content of given `bis.Subject` instance. The produced content is customized to
// additionally have a calculated "My Calculated Property" property that is placed into a custom category by
// assigning it a `categoryId`.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "Content",
specifications: [
{
specType: "SelectedNodeInstances",
propertyCategories: [
{
id: "custom-category",
label: "Custom",
},
],
calculatedProperties: [
{
label: "My Calculated Property",
value: "123",
categoryId: "custom-category",
},
],
},
],
},
],
};

Attribute: renderer
Custom property renderer specification that allows assigning a custom value renderer to be used in UI. The
specification is used to set up Field.renderer for this property and it's up to the UI component to make sure
appropriate renderer is used to render the property.
See Custom property value renderers page for a list of available renderers or how to register a custom one.
// There's a content rule for returning content of given `bis.Subject` instance. The produced content is customized to
// additionally have a calculated "My Calculated Property" property with a custom "my-renderer" renderer.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "Content",
specifications: [
{
specType: "SelectedNodeInstances",
calculatedProperties: [
{
label: "My Calculated property",
value: "123",
renderer: {
rendererName: "my-renderer",
},
},
],
},
],
},
],
};
// Ensure the calculated property field is assigned the "my-renderer" renderer
const content = await Presentation.presentation.getContentIterator({
imodel,
rulesetOrId: ruleset,
keys: new KeySet([{ className: "BisCore:Subject", id: "0x1" }]),
descriptor: {},
});
expect(content!.descriptor.fields).to.containSubset([
{
label: "My Calculated property",
renderer: {
name: "my-renderer",
},
},
]);
Attribute editor
Custom property editor specification that allows assigning a custom value editor
to be used in UI.
// There's a content rule for returning content of given `bis.Subject` instance. The produced content is customized to
// additionally have a calculated "My Calculated Property" property with a custom "my-editor" editor.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "Content",
specifications: [
{
specType: "SelectedNodeInstances",
calculatedProperties: [
{
label: "My Calculated property",
value: "123",
editor: {
editorName: "my-editor",
},
},
],
},
],
},
],
};
// Ensure the calculated property field is assigned the "my-editor" editor
const content = await Presentation.presentation.getContentIterator({
imodel,
rulesetOrId: ruleset,
keys: new KeySet([{ className: "BisCore:Subject", id: "0x1" }]),
descriptor: {},
});
expect(content!.descriptor.fields).to.containSubset([
{
label: "My Calculated property",
editor: {
name: "my-editor",
},
},
]);
Attribute: priority
Assign a custom Field.priority to the property. It's up to the UI component to make sure that priority
is respected - properties with higher priority should appear before or above properties with lower priority.
|
|
Type |
number |
Is Required |
No |
Default Value |
1000 |
// There's a content rule for returning content of given `bis.Subject` instance. The produced content is customized to
// additionally have a "My Calculated Property" property with priority set to `9999`. This should make the property
// appear at the top in the UI, since generally properties have a priority of `1000`.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "Content",
specifications: [
{
specType: "SelectedNodeInstances",
calculatedProperties: [
{
label: "My Calculated Property",
value: `123`,
priority: 9999,
},
],
},
],
},
],
};
priority: 9999 |
priority: -9999 |
 |
 |
Attribute: extendedData
A map of ECExpressions whose evaluation results are used as extended data values.
|
|
Type |
{ [key: string]: ECExpression } |
Is Required |
No |
// There's a content rule for returning content of given `bis.Subject` instance. The produced content is customized to
// additionally have a calculated "My Calculated Property" property that has extended data assigned.
const ruleset: Ruleset = {
id: "example",
rules: [
{
ruleType: "Content",
specifications: [
{
specType: "SelectedNodeInstances",
calculatedProperties: [
{
label: "My Calculated Property",
value: "123",
extendedData: {
extendedDataInt: "2*2",
extendedDataStr: "\"xxx\""
},
},
],
},
],
},
],
};
// Ensure that the calculated property field has `extendedData` items assigned to it.
const content = await Presentation.presentation.getContentIterator({
imodel,
rulesetOrId: ruleset,
keys: new KeySet([{ className: "BisCore:Subject", id: "0x1" }]),
descriptor: {},
});
expect(content!.descriptor.fields).to.containSubset([
{
label: "My Calculated Property",
extendedData: {
extendedDataInt: 4,
extendedDataStr: "xxx"
},
},
]);