Offers a choice between a number of child schemas.
Use a oneOf schema to represent either the selection of one of many constant values (e.g. a select box or dropdown) or alternative sections of a form (e.g. when the user can complete either a form in tab A or tab B).
Using Const Schema as child schemas creates a typical select box or dropdown.
obj {
id = "#schema"
properties {
oneOf("account") {
title = "Choose a balance currency"
schemas {
const {
title = "EUR"
media = Media.Avatar.build {
content { uri { uri = "urn:wise:currencies:eur:image" } }
}
description = "Euro"
value("EUR")
alert {
markdown = "This is the default currency for your account."
context = Context.NEUTRAL
}
}
const {
title = "GBP"
media = Media.Avatar.build {
content { uri { uri = "urn:wise:currencies:gbp:image" } }
}
description = "British pound"
value("GBP")
}
const {
title = "USD"
media = Media.Avatar.build {
content { uri { uri = "urn:wise:currencies:usd:image" } }
}
description = "United States dollar"
value("USD")
}
}
}
}
}Using other schema types, like a Object Schema, allows showing alternative sections of the form based on the user's choice.
val bankAccountDetails = Step.build {
id = "bankAccountDetails"
title = ""
schemas {
oneOf {
id = "#schema"
title = "Bank Account Details"
placeholder = "Please, select an option"
schemas {
obj {
title = "Inside Europe"
displayOrder = listOf("type", "iban")
properties {
const("type") {
title = "IBAN"
value("IBAN")
}
string("iban") {
title = "IBAN"
pattern = "^[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{1,30}$"
}
}
}
obj {
title = "Outside Europe"
displayOrder = listOf("type", "bic", "swift")
properties {
const("type") {
title = "SWIFT"
value("SWIFT")
}
string("bic") {
title = "BIC"
pattern = "^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$"
}
string("swift") {
title = "Swift"
pattern = "^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$"
}
}
}
}
}
}
layout {
form {
schemaId = "#schema"
}
}
}When to use
- When there are a small number of accepted values which are known to the server. E.g. any enum cases.
When not to use
- If there are a large number of values that are better represented as free-form input, consider using a String Schema instead.
- If this choice is the only function of the screen, consider using a Decision Layout instead.
Sometimes you may want to load a step with an option selected - for example in order to retain the selected option after a refresh.
To figure out which item to select, we look at the step model. Clients will first populate the form with the model, and then inspect each oneOf option and compare them with the model to see which ones match. If no options match, or if multiple match, we will not select anything.
This is the full matching algorithm:
function isPartialMatch(optionValue, stepModel) {
if (isArray(optionValue) && isArray(stepModel)) {
return (
optionValue.length === stepModel.length &&
optionValue.every((value, index) => isPartialModelMatch(value, stepModel[index]))
);
}
if (isObject(optionValue) && isObject(stepModel)) {
// Don't look at properties with null values
const nonNullishKeysInBoth = intersection(nonNullishKeys(optionValue), nonNullishKeys(stepModel));
return (
nonNullishKeysInBoth.length > 0 &&
nonNullishKeysInBoth.every((key) => isPartialModelMatch(optionValue[key], stepModel[key]))
);
}
return optionValue === stepModel;
};
Persisted fields are ignored, as are keys with nullish values.
If your oneOf options share schema property names, you will need to add a discriminator to ensure successful preselection. For example - if the following example did not contain a const type discriminator and the step model was { "name": "Jane" }, we would not know which option to select, as both match. Conversely, if you remove the name property from the schemas, the const discriminator would be unnecessary, as there would be no ambiguity. *
schemas {
obj {
title = "Iban option"
properties {
const("type") {
value = JsonPrimitive("IBAN")
}
string("iban") {
title = "IBAN"
}
string("name") {
title = "Name"
}
}
}
obj {
title = "Bic option"
properties {
const("type") {
value = JsonPrimitive("BIC")
}
string("bic") {
title = "BIC"
}
string("name") {
title = "Name"
}
}
}
}
| Property | Type | Required | Description |
|---|---|---|---|
$id | String | No | A unique id which can be used to refer to the schema. |
| String | No | Additional information to be displayed to the user.
|
alert | AlertLayout | No | Configure an alert which will be displayed above the UI for this schema. This can be used to provide warnings or additional information to the user, but shouldn't be used for validation. For client-side validation please see the validation available on each schema type, or see Validate Async and Action for server-side validation. |
analyticsId | String | No | An internal id which is attached to analytics events relating to the schema. It allows you to override $id during event emission, it is not user-facing and does not have to be unique within the step. |
| Array<AutocompleteToken> | No | A list of tokens describing to the client what kind of field it is. This can enable the user agent or assistive technologies to automatically suggest or fill in information specific to the user. Values not recognised by the client will be discarded, and clients that only support single values will take the first supported value in the list.
|
autofillKey | String | No | Identifies the type of data which the client can autofill for this schema. This is provided in a . delimited string, in the format source.prop, e.g contact.email. In this example, the client should suggest values from the email property on objects retrieved from the contact source to autofill this field. The only currently supported source is contact. It will inspect contacts from the native client address book (if available). Supported properties on the contact source are: - givenName - familyName - fullName - email - firstLine - city - state - postalCode - countryCode |
control | String | No | An identifier which can be used to request the client use a particular UI control to represent this schema. |
default | Any | No | The default value to use for this schema. This will be overridden by a value in the model of the Step if one is provided. |
description | String | No | A user-facing description for the schema. |
disabled | Boolean | No | If true, the UI for this schema will not accept input, but the corresponding data will still be submitted. Defaults to false. |
help | Help | No | Provide additional help information to the user. |
hidden | Boolean | No | If true, no UI will be shown to the user for this schema, but the corresponding data will still be submitted. Defaults to false. |
icon | Icon | No | An icon which the client can use to represent this entity. |
image | Image | No | An image which the client can use to represent this entity. |
| No | An alert that will be displayed inline with the item.
| |
keywords | Array<String> | No | A list of keywords that can be used when searching or filtering items in a One Of Schema. Only applies when this schema is child schema in a One Of Schema. |
media | Media | No | A media object which the client can use to represent this entity. |
| No | The Behavior that should be performed when the schema value changes.
| |
oneOf | Array<Schema> | Yes | The child schemas to be selected between. |
placeholder | String | No | A user-facing placeholder value to use for the field. This can be used to provide an example of the expected input. |
refreshStepOnChange | Boolean | No | When true, the step will be refreshed when the value of this schema changes. |
summary | Summary.Provider | No | Configure how this schema will be summarised when included in an Array Schema. |
| No | An object containing two strings representing two user-facing values. One being clearly more important than the other.
| |
| Array<String> | No | An optional list of identifiers used to configure renderers.
|
title | String | No | A user-facing title for the schema. |
validationMessages | Map<String, String> | No | An object where each property/value pair is the name of a validation property (e.g. maximum) to the user-facing error message to display if the validation fails. |
radio
Allow selection between child schemas using a set of radio options.
obj {
id = "#schema"
properties {
oneOf("account") {
title = "Which account type would you like to open?"
control = Control.Schema.OneOf.RADIO
schemas {
const {
title = "Business"
value("BUSINESS")
}
const {
title = "Personal"
value("PERSONAL")
}
}
}
}
}radio-item
Allow selection between child schemas using a set of radio options with support for additional context such as a third line of text and an inline alert.
obj {
id = "#schema"
properties {
oneOf("plan") {
title = "Choose a plan"
control = Control.Schema.OneOf.RADIO_ITEM
schemas {
const {
title = "Standard"
description = "Free transfers up to 1,000 GBP/month"
value("STANDARD")
}
const {
title = "Premium"
description = "Unlimited free transfers and priority support"
value("PREMIUM")
}
}
}
}
}segmented
Allow selection between items using a segmented control.
obj {
id = "#schema"
properties {
oneOf("paymentMethod") {
title = ""
control = Control.Schema.OneOf.SEGMENTED
schemas {
const {
title = "ACH"
value("ACH")
}
const {
title = "Wire"
value("WIRE")
}
const {
title = "SWIFT"
value("SWIFT")
}
}
}
}
}tab
Allow selection between child schemas using tabs. Note that depending on the number of child schemas, some clients may choose to ignore this control.
obj {
id = "#schema"
properties {
oneOf("details") {
title = ""
control = Control.Schema.OneOf.TAB
schemas {
obj {
title = "Local"
properties {
string("account-number") {
title = "Account number"
}
string("sort-code") {
title = "Sort code"
}
}
}
obj {
title = "International"
properties {
string("iban") {
title = "IBAN"
}
string("bic") {
title = "BIC"
}
}
}
}
}
}
}