Conditional questions#
In this tutorial you will build a form that shows extra questions only when a previous answer matches a specific value.
This is useful for branching forms where some options require additional configuration—for example, enabling a feature and then asking for its settings.
What you will build#
A deployment configuration form that:
Asks which authentication provider to use (
noneoroidc).Shows two extra questions—OIDC server URL and client ID—only when the user selects
oidc.
Prerequisites#
Complete Your first form or be familiar with
create_renderer.
How conditional questions work#
TUI Forms uses the standard JSONSchema allOf / if / then pattern.
"allOf": [
{
"if": { "properties": { "key": { "const": "expected_value" } } },
"then": { "properties": { "extra_field": { <question schema> } } }
}
]
When the user's answer for key equals expected_value, the questions inside
then.properties become active.
Otherwise they are skipped entirely—they will not appear in the returned
answers dict.
The if condition must follow the pattern
{properties: {key: {const: value}}}.
Only a single key–value pair per if block is supported.
Step 1—Define the base question#
Start with the choice question that controls the branching:
schema = {
"title": "Deployment configuration",
"properties": {
"auth_provider": {
"type": "string",
"title": "Authentication provider",
"default": "none",
"oneOf": [
{"const": "none", "title": "None"},
{"const": "oidc", "title": "OpenID Connect (OIDC)"},
],
},
},
}
Step 2—Add the conditional block#
Append an allOf list at the top level of the schema (alongside properties).
Each item has an if condition and a then block with the extra questions:
schema = {
"title": "Deployment configuration",
"properties": {
"auth_provider": {
"type": "string",
"title": "Authentication provider",
"default": "none",
"oneOf": [
{"const": "none", "title": "None"},
{"const": "oidc", "title": "OpenID Connect (OIDC)"},
],
},
},
"allOf": [
{
"if": {
"properties": {"auth_provider": {"const": "oidc"}}
},
"then": {
"properties": {
"oidc_server_url": {
"type": "string",
"title": "OIDC server URL",
"description": "for example, https://auth.example.com/realms/myrealm",
"default": "",
},
"oidc_client_id": {
"type": "string",
"title": "Client ID",
"default": "my-app",
},
}
},
}
],
}
Step 3—Run the form#
from tui_forms import create_renderer
renderer = create_renderer("stdlib", schema)
answers = renderer.render()
print(answers)
Step 4—Try both branches#
Run the script and select None first:
{'auth_provider': 'none'}
The OIDC questions are skipped; they do not appear in the answers at all.
Run again and select OpenID Connect (OIDC):
{'auth_provider': 'oidc', 'oidc_server_url': 'https://auth.example.com/realms/myrealm', 'oidc_client_id': 'my-app'}
This time both extra questions were asked and their answers are in the dict.
Multiple conditional branches#
You can add more allOf items to handle additional choices.
Each item is evaluated independently:
"allOf": [
{
"if": {"properties": {"auth_provider": {"const": "oidc"}}},
"then": {
"properties": {
"oidc_server_url": {"type": "string", "title": "OIDC server URL"},
"oidc_client_id": {"type": "string", "title": "Client ID"},
}
},
},
{
"if": {"properties": {"auth_provider": {"const": "saml"}}},
"then": {
"properties": {
"saml_metadata_url": {"type": "string", "title": "SAML metadata URL"},
}
},
},
]
Next steps#
Computed and constant hidden fields: derive values automatically from what the user answered.
JSONSchema support: full reference for conditional fields and
$refresolution.