Skip to main content

Expressions

An expression is a short calculation over your shopper's choices. The same language works everywhere 3D Bits takes one, so what you learn in a price formula also works in a condition.

length * 12000 + 400

On a catamaran with a Length control, that charges 12,000 for each metre plus 400. Change the length and the result follows.

Where you can use one​

You write it inWhat it decides
A price formula, in its Expression fieldAn amount of money
A part, in Quantity expression (optional)How many of a part the configuration needs
A range or number control, in Min expression, Max expression and Step expressionThe limits of a slider, from other choices
A parameter binding, in its Expression fieldA number in the scene, such as the position of a part
A condition, in Logical expressionWhether something applies

Naming a control​

Write a control by its key, which you see in the control's panel. A key made of letters, digits and underscores, not starting with a digit, can stand alone, like length. For any other key, use input("key").

A name no control has counts as 0.

A multi-select has no single value, so ask about its choices with selectedCount, contains and includes.

Text goes in single or double quotes: helm_style == "sport".

In a condition, 0, empty text and false do not hold, and anything else does.

Operators​

OperatorWhat it doesExampleGives
+ - * /Add, subtract, multiply and divide. Dividing by zero gives 0.length * 12000 + 400240400
%The remainder after dividing.length % 32
( )Work this part out first.(length + 5) * 250
== !=Equal to, not equal to.length == 20true
> >= < <=Greater than, at least, less than, at most.length >= 25false
&&Both sides hold.length >= 20 && beam > 10true
||At least one side holds.length > 22 || beam > 10true
!The opposite.!(length > 22)true
? :If the first part holds the second, otherwise the third.length > 22 ? 3 : 22

Functions​

FunctionWhat it doesExampleGives
min(a, b, ...)The smallest value.min(length, 18)18
max(a, b, ...)The largest value.max(length, 22.5)22.5
round(a)To the nearest whole number.round(beam)10
ceil(a)Up to the next whole number.ceil(beam)11
floor(a)Down to the previous whole number.floor(beam)10
abs(a)The value without its sign.abs(length - 25)5
clamp(a, low, high)Keeps a value between two limits.clamp(length, 15, 18)18
input("key")A control's value by its key, for a key that holds anything but letters, digits and underscores, or starts with a digit.input("length") + 121
selectedCount("key")How many choices of a multi-select are picked.selectedCount("on_deck")2
contains("key", "text")Whether a multi-select has this choice picked, or a text value holds this text, whatever the case.contains("on_deck", "TENDER")true
includes("key", "text")The same as contains, with the case exact.includes("on_deck", "TENDER")false
prev("key", steps)The value a control held before. One step back is the default and works on every control. Past what is kept, the value it holds now.prev("length") == 15true
changed("key")Whether the control's value differs from the step before.changed("length")true
initial("key")The value a control started with on this page.initial("length") == 20true

History​

prev, changed and initial read what happened earlier, and they read it only in a logic rule that fires once, On change or On load. Anywhere else there is nothing to read: changed gives false, and prev and initial give the value the control holds now.

A rule that holds While matching is worked out afresh on every change, so it cannot ask what came before: such a rule is skipped, and on a project with pricing on publishing refuses it.

changed, initial and one step of prev work on every control. To reach further back, set History depth on the control you ask about: prev("length", 3) needs a depth of at least 2. Steps count every change to the configuration, not only this control's.

initial is what the control held when the page settled, so a configuration restored from a link or the cart counts as the start.

What a price can depend on​

A condition that decides a price is held to more than this page. Write it with the structured rows, not in Logical expression, and keep the history functions out of it. Publishing refuses one that is not, and names it. Publish blockers lists each case.

Where to go next​

Verified against the product in November 2026