Switch
An on/off setting with a clear label and optional state text.
Playground and Examples use the shared browser runtime. For Service Studio inputs and event wiring, use Implementation and API.
Open OutSystems showcase ↗Implement Switch in your application
Use the same setup, screen state and event mapping workflow as the existing components. These components are included in Community 1.1.0.
An on/off setting with a clear label and optional state text. These components are included in @blukavantui/community 1.1.0.
Prepare your local Web project
Use a TypeScript application with a CSS-capable bundler. Install @blukavantui/community@1.1.0 from npm, or install the matching downloaded archive.
// In your test application’s package.json dependencies:
"@blukavantui/community": "1.1.0"Run npm install in that test application to install the component package. Load the theme once and the component stylesheet shown in the adapter. Create an empty host in your view:
<div id="example"></div>Mount one typed instance
This reusable adapter follows the Button and TimePicker guide pattern. Its types come from the factory, so required options stay required. Attach the host first; mount once per view and retain the handle.
import { createSwitch } from '@blukavantui/community/switch'
import '@blukavantui/community/theme.css'
import '@blukavantui/community/switch.css'
type Options = NonNullable<Parameters<typeof createSwitch>[1]>
type Events = NonNullable<Parameters<typeof createSwitch>[2]>
export function mount(host: HTMLElement, options: Options, events: Events = {}) {
const instance = createSwitch(host, options, events)
return { instance, update: (patch: Partial<Options>) => instance.update(patch), destroy: () => instance.destroy() }
}
Connect state and updates
User interaction calls Change; update() and reset() do not. Synchronize your application state after either method. Clear a stale Error before validate(), and validate again in your application before saving. These fields expose Change and Blur; TextInput also exposes Action.
The working example stores values in application variables. If the host is inside a form, a non-canceled form reset restores initial component values; synchronize your store after that reset and clear any application errors explicitly.
Reflect a Boolean preference
Use: Checked, OnText, OffText, Change
Store the Boolean from Change. OnText and OffText are visual labels; the field’s Label supplies the accessible name. Use update({Checked}) for a saved preference loaded by your application.
Toggle with Space and verify the text and application state agree.
Separate a setting change from saving it
Use: Disabled, ReadOnly, Error
The Switch does not persist preferences. If your application saves immediately, control pending/failed states around its own request and restore the previous Checked value on failure.
Confirm a read-only switch stays focusable but cannot change, and a disabled switch cannot be operated.
Use the complete working example
Save this as switch.ts, import its mount function and pass your attached host. It includes application state, interactive controls and a destroy handler.
Download the editable TypeScript example ↓
Complete Switch example
import { createSwitch } from '@blukavantui/community/switch'
import '@blukavantui/community/theme.css'
import '@blukavantui/community/switch.css'
export function mount(host: HTMLElement) {
const root = document.createElement('section')
const target = document.createElement('div')
const status = document.createElement('p')
status.setAttribute('role', 'status')
const reset = document.createElement('button')
reset.type = 'button'; reset.textContent = 'Restore saved preference'
root.append(target, status, reset); host.append(root)
const savedPreference = true // Replace with your application data.
let enabled = savedPreference
const render = () => { status.textContent = `Draft preference: ${enabled ? 'enabled' : 'disabled'}` }
const instance = createSwitch(target, {
Name: 'notifications', Label: 'Email notifications', Checked: enabled,
OnText: 'On', OffText: 'Off', Description: 'Changes here are not sent to a server.',
}, { Change(value) { enabled = value; render() } })
const listeners = new AbortController()
reset.addEventListener('click', () => {
instance.update({ Checked: savedPreference })
enabled = instance.getValue(); render()
}, { signal: listeners.signal })
render()
return { instance, destroy() { listeners.abort(); instance.destroy(); root.remove() } }
}
Verify behavior and dispose
- Use Tab to reach the control. Space toggles choices; radio groups support arrow navigation. Inputs retain standard text-editing shortcuts.
- Check required, disabled and read-only states; verify reset and programmatic updates also synchronize your application state.
- Call the example handle’s
destroy()when the view is removed. Abort your application listeners and requests; ignore any asynchronous result after disposal. - Mount again and confirm there is one instance and one callback per interaction.
Reference the native producer
In Manage Dependencies, select Switch from BluKavantUi_Community_Inputs, together with the structures and public actions used by its API. Refresh existing references before publishing your consumer. Inherit the shared Community theme in your application's theme.
Place the Block in your screen
ExampleScreen — Screen (your application)
└─ ExistingLayout — referenced Layout Block instance (child of ExampleScreen)
└─ Content — existing slot on ExistingLayout
└─ ComponentRegion — Container (child of that slot)
└─ MainComponent — BluKavantUi_Community_Inputs.Switch Block instance (child of ComponentRegion)Reuse your screen’s existing Layout and its content slot; do not add a second layout. If your Layout names that slot differently, use its actual content slot. ComponentRegion is a new Container; MainComponent is a referenced Block instance.
Create and bind screen state
Create local variables on ExampleScreen for the values your application changes. Use the exact native types below; lists are typed OutSystems Lists, while inputs ending in Json are Text containing the documented JSON. Bind each MainComponent.Input to its matching StateInput local. Constants can instead use the default directly. Fill required data from your Aggregate or Data Action before enabling interaction.
| MainComponent input | Screen local / native type | Initial value | Purpose |
|---|---|---|---|
| Error | StateError · Text | "" | Application validation message; a non-empty value marks the control invalid. Clear it after validation succeeds. |
| Checked | StateChecked · Boolean | False | Boolean checked state. Bind a screen variable and assign the Boolean OnChange.Value back to it. |
All native input defaults
| Input | Type | Default | Required |
|---|---|---|---|
| Name | Text | "" | No |
| Label | Text | "" | No |
| Description | Text | "" | No |
| Error | Text | "" | No |
| Required | Boolean | False | No |
| Disabled | Boolean | False | No |
| ReadOnly | Boolean | False | No |
| Size | Text | "Medium" | No |
| ExtendedClass | Text | "" | No |
| Checked | Boolean | False | No |
| OnText | Text | "" | No |
| OffText | Text | "" | No |
| EnableMotion | Boolean | False | No |
| MotionPreference | Text | "System" | No |
| UseDefaultMotionDuration | Boolean | True | No |
| MotionDurationMs | Integer | 450 | No |
| MotionEasing | Text | "standard" | No |
| EnableRipple | Boolean | False | No |
Create the event handlers and map every argument
For each event you use, create the named screen Client Action below. Add its listed input parameters with the exact types. Select that action on MainComponent's event property, then enter each mapping explicitly. Event arguments and screen locals are different scopes.
OnBlur → HandleBlur
Raised when a field loses focus. Validate your screen state here when using validation on blur.
| Handler input | Native type | Event mapping |
|---|
Flow: Start → run your application action using the mapped event arguments → End.
OnChange → HandleChange
Raised when the user changes the value. Assign the emitted Value back to the bound screen variable.
| Handler input | Native type | Event mapping |
|---|---|---|
| RequestedValue | Boolean | RequestedValue = Value |
Flow: Start → validate the requested value; assign the corresponding screen state so the Block receives it back → End.
OnError → HandleError
Reports native runtime initialization or update errors. Show safe feedback and inspect the configuration; this is not the normal field validation event.
| Handler input | Native type | Event mapping |
|---|---|---|
| RequestedMessage | Text | RequestedMessage = Message |
Flow: Start → display the mapped error argument in your feedback region → End.
Apply the example event flow
MainComponent.OnChange → HandleChange
Map RequestedValue = Value
Start
→ Assign StateChecked = RequestedValue
→ EndValidate before saving
These custom controls do not automatically participate in OutSystems Form.Valid. Validate your bound screen state, assign Error text for invalid fields, and call your own Server Action only when valid. Validate again on the server. Required is a runtime field requirement, not a mandatory Block input.
Verify in your consumer
Publish the consumer, supply representative data, trigger each connected event and inspect the mapped arguments. Check a failed request, a retry and leaving/reopening the screen. The table describes the native contract; the Web recipes can contain capabilities with different native names or availability. Use these native names and the API tab as the authority for Service Studio.
Shared component motion settings
Use createMotionComponents from the local bluui-community/src/component-motion.ts entry. The factories retain the component’s data, options, events and methods, and add setMotion(settings?). Create the controller with createMotionController from bluui-community/src/motion.ts.
| Setting / method | Behavior |
|---|---|
mode | inherit (default), reduced, or off. The owning controller and operating system can always reduce or disable motion. |
duration | Optional finite-transition override, 0–2000 ms. Omit for default timings; zero is immediate. Reduced caps permitted fades at 200 ms. Continuous loading retains its own cadence. |
easing | Optional standard, ease-in, ease-out, ease-in-out, linear or spring. Omit for each component's default easing. |
ui.configure(settings?) | Replace collection defaults, update existing instances and cancel their unfinished decoration. Explicit instance overrides remain. Omit settings to restore component defaults. |
component.setMotion(settings?) | Replace just this instance's overrides. Omit settings to inherit the collection again. Inputs, focus, content and actions are retained. |
ui.destroy() | Dispose owned instances and their motion before destroying the controller. No global listener is added at import time. |
Validation rejects nonfinite, negative and over-2000-ms durations before changing settings. Motion follows the existing component behavior. Grid rows need stable keys; charts update their actual data series; workflow transitions retain their approval and save contracts. Charts respect EnableAnimation: false; continuous Sparkline glow keeps its own cadence and Pause control. Ripple, glow, shimmer and page-entry helpers remain explicit additions.
Open the playground motion controls · Read the motion and OutSystems integration guide
Current playground settings
Open the playground to load the local source example.Switch with application state
These components are included in @blukavantui/community 1.1.0. This is the same complete example used by the implementation guide, with real controls, event handling and cleanup.
import { createSwitch } from '@blukavantui/community/switch'
import '@blukavantui/community/theme.css'
import '@blukavantui/community/switch.css'
export function mount(host: HTMLElement) {
const root = document.createElement('section')
const target = document.createElement('div')
const status = document.createElement('p')
status.setAttribute('role', 'status')
const reset = document.createElement('button')
reset.type = 'button'; reset.textContent = 'Restore saved preference'
root.append(target, status, reset); host.append(root)
const savedPreference = true // Replace with your application data.
let enabled = savedPreference
const render = () => { status.textContent = `Draft preference: ${enabled ? 'enabled' : 'disabled'}` }
const instance = createSwitch(target, {
Name: 'notifications', Label: 'Email notifications', Checked: enabled,
OnText: 'On', OffText: 'Off', Description: 'Changes here are not sent to a server.',
}, { Change(value) { enabled = value; render() } })
const listeners = new AbortController()
reset.addEventListener('click', () => {
instance.update({ Checked: savedPreference })
enabled = instance.getValue(); render()
}, { signal: listeners.signal })
render()
return { instance, destroy() { listeners.abort(); instance.destroy(); root.remove() } }
}
Mount and dispose
Call mount after the host is attached to the document. Retain the returned handle and call destroy from your view’s unmount hook.
import { mount } from './switch'
const host = document.getElementById('example')
if (!host) throw new Error('Missing example host')
const view = mount(host)
// Register this with your framework/router’s unmount hook:
function disposeView() { view.destroy() }Use instance.update(patch) for changes while mounted; creating another instance on each render leaves duplicate controls.
Build with native Blocks
Configure the referenced Block in Service Studio using typed inputs, screen state and Client Actions. The Implementation tab includes the widget tree and exact event argument mappings.
Shared component motion settings
Use createMotionComponents from the local bluui-community/src/component-motion.ts entry. The factories retain the component’s data, options, events and methods, and add setMotion(settings?). Create the controller with createMotionController from bluui-community/src/motion.ts.
| Setting / method | Behavior |
|---|---|
mode | inherit (default), reduced, or off. The owning controller and operating system can always reduce or disable motion. |
duration | Optional finite-transition override, 0–2000 ms. Omit for default timings; zero is immediate. Reduced caps permitted fades at 200 ms. Continuous loading retains its own cadence. |
easing | Optional standard, ease-in, ease-out, ease-in-out, linear or spring. Omit for each component's default easing. |
ui.configure(settings?) | Replace collection defaults, update existing instances and cancel their unfinished decoration. Explicit instance overrides remain. Omit settings to restore component defaults. |
component.setMotion(settings?) | Replace just this instance's overrides. Omit settings to inherit the collection again. Inputs, focus, content and actions are retained. |
ui.destroy() | Dispose owned instances and their motion before destroying the controller. No global listener is added at import time. |
Validation rejects nonfinite, negative and over-2000-ms durations before changing settings. Motion follows the existing component behavior. Grid rows need stable keys; charts update their actual data series; workflow transitions retain their approval and save contracts. Charts respect EnableAnimation: false; continuous Sparkline glow keeps its own cadence and Pause control. Ripple, glow, shimmer and page-entry helpers remain explicit additions.
Open the playground motion controls · Read the motion and OutSystems integration guide
Current playground settings
Open the playground to load the local source example.createSwitch
User interaction calls Change; update() and reset() do not. Synchronize your application state after either method. Clear a stale Error before validate(), and validate again in your application before saving. These fields expose Change and Blur; TextInput also exposes Action.
import { createSwitch } from '@blukavantui/community/switch';
import '@blukavantui/community/switch.css';Load @blukavantui/community/theme.css once in your app shell.createSwitch(host: HTMLElement, options?: SwitchOptions, events?: FieldEvents<boolean>)These components are included in @blukavantui/community 1.1.0. Required/optional and signatures come from the 1.1.0 TypeScript source. Defaults below describe runtime behavior, which may differ from the Playground’s selected example.
Options
13| Name | Type / requirement | Usage |
|---|---|---|
Checked | boolean | undefinedOptional | Default: false. Boolean state. Change emits the new checked value, not the option’s string Value. |
OnText | string | undefinedOptional | Default: "". Visual state text beside a checked Switch. Label remains its accessible name. |
OffText | string | undefinedOptional | Default: "". Visual state text beside an unchecked Switch. |
Id | string | undefinedOptional | Default: Generated once. Control id used for label/help association. Set when mounting; changing Id later does not replace the generated identity. |
Name | string | undefinedOptional | Default: "". HTML form field name. Supply it when using FormData. |
Label | string | undefinedOptional | Default: "". Visible accessible label. Placeholder text does not replace a label. |
Description | string | undefinedOptional | Default: "". Supporting text associated with the control through aria-describedby. |
Error | string | undefinedOptional | Default: "". Validation message and invalid appearance. Input components also set custom validity; clear Error before rechecking a corrected value. |
Required | boolean | undefinedOptional | Default: false. Enables the control’s required constraint and accessible required state. Validation still belongs to your application. |
Disabled | boolean | undefinedOptional | Default: false. Prevents interaction; disabled native form controls are omitted from FormData. |
ReadOnly | boolean | undefinedOptional | Default: false. Prevents user changes while retaining a readable value. Choice and Select controls implement this behavior themselves. |
Size | FieldSize | undefinedOptional | Default: "Medium". Small, Medium or Large. Uses the shared field sizing tokens. |
ExtendedClass | string | undefinedOptional | Default: "". Additional space-separated classes on the root. Keep application CSS scoped. |
Callbacks
2| Name | Type / requirement | Usage |
|---|---|---|
Change | ((value: boolean) => void) | undefinedOptional | Called for a user value change (including a clear action). TextInput/TextArea emit on input; choices emit on selection. update and reset do not emit Change. Synchronize your application state explicitly after programmatic changes. |
Blur | (() => void) | undefinedOptional | Called when the input loses focus. Select reports Blur when focus leaves its composite control. Use it to run application validation if desired. |
Instance methods & properties
8| Name | Signature / type | Usage |
|---|---|---|
element | HTMLElement | Root DOM element owned by the component. Mount into a real host before using focus or validation. |
control | HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | Underlying form-associated native control. Use focus() for keyboard focus; Select.control is hidden and its focus() method targets the visible trigger. |
update | (patch: Partial<ToggleOptions>) => void | Shallow-merge an options patch into the current configuration. Arrays/adornment objects replace their previous value. User-change callbacks are not emitted. Call before destroy; updates afterward throw. |
getValue | () => boolean | Read the current user value; Boolean for Checkbox/Switch/RadioButton, string for TextInput/TextArea/RadioGroup/Select. Use this after programmatic updates or reset to synchronize your state. |
reset | () => void | Restore the initial Value/Checked (and Checkbox Indeterminate), retaining current options such as labels and choices. Does not emit Change or clear an application Error. A non-canceled form reset also invokes this when mounted inside that form. |
focus | () => void | Focus the visible control. RadioGroup prefers the selected enabled option, then the first enabled option; Select focuses its custom trigger. |
validate | () => boolean | Calls browser reportValidity and returns a Boolean; it may focus the invalid control. RadioGroup checks its enabled inputs. Clear a stale Error first. There is no ValidationChanged callback on these new fields. |
destroy | () => void | Remove owned DOM and listeners. Destroy child component instances before their layout. Safe to call repeatedly; do not use other methods afterward. |
Related data types
Expand a type for its exact fields and allowed values. Pass objects and arrays directly in Web code.
SwitchOptions
Current local TypeScript declaration. Use the component-specific options and callbacks shown above.
interface SwitchOptions extends FieldOptions { Checked?: boolean; OnText?: string; OffText?: string; }FieldOptions
Common typed field options. FormField only applies presentation and ARIA; see its option notes for properties managed by the consumer.
interface FieldOptions {
Id?: string; Name?: string; Label?: string; Description?: string; Error?: string;
Required?: boolean; Disabled?: boolean; ReadOnly?: boolean; Size?: FieldSize;
ExtendedClass?: string;
}FieldSize
Allowed shared input sizes.
type FieldSize = 'Small' | 'Medium' | 'Large';FieldEvents
Current local TypeScript declaration. Use the component-specific options and callbacks shown above.
interface FieldEvents<T> { Change?: (value: T) => void; Blur?: () => void; }FieldComponent
Current local TypeScript declaration. Use the component-specific options and callbacks shown above.
interface FieldComponent<P, T> {
element: HTMLElement; control: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
update(patch: Partial<P>): void; getValue(): T; reset(): void; focus(): void;
validate(): boolean; destroy(): void;
}ToggleOptions
Internal return-type alias shared by checkbox/switch/radio implementations. For application options, import the component-specific CheckboxOptions, SwitchOptions or RadioButtonOptions.
type ToggleOptions = CheckboxOptions & SwitchOptions;CheckboxOptions
Current local TypeScript declaration. Use the component-specific options and callbacks shown above.
interface CheckboxOptions extends FieldOptions { Checked?: boolean; Indeterminate?: boolean; Value?: string; }Verified native contract for BluKavantUi_Community_Inputs → Essentials → Switch. Bindings, events and layout were verified in the compiled development consumer on 2026-10-24.
Browser checks cover labels, keyboard interactions, values and cleanup. Scoped Safari VoiceOver and browser checks passed; this is not a full-library conformance certification. Test your composed application with its actual content and assistive technologies.
Purpose and use
An on/off setting with a clear label and optional state text.
Keyboard design guidance
Use Tab to reach the control. Space toggles choices; radio groups support arrow navigation. Inputs retain standard text-editing shortcuts.
See the support status above for review coverage and any limitations.
In your application
Provide useful labels, preserve visible focus, and test the component with your actual content. Use text alongside status colors and check contrast in each state.
Events0No events yet.
Interact with an example to see its events.