Quantity Formatting
The iTwin.js offers two ways to format quantity values. The more primitive interface is found in the Formatter in core-quantity
package.
A more convenient interface to format and parse values is the QuantityFormatter in the core-frontend
package. It is limited to formatting and parsing values for a fixed set of quantity types.
More detailed explanation can be found at Quantity Formatting and Parsing.
QuantityFormatter
The QuantityFormatter class formats quantities for interactive tools, such as the different measure tools, and is used to parse strings back into quantity values. The QuantityFormatter is not used to format properties stored in the iModel, as that is work is done on the back-end via the Presentation layer, but the QuantityFormatter can be set to format values in the same unit system as that used by the back-end. There are four Unit Systems definitions that is shared between the back-end Presentation Manager and the front-end QuantityFormatter:
- "metric"
- "imperial"
- "usCustomary"
- "usSurvey"
QuantityType
There are nine built-in quantity types (see QuantityType). The QuantityFormatter defines default a formatting specification for each of these types per unit system. IModelApp initialization calls the QuantityFormatter initialization, during which FormatterSpec and ParserSpec for each quantity type are generated asynchronously. This allows caller to get these objects via synchronous calls. Any time the unit system is set, a format is overridden, or a units provider is assigned the cached specs are updated.
Custom quantity types that implement the CustomQuantityTypeDefinition interface may also be registered with the QuantityFormatter, see method registerQuantityType
. See example implementation of a custom type here.
Migrating from QuantityType to KindOfQuantity
Starting in iTwin.js 5.0, we encourage developers to move away from using QuantityType
, and to instead use KindOfQuantity
EC full names.
We encourage users to move away from QuantityType
in favor of KindOfQuantity
and by extension the FormatsProvider to retrieve formats, as it enables users to access a broader range of formatting capabilities. While QuantityType
was limited to a predefined set of nine built-in quantity types (e.g., Length, Angle, Area), the new FormatsProvider
approach allows users to define and retrieve formats dynamically, without being constrained to a fixed list. A FormatsProvider
is scalable, letting users work with formats defined in custom schemas, while a MutableFormatsProvider lets users add or override formats to fit specific project needs. More information on FormatsProvider
can be found in this learnings section.
Here is a table of replacements for each QuantityType
:
QuantityType | Actual KindOfQuantity (EC Full Name) |
---|---|
Length | AecUnits.LENGTH |
Angle | AecUnits.ANGLE |
Area | AecUnits.AREA |
Volume | AecUnits.VOLUME |
LatLong | AecUnits.ANGLE |
Coordinate | AecUnits.LENGTH |
Stationing | RoadRailUnits.STATION |
LengthSurvey | RoadRailUnits.LENGTH |
LengthEngineering | AecUnits.LENGTH |
AecUnits is a Common layer schema that will be present in many iModels. RoadRailUnits, a Discipline-Physical layer schema, contains Kind of Quantities used by Road & Rail schemas. More information on schemas and their different layers can be found in Bis Organization.
iModels might not have AecUnits or RoadRailUnits schemas included, in such cases developers can address this through integrating their tools/components to use a FormatsProvider
, and add the missing KindOfQuantity (and associated FormatProps) through that FormatsProvider, independent from schemas coming from iModels.
To support users with the migration, IModelApp
by default uses an internal QuantityTypeFormatsProvider that provides default formatProps
associated to each KindOfQuantity in the table above, ensuring formatProps will always be available for those Kind Of Quantities out of the box. We still strongly encourage developers to either implement their own FormatsProvider
or set a new SchemaFormatsProvider if possible and the application uses iModels.
We plan to deprecate QuantityType
during the iTwin.js 5.x lifecycle.
Overriding Default Formats
The QuantityFormatter
provides the method setOverrideFormats
which allows the default format to be overridden. These overrides may be persisted by implementing the UnitFormattingSettingsProvider interface in the QuantityFormatter. This provider can then monitor the current session to load the overrides when necessary. The class LocalUnitFormatProvider can be used to store settings in local storage and to maintain overrides by iModel as shown below:
This allows both the Presentation Unit System and the format overrides, set by the user, to stay in sync as the user opens different iModels.
AlternateUnitLabelsProvider
The QuantityFormatter provides a default set of alternate unit labels which are used when parsing strings to quantities. The interface AlternateUnitLabelsProvider defines how alternate units are defined. One commonly specified alternate label is "^" to specify degrees, much easier to type than trying to figure out how to enter the default label for degree, "°".
To add custom labels use QuantityFormatter.addAlternateLabels as shown in the examples below:
Units Provider
A units provider is used to define all available units and provides conversion factors between units. The QuantityFormatter has a default units provider BasicUnitsProvider that only defines units needed by the set of QuantityTypes the formatter supports. Most iModels contain a Units
schema. If this is the case, a SchemaUnitProvider may be defined when an IModel is opened. The parent application must opt-in to using an iModel specific UnitsProvider using the following technique:
If errors occur while configuring the units provider, they are caught within the QuantityFormatter.setUnitsProvider method, and the code reverts back to the [BasicUnitsProvider] described above.
Measure Tools
Below are a list of a few of the delivered Measure Tools and the QuantityTypes they use.
MeasureDistanceTool
- Length - QuantityType.Length
- Coordinates - QuantityType.Coordinate
MeasureLocationTool
- Coordinates - QuantityType.Coordinate
- Spatial Coordinates - QuantityType.LatLong
- Height - QuantityType.Coordinate
MeasureAreaByPointsTool
- Perimeter - QuantityType.Length
- Coordinates - QuantityType.Coordinate
- Area - QuantityType.Area
MeasureElementTool
- Accumulated Length - QuantityType.Length
- Accumulated Area - QuantityType.Area
- Volume - QuantityType.Volume
- Centroid - QuantityType.Coordinate
Formatting Example
Below is example converting totalDistance, in persistence units of meters, to the format specified for QuantityType.Length
in the current unit system. The
formatterSpec contains all the unit conversions necessary to convert the persistence unit to the units specified in the FormatProps.
If the unit system is "imperial"
then the following format (FormatProps) would typically be applied. This format specifies to create a string in the format of X'-X"
, where inches would be shown to the nearest 1/8 inch.
If the unit system is "metric"
then the following format (FormatProps) would typically be applied. This format specifies to create a string in the format of Xm
, where meters would be shown to nearest .0001 precision.
Parsing Example
Below is an example of parsing the string 24^34.5'
into an angle in the persistence unit of radian. The parserSpec that is generated
contains all the unit conversions necessary to convert from any angular unit to radians.
The persistence unit is predefined by the QuantityType definition in the QuantityFormatter. For QuantityType.Angle
the following is used.
The default angle format (FormatProps) is used during parsing to supply the default set of labels to look for in the string. Any alternate unit labels, as provided by AlternateUnitLabelsProvider, will also be checked during the parsing operation. The alternate unit label of "^" is commonly set up for QuantityType.Angle making it easier to build the angle string with standard keyboard keys. The default format for QuantityType.Angle when the unit system is set to "imperial" is shown below.
SchemaUnitProvider
It is possible to retrieve Units
from schemas stored in IModels. The new SchemaUnitProvider can now be created and used by the QuantityFormatter or any method in the core-quantity
package that requires a UnitsProvider. Below is an example, extracted from ui-test-app
, that demonstrates how to register the IModel-specific UnitsProvider
as the IModelConnection is created. This new provider will provide access to a wide variety of Units that were not available in the standalone BasicUnitsProvider
.
IMPORTANT: the
core-quantity
package is not a peer dependency of theecschema-metadata
package
Quantity Package
The Quantity Package @itwinjs\core-quantity
defines interfaces and classes used to specify formatting and provide information needed to parse strings into quantity values. It should be noted that most of the classes and interfaces used in this package are based on the native C++ code that formats quantities on the back-end. The purpose of this frontend package was to produce the same formatted strings without requiring constant calls to the backend to do the work.
Common terms used across this page are explained at Quantity Formatting and Parsing.
Formatting Examples
Below are a couple examples of formatting values using methods directly from the @itwinjs/core-quantity package. The UnitsProvider used in the examples below can be seen in TestHelper. As discussed above, there are UnitProviders that can read units defined in the active iModel, and there is a basic provider that can be used when no iModel is open.
Numeric Format
The example below uses a simple numeric format and generates a formatted string with 4 decimal place precision. For numeric formats there is no conversion to other units; the unit passed in is the unit returned with the unit label appended if "showUnitLabel" trait is set.
Composite Format
For the composite format below, we provide a unit in meters and produce a formatted string showing feet and inches to a precision of 1/8th inch.
Parsing Values
AlternateUnitLabelsProvider
The AlternateUnitLabelsProvider interface allows users to specify a set of alternate labels which may be encountered during parsing of strings. By default only the input unit label and the labels of other units in the same Unit Family/Phenomenon, as well as the label of units in a Composite format are used.
Mathematical Operation Parsing
The quantity formatter supports parsing mathematical operations. The operation is solved, formatting every values present, according to the specified format. This makes it possible to process several different units at once.
Limitations
There are corner cases and rules we've established surrounding use of math operations, explained further in Limitations.
Usage
The parsing of mathematical operations is disabled by default. To enable it, you can override the default QuantityFormatter. Ex :
Last Updated: 07 June, 2025