Conditional Logic
Dynamically show/hide blocks, variants, 3D objects, and individual mesh parts based on user selections. Attach rules to blocks, then evaluate at runtime.
Add Rules to a Block
// Hide "Armrest Color" when armrests toggle is off
await client.updateOptionBlock('proj_123', 'blk_armrest_color', {
conditionalRules: [{
id: crypto.randomUUID(),
action: 'hide',
targetScope: 'block',
targetVariantIds: [],
operator: 'all',
conditions: [{
id: crypto.randomUUID(),
sourceBlockId: 'blk_armrests',
matchType: 'is-selected',
sourceVariantIds: ['var_without']
}]
}]
});Variant-Level Rules
// Hide indoor-only fabrics when "Outdoor" is selected
await client.updateOptionBlock('proj_123', 'blk_fabric', {
conditionalRules: [{
id: crypto.randomUUID(),
action: 'hide',
targetScope: 'variants',
targetVariantIds: ['var_silk', 'var_velvet'],
operator: 'all',
conditions: [{
id: crypto.randomUUID(),
sourceBlockId: 'blk_environment',
matchType: 'is-selected',
sourceVariantIds: ['var_outdoor']
}]
}]
});3D Object Visibility Rules
// Hide 3D objects in the viewport without hiding the UI block
await client.updateOptionBlock('proj_123', 'blk_chair_parts', {
conditionalRules: [{
id: crypto.randomUUID(),
action: 'hide',
targetScope: '3d',
targetVariantIds: [],
target3dObjectNames: ['headrest_mesh', 'armrest_left', 'armrest_right'],
operator: 'all',
conditions: [{
id: crypto.randomUUID(),
sourceBlockId: 'blk_style',
matchType: 'is-selected',
sourceVariantIds: ['var_minimal']
}]
}]
});3D Part Visibility Rules
// Hide individual mesh parts (sub-meshes) in the viewport
// Targets specific part names from targetPartName / targetPartNames
// rather than whole objects (targetObjectName)
await client.updateOptionBlock('proj_123', 'blk_details', {
conditionalRules: [{
id: crypto.randomUUID(),
action: 'hide',
targetScope: '3d-parts',
targetVariantIds: [],
target3dPartNames: ['logo_emboss', 'stitching_detail', 'button_caps'],
operator: 'all',
conditions: [{
id: crypto.randomUUID(),
sourceBlockId: 'blk_finish',
matchType: 'is-selected',
sourceVariantIds: ['var_plain']
}]
}]
});3D Parts Across Multiple Objects (Enterprise · Modular)
// Enterprise accounts on Modular projects can target 3D parts across
// SEVERAL 3D objects in ONE rule. Use target3dPartsByObject — a map of
// model.fileName -> part names — which supersedes the single-object
// target3dPartObjectName + target3dPartNames pair when present.
// Each object only hides the parts listed under its own fileName key,
// so identically-named meshes in other models are never affected.
await client.updateOptionBlock('proj_123', 'blk_roof', {
conditionalRules: [{
id: crypto.randomUUID(),
action: 'hide',
targetScope: '3d-parts',
targetVariantIds: [],
target3dPartsByObject: {
'Main_roof_3x3.glb': ['ridge_caps', 'flashing'],
'Extra_roof_3x3.glb': ['ridge_caps_extra', 'flashing_extra']
},
operator: 'all',
conditions: [{
id: crypto.randomUUID(),
sourceBlockId: 'blk_treatment',
matchType: 'is-selected',
sourceVariantIds: ['var_smooth']
}]
}]
});Evaluate Conditions
const results = await client.evaluateConditions('proj_123', {
selections: {
dropdownSelections: { 'blk_frame': 'black' },
selectMaterialSelections: { 'blk_fabric': 'linen' },
checkboxSelections: { 'blk_acc': ['cup-holder'] },
toggleSwitchSelections: { 'blk_armrests': 'with' },
carouselSelections: {}
}
});
results.forEach(r => {
console.log(r.blockId, 'visible:', r.blockVisible);
if (r.hiddenVariantIds.length > 0) {
console.log(' hidden variants:', r.hiddenVariantIds);
}
if (r.hidden3dObjectNames?.length > 0) {
console.log(' hidden 3D objects:', r.hidden3dObjectNames);
}
if (r.hidden3dPartNames?.length > 0) {
console.log(' hidden 3D parts:', r.hidden3dPartNames);
}
});Target Scopes Reference
| Scope | Effect | Target Field |
|---|---|---|
| block | Hides/shows the entire option block UI | targetVariantIds (ignored) |
| variants | Hides/shows specific variants within the block | targetVariantIds |
| 3d | Hides/shows whole 3D objects in the viewport (UI stays visible) | target3dObjectNames |
| 3d-parts | Hides/shows individual mesh parts in the viewport (UI stays visible). Enterprise + Modular: target3dPartsByObject targets parts across multiple objects in one rule | target3dPartNames / target3dPartsByObject |
Continue reading
Pricing & CPQBuild CPQ pricing — base prices, price groups, tables, unique modular prices, variables, and formulas.Contact FormsManage contact forms and their 12 field types for lead capture and orders.Quote SubmissionsList and read quote and contact-form submissions captured from configurators.3D ViewerControl the embedded 3D viewer — camera, lighting, scene presets, and runtime selections.
