Build UIControls in code (Builder API)
In addition to fetching UIControls from the backend, you can construct a complete UIControls object in code using the exported builder utilities.
If you are new to the concept, first see UIControls to learn what the structure represents. The builders simply help you produce that same structure fluently.
Quick overview
- Use UiControlsInitRequestBuilder to build the Request section
- Combine InputValueBuilder + InputParameterFloatBuilder / InputParameterStringBuilder to define fields
- Group fields with InputParameterCategoryBuilder inside InputParameterCategoryGroupBuilder
- Wrap everything into an InputParameterSetBuilder and finally UiControlsInitResponseBuilder
Exports (quick reference)
| Export | Kind | Purpose | Common methods (subset) | Produces |
|---|---|---|---|---|
| UiControlsInitRequestBuilder | builder | Build the Request object used in UIControls.Request | withProductIds, withProductGroupIds, withProductFamilyIds, withScopeSystem, withInterfaceI18n, withCalculationI18n | InitRequest |
| UiControlsInitResponseBuilder | builder | Assemble the final UIControls response structure | withRequest, withCalcRequestURL, addInputParameterSet, addAccessoryCategory, addResultTableType, build | UIControls |
| InputParameterSetBuilder | builder | Top-level set holding category groups | withKey, withName, withOrder, addCategoryGroup, build | InputParameterSet |
| InputParameterCategoryGroupBuilder | builder | Holds one or more categories within a set | withKey, withName, withOrder, withLength, addCategory, build | CategoryGroup |
| InputParameterCategoryBuilder | builder | Holds input fields, calculated floats and dependencies | withGroupKey, withGroupName, withGroupOrder, addInputValue, addCalculatedFloat, addDependency, build | Category |
| InputValueBuilder | builder | Defines a single field (float/string/bool) and general props | float(), string(), bool(), withVisible, withDisplayOn, withFieldType, withFloat, withString, build | InputValue |
| InputParameterFloatBuilder | builder | Float-specific metadata (units, min/max/default/step) | withUnitType, withUnit, withMinPimValue, withMaxPimValue, withDefaultPimValue, withStepSizePimValue, withDecimals, build | FloatValue |
| InputParameterStringBuilder | builder | String options list and defaults | withValuesKey, addValue, withDefaultValueKey, build | StringValue |
| InputCalculatedFloatBuilder | builder | Computed float values derived from formulas | withKey, withFormula, withValue, build | CalculatedFloat |
| InputDependencyBuilder | builder | Declarative constraints/influences between inputs | withKey, withDependency, withFirstValueKey, withSecondValueKey, addInfluenceValue, build | Dependency |
| AccessoryCategoryBuilder | builder | Accessory categories container | withKey, withName, withOrder, withCalculationRelevant, addAccessory, build | AccessoryCategory |
| AccessoryBuilder | builder | A single accessory incl. image and nested IPS | withId, withKey, withName, withDescription, withPrice, withImage, addInputParameterSet, build | Accessory |
| ImageRefBuilder | builder | Create image references for accessories | withId, withPath, withName, withSize, withUrl, build | ImageRef |
| pimFloat | helper | Construct PimValue for float ranges/defaults | pimFloat(value, unit?, unitType?, key?) | PimValue |
| stringValue | helper | Construct option entries for string inputs | stringValue(key, name) | { Key, Name } |
| influenceValue | helper | Construct influence rules for dependencies | influenceValue(key, order, direction) | InfluenceValue |
Exports
All builder classes and helpers are exported from the package root. You can import them directly from 'kampmann-calcgateway-frontend'.
How to use a builder
Here is a tiny example that creates one float input and one dropdown, groups them, and builds a minimal UIControls object:
import {
UiControlsInitRequestBuilder,
UiControlsInitResponseBuilder,
InputParameterSetBuilder,
InputParameterCategoryGroupBuilder,
InputParameterCategoryBuilder,
InputValueBuilder,
InputParameterFloatBuilder,
InputParameterStringBuilder,
pimFloat,
stringValue,
} from 'kampmann-calcgateway-frontend'
const req = UiControlsInitRequestBuilder.create()
.withProductGroupIds([51050])
.build()
const length = InputValueBuilder.float('length', 'Length', 1)
.withFloat(
InputParameterFloatBuilder.create()
.withUnit('mm')
.withUnitType('length')
.withMinPimValue(pimFloat(100, 'mm', 'length'))
.withMaxPimValue(pimFloat(3000, 'mm', 'length'))
.withDefaultPimValue(pimFloat(800, 'mm', 'length'))
.build()
)
.build()
const medium = InputValueBuilder.string('medium', 'Medium', 2)
.withString(
InputParameterStringBuilder.create()
.addValue(stringValue('water', 'Water'))
.addValue(stringValue('glycol', 'Glycol'))
.withDefaultValueKey('water')
.build()
)
.build()
const category = InputParameterCategoryBuilder.create()
.withGroupKey('general')
.withGroupName('General')
.withGroupOrder(1)
.addInputValue(length)
.addInputValue(medium)
.build()
const group = InputParameterCategoryGroupBuilder.create()
.withKey('general')
.withName('General')
.addCategory(category)
.build()
const ips = InputParameterSetBuilder.create()
.withKey('set1')
.withName('Standard')
.addCategoryGroup(group)
.build()
export const ui = UiControlsInitResponseBuilder.create()
.withRequest(req)
.addInputParameterSet(ips)
.build()
Advanced example
The following example demonstrates a more complete, production-like UIControls definition. It includes:
- Multiple groups (medium, cooling, heating)
- Float inputs with units, ranges and slider field types
- String inputs with option lists
- Calculated floats
- Dependencies with influence values
You can copy/paste this example and adapt values to your needs.
import type { UIControls } from 'kampmann-calcgateway-frontend'
import {
// Components and types you might use
CalcGatewayForm,
CalculationTable,
// Builders
UiControlsInitRequestBuilder,
UiControlsInitResponseBuilder,
InputParameterSetBuilder,
InputParameterCategoryGroupBuilder,
InputParameterCategoryBuilder,
InputValueBuilder,
InputParameterFloatBuilder,
InputParameterStringBuilder,
InputCalculatedFloatBuilder,
InputDependencyBuilder,
// Helpers
pimFloat,
stringValue,
influenceValue,
// Enums / constants
RequestLanguage,
RequestRegion,
RequestUnitSystem,
ScopeSystem,
ResultTableType,
} from 'kampmann-calcgateway-frontend'
function buildExampleUIControls(): UIControls {
// Build Request
const req = UiControlsInitRequestBuilder.create()
.withProductIds([444933])
.withProductGroupIds([])
.withProductFamilyIds([])
.withScopeSystem(ScopeSystem.EXTERNAL)
.withIncludeAccessory(false)
.withInterfaceI18n({
Language: RequestLanguage.DE,
Region: RequestRegion.DE,
UnitSystem: RequestUnitSystem.METRIC
})
.withCalculationI18n({
Language: RequestLanguage.DE,
Region: RequestRegion.DE,
UnitSystem: RequestUnitSystem.METRIC
})
.build();
// Group: medium
const mediumCategory = InputParameterCategoryBuilder.create()
.withGeneralUse(true)
.withGroupOrder(0)
.addInputValue(
// medium (string dropdown)
InputValueBuilder.string('medium', 'Medium', 10)
.withVisible(true)
.withFieldType('dropDown')
.withFloat(
InputParameterFloatBuilder.create()
.withMinPimValue(pimFloat(0))
.withMaxPimValue(pimFloat(0))
.withDefaultPimValue(pimFloat(0))
.withStepSizePimValue(pimFloat(0))
.withDecimals(0)
.build()
)
.withString(
InputParameterStringBuilder.create()
.withValuesKey('MEDIUM.SEL')
.addValue(stringValue('water', 'Wasser'))
.addValue(stringValue('water_ETHYL', 'Ethylenglykol'))
.withDefaultValueKey('water')
.build()
)
.build()
)
.addInputValue(
// medium_concentration (float slider)
InputValueBuilder.float('medium_concentration', 'Konzentration', 20)
.withVisible(true)
.withDisplayOn('medium != water')
.withValueListCheck(true)
.withFieldType('slider')
.withFloat(
InputParameterFloatBuilder.create()
.withUnitType('percentage')
.withUnit('%')
.withMinPimValue({ Key: 'MINGLYKOLKONZENTRATION.NUM', Value: 30, Unit: '%', UnitType: 'percentage' })
.withMaxPimValue({ Key: 'MAXGLYKOLKONZENTRATION.NUM', Value: 30, Unit: '%', UnitType: 'percentage' })
.withDefaultPimValue({ Key: 'DEFAULTGLYKOLKONZENTRATION.NUM', Value: 30, Unit: '%', UnitType: 'percentage' })
.withStepSizePimValue({ Key: 'STEPGLYKOLKONZENTRATION.NUM', Value: 1, Unit: '%', UnitType: 'percentage' })
.withDecimals(0)
.build()
)
.withString({ Values: null } as any)
.build()
)
.build();
const mediumGroup = InputParameterCategoryGroupBuilder.create()
.withKey('medium')
.withName('Medium')
.withOrder(0)
.withLength(1)
.addCategory(mediumCategory)
.build();
// Group: cooling
const coolingCategory = InputParameterCategoryBuilder.create()
.withGroupOrder(0)
.addInputValue(
InputValueBuilder.float('flow_temperature', 'Vorlauftemperatur', 30)
.withVisible(true)
.withFieldType('slider')
.withFloat(
InputParameterFloatBuilder.create()
.withUnitType('temperature')
.withUnit('°C')
.withMinPimValue({ Key: 'MINVORLAUFKUEHLEN.NUM', Value: 5, Unit: '°C', UnitType: 'temperature' })
.withMaxPimValue({ Key: 'MAXVORLAUFKUEHLEN.NUM', Value: 18, Unit: '°C', UnitType: 'temperature' })
.withDefaultPimValue({ Key: 'DEFAULTVORLAUFKUEHLEN.NUM', Value: 7, Unit: '°C', UnitType: 'temperature' })
.withStepSizePimValue({ Key: 'STEPVORLAUFKUEHLEN.NUM', Value: 1, Unit: '°C', UnitType: 'temperature' })
.withDecimals(0)
.build()
)
.withString({ Values: null } as any)
.build()
)
.addInputValue(
InputValueBuilder.float('return_temperature', 'Rücklauftemperatur', 40)
.withVisible(true)
.withDisplayOn('false')
.withFieldType('slider')
.withFloat(
InputParameterFloatBuilder.create()
.withUnitType('temperature')
.withUnit('°C')
.withMinPimValue({ Key: 'MINRUECKLAUFKUEHLEN.NUM', Value: 10, Unit: '°C', UnitType: 'temperature' })
.withMaxPimValue({ Key: 'MAXRUECKLAUFKUEHLEN.NUM', Value: 23, Unit: '°C', UnitType: 'temperature' })
.withDefaultPimValue({ Key: 'DEFAULTRUECKLAUFKUEHLEN.NUM', Value: 12, Unit: '°C', UnitType: 'temperature' })
.withStepSizePimValue({ Key: 'STEPRUECKLAUFKUEHLEN.NUM', Value: 1, Unit: '°C', UnitType: 'temperature' })
.withDecimals(0)
.build()
)
.withString({ Values: null } as any)
.build()
)
.addInputValue(
InputValueBuilder.float('outdoor_air_temperature', 'Außenlufttemperatur', 50)
.withVisible(true)
.withFieldType('slider')
.withFloat(
InputParameterFloatBuilder.create()
.withUnitType('temperature')
.withUnit('°C')
.withMinPimValue({ Key: 'MINAUSSENTEMPERATURKUEHLEN.NUM', Value: 20, Unit: '°C', UnitType: 'temperature' })
.withMaxPimValue({ Key: 'MAXAUSSENTEMPERATURKUEHLEN.NUM', Value: 40, Unit: '°C', UnitType: 'temperature' })
.withDefaultPimValue({ Key: 'DEFAULTAUSSENTEMPERATURKUEHLEN.NUM', Value: 35, Unit: '°C', UnitType: 'temperature' })
.withStepSizePimValue({ Key: 'STEPAUSSENLUFTTEMPERATURKUEHLEN.NUM', Value: 1, Unit: '°C', UnitType: 'temperature' })
.withDecimals(0)
.build()
)
.withString({ Values: null } as any)
.build()
)
.addCalculatedFloat(
InputCalculatedFloatBuilder.create().withKey('delta_temperature').withFormula('return_temperature - flow_temperature').build()
)
.addCalculatedFloat(
InputCalculatedFloatBuilder.create().withKey('neg_delta_temperature').withFormula('flow_temperature - return_temperature').build()
)
.addCalculatedFloat(
InputCalculatedFloatBuilder.create().withKey('under_temperature').withFormula('outdoor_air_temperature - (flow_temperature + return_temperature) / 2').build()
)
.addCalculatedFloat(
InputCalculatedFloatBuilder.create().withKey('delta_air_to_return_temperature').withFormula('outdoor_air_temperature - return_temperature').build()
)
.addDependency(
InputDependencyBuilder.create()
.withKey('cooling_offset_lower_limit')
.withDependency('<=')
.withFirstValueKey('delta_temperature')
.withFirstPimValue({ Key: 'delta_temperature', Value: 0, Unit: '°C', UnitType: 'temperature' })
.withSecondValueKey('OFFSETRUECKLAUFKUEHLEN.NUM')
.withSecondPimValue({ Key: 'OFFSETRUECKLAUFKUEHLEN.NUM', Value: 5, Unit: '°C', UnitType: 'temperature' })
.addInfluenceValue(influenceValue('return_temperature', 0, 'lower'))
.addInfluenceValue(influenceValue('flow_temperature', 1, 'raise'))
.build()
)
.addDependency(
InputDependencyBuilder.create()
.withKey('cooling_offset_upper_limit')
.withDependency('>=')
.withFirstValueKey('delta_temperature')
.withFirstPimValue({ Key: 'delta_temperature', Value: 0, Unit: '°C', UnitType: 'temperature' })
.withSecondValueKey('OFFSETRUECKLAUFKUEHLEN.NUM')
.withSecondPimValue({ Key: 'OFFSETRUECKLAUFKUEHLEN.NUM', Value: 5, Unit: '°C', UnitType: 'temperature' })
.addInfluenceValue(influenceValue('return_temperature', 0, 'raise'))
.addInfluenceValue(influenceValue('flow_temperature', 1, 'lower'))
.build()
)
.addDependency(
InputDependencyBuilder.create()
.withKey('cooling_thermomode')
.withDependency('<')
.withFirstValueKey('flow_temperature')
.withFirstPimValue({ Key: 'flow_temperature', Value: 0, Unit: '°C', UnitType: 'temperature' })
.withSecondValueKey('return_temperature')
.withSecondPimValue({ Key: 'return_temperature', Value: 0, Unit: '°C', UnitType: 'temperature' })
.addInfluenceValue(influenceValue('flow_temperature', 0, 'lower'))
.build()
)
.addDependency(
InputDependencyBuilder.create()
.withKey('under_temperature_lower_limit')
.withDependency('>=')
.withFirstValueKey('under_temperature')
.withFirstPimValue({ Key: 'under_temperature', Value: 0, Unit: '°C', UnitType: 'temperature' })
.withSecondValueKey('INFLUMINUNTERTEMPERATURKUEHLEN.NUM')
.withSecondPimValue({ Key: 'INFLUMINUNTERTEMPERATURKUEHLEN.NUM', Value: -1.5, Unit: '°C', UnitType: 'temperature' })
.addInfluenceValue(influenceValue('flow_temperature', 0, 'lower'))
.addInfluenceValue(influenceValue('outdoor_air_temperature', 1, 'raise'))
.build()
)
.addDependency(
InputDependencyBuilder.create()
.withKey('under_temperature_upper_limit')
.withDependency('<=')
.withFirstValueKey('under_temperature')
.withFirstPimValue({ Key: 'under_temperature', Value: 0, Unit: '°C', UnitType: 'temperature' })
.withSecondValueKey('INFLUMAXUNTERTEMPERATURKUEHLEN.NUM')
.withSecondPimValue({ Key: 'INFLUMAXUNTERTEMPERATURKUEHLEN.NUM', Value: 33, Unit: '°C', UnitType: 'temperature' })
.addInfluenceValue(influenceValue('flow_temperature', 0, 'raise'))
.addInfluenceValue(influenceValue('outdoor_air_temperature', 1, 'lower'))
.build()
)
.addDependency(
InputDependencyBuilder.create()
.withKey('delta_air_to_return_temperature_lower_limit')
.withDependency('>=')
.withFirstValueKey('delta_air_to_return_temperature')
.withFirstPimValue({ Key: 'delta_air_to_return_temperature', Value: 0, Unit: '°C', UnitType: 'temperature' })
.withSecondValueKey('INFLUMINRUECKLAUFRAUMKUEHLEN.NUM')
.withSecondPimValue({ Key: 'INFLUMINRUECKLAUFRAUMKUEHLEN.NUM', Value: -3, Unit: '°C', UnitType: 'temperature' })
.addInfluenceValue(influenceValue('outdoor_air_temperature', 0, 'raise'))
.build()
)
.build();
const coolingGroup = InputParameterCategoryGroupBuilder.create()
.withKey('cooling')
.withName('Kühlen')
.withOrder(1)
.withLength(1)
.addCategory(coolingCategory)
.build();
// Group: heating
const heatingCategory = InputParameterCategoryBuilder.create()
.withGroupOrder(0)
.addInputValue(
InputValueBuilder.float('flow_temperature', 'Vorlauftemperatur', 160)
.withVisible(true)
.withFieldType('slider')
.withFloat(
InputParameterFloatBuilder.create()
.withUnitType('temperature')
.withUnit('°C')
.withMinPimValue({ Key: 'MINVORLAUFHEIZEN.NUM', Value: 35, Unit: '°C', UnitType: 'temperature' })
.withMaxPimValue({ Key: 'MAXVORLAUFHEIZEN.NUM', Value: 70, Unit: '°C', UnitType: 'temperature' })
.withDefaultPimValue({ Key: 'DEFAULTVORLAUFHEIZEN.NUM', Value: 45, Unit: '°C', UnitType: 'temperature' })
.withStepSizePimValue({ Key: 'STEPVORLAUFHEIZEN.NUM', Value: 1, Unit: '°C', UnitType: 'temperature' })
.withDecimals(0)
.build()
)
.build()
)
.addInputValue(
InputValueBuilder.float('return_temperature', 'Rücklauftemperatur', 170)
.withVisible(true)
.withDisplayOn('false')
.withFieldType('slider')
.withFloat(
InputParameterFloatBuilder.create()
.withUnitType('temperature')
.withUnit('°C')
.withMinPimValue({ Key: 'MINRUECKLAUFHEIZEN.NUM', Value: 30, Unit: '°C', UnitType: 'temperature' })
.withMaxPimValue({ Key: 'MAXRUECKLAUFHEIZEN.NUM', Value: 65, Unit: '°C', UnitType: 'temperature' })
.withDefaultPimValue({ Key: 'DEFAULTRUECKLAUFHEIZEN.NUM', Value: 40, Unit: '°C', UnitType: 'temperature' })
.withStepSizePimValue({ Key: 'STEPRUECKLAUFHEIZEN.NUM', Value: 1, Unit: '