core2-jvm (latest)
core2-jvm (latest)core-jvm
  • Home
  • Features
  • Spec
  • Guides
  • Sandbox
  • Step Studio
  • Step
    • Action
    • External
    • Help
    • Link Handler
    • Navigation
    • Persist Async
    • Polling
    • Refresh On Change
    • Schema On Change
    • Step Error
    • Suggestions
    • Summary
    • Toolbar
    • Upload
    • Validate Async
    • Schema
    • All Of Schema
    • Array Schema
    • Blob Schema
    • Boolean Schema
    • Const Schema
    • Integer Schema
    • Number Schema
    • Object Schema
    • One Of Schema
    • String Schema
    • Layout
    • Alert Layout
    • Box Layout
    • Button Layout
    • Columns Layout
    • Decision Layout
    • Divider Layout
    • Form Layout
    • Heading Layout
    • Image Layout
    • Instructions Layout
    • List Layout
    • Loading Indicator Layout
    • Markdown Layout
    • Media Layout
    • Modal Layout
    • Paragraph Layout
    • Progress Layout
    • Review Layout
    • Search Layout
    • Section Layout
    • Status List Layout
    • Tabs Layout
    • Upsell Layout
    • Behavior
    • Action Behavior
    • Copy Behavior
    • Dismiss Behavior
    • Link Behavior
    • Modal Behavior
    • Refresh Behavior
    • Subflow Behavior
    • Subflow
    • Dynamic Launch Config
    • Launch Config
    • Modal Presentation
    • Native Launch Config
    • Presentation
    • Push Presentation
    • Action Response Body
    • Error Response Body
    • Flow Response
    • Modal Response Body
    • No Op Response Body
    • Search Initial Layout Config
    • Search Initial Results Config
    • Search Initial State
    • Search Layout Response Body
    • Search Response
    • Search Response Body
    • Search Result
    • Search Results Response Body
    • Subflow Response Body
    • Additional Info
    • Align
    • Autocapitalization Type
    • Autocomplete Token
    • Context
    • Icon
    • Image
    • Inline Alert
    • Media
    • Native Capabilities
    • Request
    • Size
    • Supporting Values
    • Control
    • Tag

One Of Schema

Android - 8.25.0 iOS - 11539 Web - 2.5.0

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.

Preselection

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;
};

Caveats

Persisted fields are ignored, as are keys with nullish values.

Discriminators

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"
            }
        }
    }
}

Properties

PropertyTypeRequiredDescription
$idStringNoA unique id which can be used to refer to the schema.

additionalText

String

No

Additional information to be displayed to the user.

Android - 9.4.0 iOS - 9.6 Web - 4.38.0

alertAlertLayoutNoConfigure 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.
analyticsIdStringNoAn 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.

autocompleteHint

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.

Android - 8.39.0 iOS - 8.40 Web - 2.5.0

autofillKeyStringNoIdentifies 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
controlStringNoAn identifier which can be used to request the client use a particular UI control to represent this schema.
defaultAnyNoThe default value to use for this schema. This will be overridden by a value in the model of the Step if one is provided.
descriptionStringNoA user-facing description for the schema.
disabledBooleanNoIf true, the UI for this schema will not accept input, but the corresponding data will still be submitted. Defaults to false.
helpHelpNoProvide additional help information to the user.
hiddenBooleanNoIf true, no UI will be shown to the user for this schema, but the corresponding data will still be submitted. Defaults to false.
iconIconNoAn icon which the client can use to represent this entity.
imageImageNoAn image which the client can use to represent this entity.

inlineAlert

InlineAlert

No

An alert that will be displayed inline with the item.

Android - 9.4.0 iOS - 9.6 Web - 4.38.0

keywordsArray<String>NoA 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.
mediaMediaNoA media object which the client can use to represent this entity.

onChange

Behavior

No

The Behavior that should be performed when the schema value changes.

Android - 8.122.0 iOS - 8.114 Web - 4.7.0

oneOfArray<Schema>YesThe child schemas to be selected between.
placeholderStringNoA user-facing placeholder value to use for the field. This can be used to provide an example of the expected input.
refreshStepOnChangeBooleanNoWhen true, the step will be refreshed when the value of this schema changes.
summarySummary.ProviderNoConfigure how this schema will be summarised when included in an Array Schema.

supportingValues

SupportingValues

No

An object containing two strings representing two user-facing values. One being clearly more important than the other.

Android - 9.4.0 iOS - 9.6 Web - 4.38.0

tags

Array<String>

No

An optional list of identifiers used to configure renderers.

Android - 8.131.0 iOS - 8.125 Web - 4.33.0

titleStringNoA user-facing title for the schema.
validationMessagesMap<String, String>NoAn 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.

Controls

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

Android - Unsupported iOS - Unsupported Web - Unsupported

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"
                        }
                    }
                }
            }
        }
    }
}