Skip to main content

Foundation Forms UI schema

Most renderers are defined directly in the jsonSchema that comes from the server, but there are also those that you can add via uiSchema.

You can control the appearance of your form using the UI Schema to describe the layout of your form. This describes the different UI schema elements that appear in your form.

Examples

Customisable UI schema

Here is an example of a UI schema we could use with the JSON schema we described in the previous page.

In this UISchema:

  • the SIMPLE_TRADE_ID field is hidden
  • the label is overridden for QUANTITY and SIDE
  • an options configuration has been provided for SIDE, which will render a comboxbox

The combobox accepts an array of objects. You can specify the object property for option value for each option with valueField and the option display value with labelField.

Declaration:

<foundation-form
design-system-prefix="rapid"
:jsonSchema="${sampleJsonSchema}"
:uischema="${simpleTradeUiSchema}"
></foundation-form>

Usage:

const sampleJsonSchema = {
type: 'object',
properties: {
QUANTITY: {
type: 'number',
description: 'kotlin.Double',
},
SIDE: {
type: 'string',
description: 'kotlin.String',
},
},
};

export const simpleTradeUiSchema: UiSchema = {
type: 'VerticalLayout',
elements: [
{
type: 'Control',
scope: '#/properties/SIMPLE_TRADE_ID',
options: {
hidden: true
}
},
{
type: 'Control',
scope: '#/properties/QUANTITY',
label: 'Enter Quantity:'
},
{
type: 'Control',
scope: '#/properties/SIDE',
options: <ConnectedRenderersOptions>{
data: [
{ label: 'Buy', value: 'BUY' },
{ label: 'Sell', value: 'SELL' }
],
valueField: 'value',
labelField: 'label',
}
}
]
}

@customElement({
name: 'form-example',
template: html`
<foundation-form
design-system-prefix="rapid"
:jsonSchema="${sampleJsonSchema}"
:uischema="${simpleTradeUiSchema}"
></foundation-form>
`,
})
export class FormExample extends GenesisElement {}

It is important to note the scope property in each UiSchemaElement.

Foreign-key relationship with UISchema

You can easily use foundation forms to enforce a foreign-key relationship between two entities.

Let's say you have two tables, COUNTERPARTY and TRADE, and the TRADE table has a foreign-key relationship on COUNTERPARTY_ID.

You can use the UISchema to show a list derived from the COUNTERPARTY table. You can make it user-friendly and show the NAME field for the label and the COUNTERPARTY_ID field for the value.

smart-forms-examples-dictionary.kts

tables {
...
table(name = "TRADE", id = 11_000) {
field("TRADE_ID", STRING).sequence("TR")
field("COUNTERPARTY_ID", INT).notNull()
field("NOTES", STRING)
field("PRICE", DOUBLE).notNull()
field("QUANTITY", STRING).notNull()
field("SIDE", ENUM("SELL","BUY")).default("BUY").notNull()
primaryKey("TRADE_ID")
}

table(name = "COUNTERPARTY", id = 11_001) {
field("COUNTERPARTY_ID", INT).notNull()
field("ENABLED", BOOLEAN).default(false).notNull()
field("MAIN_CONTACT", STRING).notNull()
field("NAME", STRING).notNull()
primaryKey("COUNTERPARTY_ID")
}
...
}

You must have a query in your Data Server to serve the contents of the COUNTERPARTY table.

dataServer {
...
query("ALL_COUNTERPARTIES", COUNTERPARTY)
...
}

In the UI schema, for the COUNTERPARTY_ID control:

  1. Specify the allOptionsResourceName to be the value from your Data Server query - in this case, ALL_COUNTERPARTIES.

  2. Set the valueField to be COUNTERPARTY_ID and labelField to be NAME:

Declaration:

<foundation-form
design-system-prefix="rapid"
:jsonSchema="${sampleJsonSchema}"
:uischema="${simpleTradeUiSchema}"
></foundation-form>

Usage:

const sampleJsonSchema = {
type: 'object',
properties: {
TRADE_ID: {
type: 'string',
description: 'kotlin.String',
},
PRICE: {
type: 'number',
description: 'kotlin.Double',
},
NOTES: {
type: 'string',
description: 'kotlin.String',
},
COUNTERPARTY_ID: {
type: 'string',
description: 'kotlin.String',
},
QUANTITY: {
type: 'number',
description: 'kotlin.Double',
},
SIDE: {
type: 'string',
description: 'kotlin.String',
},
},
};

export const tradeUISchema: UiSchema = {
type: 'Control',
elements: [
{
type: 'Control',
scope: '#/properties/TRADE_ID',
options: {
hidden: true,
}
},
{
type: 'Control',
scope: '#/properties/SIDE',
options: <ConnectedRenderersOptions>{
data: [
{ label: 'Buy', value: 'BUY' },
{ label: 'Sell', value: 'SELL' }
],

valueField: 'value',
labelField: 'label',
}
},
{
type: 'Control',
scope: '#/properties/PRICE'
},
{
type: 'Control',
scope: '#/properties/QUANTITY'
},

{
type: 'Control',
scope: '#/properties/COUNTERPARTY_ID',
label: 'Counterparty',
options: {
allOptionsResourceName: 'ALL_COUNTERPARTIES',
valueField: 'COUNTERPARTY_ID',
labelField: 'NAME',
}
},
{
type: 'Control',
scope: '#/properties/NOTES',
options: {
textarea: true,
},
},
]
}


@customElement({
name: 'form-example',
template: html`
<foundation-form
design-system-prefix="rapid"
:jsonSchema="${sampleJsonSchema}"
:uischema="${simpleTradeUiSchema}"
></foundation-form>
`,
})
export class FormExample extends GenesisElement {}

The resulting form looks like this, with the counterparty name displayed in the combobox.

There is much more you can do with the UiSchema, such as specify layouts, rules for showing/hiding/enabling/disabling controls.

info

After you have looked at the basics here, you can find more details in our API Docs

Full source code at JSON/UI Schema example