# Rendering Customizations



This guide explains how to use the `tag` property on a field within
the data model to customize its behavior in the UI when using
`@socotra/ec-react-components`.

Hiding Fields [#hiding-fields]

For fields that should be part of the data model but should almost never
be shown in the UI, you can use the simple `hidden` tag. This tag
removes the field from the form schema during generation, ensuring it
does not render.

This provides a way to control field visibility at the data-model level,
rather than passing a prop to every form instance. The only way to make
a `hidden` field appear is to pass its name in the
`hiddenExceptions` array prop on the form component, making it a
deliberate choice to show it.

* **Tag Format:** `hidden`

Example [#example]

Imagine you have an `internalNotes` field on your `Quote` data
model. This field should be saved with the quote data but should not be
visible on the standard quote form.

**Data Model Configuration:**

```json
{
	"internalNotes": {
		"type": "string",
		"displayName": "Internal Notes",
		"tag": ["hidden"]
	},
	"premiumAmount": {
		"type": "decimal",
		"displayName": "Premium Amount",
		"tag": ["currency.USD"]
	}
}
```

**Result:**

* By default, the `QuoteForm` will **not** display the “Internal
  Notes” field. It is completely removed from the generated schema.

* If you have a special administrative view where you *do* want to show
  this field, you would render the `QuoteForm` with the
  `hiddenExceptions` prop:

```tsx
<QuoteForm hiddenExceptions={['internalNotes']} />
```

Only in this specific instance would the “Internal Notes” field
appear.

Hiding Fields Conditionally [#hiding-fields-conditionally]

The forms support two distinct methods for hiding fields based on the
values of other fields:

1. **Dynamic Client-Side Hiding:** Hides a field based on the value of
   another field *within the same form*. This is ideal for dynamic UIs
   where you want a field to appear or disappear immediately as the user
   makes selections.
2. **Static Schema-Level Hiding:** Hides a field based on a value from
   the root `quote` object. This is useful when a field’s visibility
   depends on a more global state that doesn’t change within the context
   of the current form.

Dynamic Client-Side Hiding (hidden|...) [#dynamic-client-side-hiding-hidden]

This method uses a UI schema rule to show or hide a field. The change
happens instantly on the client-side without a backend call.

* **Tag Format:** `hidden|{fieldName}{operator}{value}`
  * `fieldName`: The name of the field *within the same data model
    level* whose value will be checked.
  * `operator`: Must be either `==` (equals) or `!=` (not equals).
  * `value`: The value to check against (e.g., `true`, `CAR`,
    `123`).

<span id="example-1" />

Example [#example-1]

Imagine you have a `vehicleType` field and you only want to show the
`vin` field if the `vehicleType` is “CAR”.

**Data Model Configuration:**

On your `vin` field, you would add the following tag:

```json
{
	"vin": {
		"type": "string",
		"displayName": "VIN",
		"tag": ["hidden|vehicleType!=CAR"]
	},
	"vehicleType": {
		"type": "string",
		"displayName": "Vehicle Type",
		"options": ["CAR", "MOTORCYCLE", "BOAT"]
	}
}
```

**Result:**

* The “VIN” field will be hidden by default.
* If the user selects “CAR” from the “Vehicle Type” dropdown, the “VIN”
  field will instantly appear.
* If the user selects “MOTORCYCLE” or “BOAT”, the “VIN” field will
  remain hidden.

Static Schema-Level Hiding (rootHidden|...) [#static-schema-level-hiding-roothidden]

This method filters a field out of the JSON Schema itself during its
creation. This is best when the condition for hiding is based on data
outside the immediate form’s scope, specifically from the root quote’s
element data.

* **Tag Format:** `rootHidden|{fieldName}{operator}{value}`
  * `fieldName`: The name of a field located at the
    `quote.element.data` path.
  * `operator`: Must be either `==` or `!=`.
  * `value`: The value to check against.

<span id="example-2" />

Example [#example-2]

Suppose you have an `additionalInsured` element on your quote. You
want to hide the `relationshipToPrimary` field within that element if
the `policyHolderType` (a field on the root quote’s element) is
“INDIVIDUAL”.

**Data Model Configuration:**

On your `relationshipToPrimary` field (inside the
`additionalInsured` element’s model), you would add the following tag:

```json
{
	"relationshipToPrimary": {
		"type": "string",
		"displayName": "Relationship to Primary Insured",
		"tag": ["rootHidden|policyHolderType==INDIVIDUAL"]
	}
}
```

**Result:**

* When the `ElementForm` for the `additionalInsured` element is
  rendered, the system checks the value of
  `quote.element.data.policyHolderType`.
* If the value is “INDIVIDUAL”, the `relationshipToPrimary` field will
  be completely omitted from the form’s schema and will not be rendered.
* If the value is anything else (e.g., “CORPORATION”), the field will be
  included in the schema and rendered in the form.

Horizontal Layout for Custom Data Types [#horizontal-layout-for-custom-data-types]

When working with custom data types (repeatable sets of fields like a
“Driver” or “Vehicle”), you can control how the fields are displayed. By
default, fields are rendered in a two-column layout. By using the
`horizontal-layout` tag, you can force the fields within that custom
data type to render in a single-column layout, where each field takes up
the full width of its row.

* **Tag Format:** `horizontal-layout`

<span id="example-3" />

Example [#example-3]

Imagine you have a `Driver` custom data type that contains
`driverName` and `licenseNumber` fields. You want to add a list of
drivers to a quote, but you want each driver’s fields to be laid out
horizontally for better readability.

**Data Model Configuration:**

1. Define your `Driver` custom data type.
2. On the field in your product model that *references* the `Driver`
   type, add the `horizontal-layout` tag.

```json
// In your product's data model
{
  "drivers": {
    "type": "Driver*", // This is an array of the "Driver" custom data type
    "displayName": "Drivers",
    "tag": ["horizontal-layout"] // Apply the tag here
  }
}

// In your dataTypes configuration
{
  "Driver": {
    "displayName": "Driver",
    "data": {
      "driverName": {
        "type": "string",
        "displayName": "Driver Name"
      },
      "licenseNumber": {
        "type": "string",
        "displayName": "License Number"
      }
    }
  }
}
```

**Result:**

When the form renders the “Drivers” section, instead of stacking the
“Driver Name” and “License Number” fields in a two-column grid, each
driver entry will be displayed in its own row, with the “Driver Name”
label and input field appearing next to each other, taking up the full
available width. This provides a more compact and linear layout for
nested data.

Multi-Select Dropdown for Arrays [#multi-select-dropdown-for-arrays]

For fields that are an array of primitive values (like `string*` or
`int+`) and have a predefined list of choices, you can use the
`multiselect` tag to render the input as a multi-select dropdown or
checkbox group instead of the default array input UI.

* **Tag Format:** `multiselect`
* **Prerequisites:**
  * The field `type` must be an array of primitives (e.g.,
    `string*`, `string+`, `int*`).
  * The field definition must include an `options` array containing
    the list of choices.

<span id="example-4" />

Example [#example-4]

Imagine you want users to select multiple “coverage add-ons” from a list
for their policy.

**Data Model Configuration:**

On your `coverageAddOns` field, you define it as an array of strings,
provide the list of options, and add the tag.

```json
{
	"coverageAddOns": {
		"type": "string*",
		"displayName": "Coverage Add-ons",
		"tag": ["multiselect"],
		"options": [
			"Roadside Assistance",
			"Rental Reimbursement",
			"Towing and Labor",
			"Glass Coverage"
		]
	}
}
```

**Result:**

* **Without the tag:** The UI would render a label “Coverage Add-ons”
  with an “Add” button. Clicking “Add” would create a new select input
  field, forcing the user to select 1 option at a time.
* **With the `multiselect` tag:** The UI renders a single multi-select
  dropdown or a group of checkboxes with all the options listed,
  allowing the user to easily select multiple items from the predefined
  list.

Rendering as a Radio Group [#rendering-as-a-radio-group]

For fields that have a small, fixed set of options, you can use the
`radio-group` tag to display them as a set of radio buttons instead of
a dropdown. This is often more user-friendly when there are only a few
choices.

* **Tag Format:** `radio-group`
* **Prerequisites:**
  * The field `type` must be `string`.
  * The field definition must include an `options` array with the
    available choices.

<span id="example-5" />

Example [#example-5]

Suppose you have a `region` field where the user must select either
“West” or “East”.

**Data Model Configuration:**

On your `region` field, you define it as a string, provide the list of
options, and add the tag.

```json
{
	"region": {
		"type": "string",
		"displayName": "Region",
		"options": ["West", "East"],
		"tag": ["radio-group"]
	}
}
```

**Result:**

* **Without the tag:** The UI would render a standard dropdown menu with
  “West” and “East” as options.
* **With the `radio-group` tag:** The UI will render two radio
  buttons, one for “West” and one for “East”, allowing the user to see
  all options at a glance and select one.

Displaying Currency Fields [#displaying-currency-fields]

To ensure that number fields are correctly formatted and displayed as
currency in the UI, you need to add a specific `currency` tag. This
tag tells the renderer to apply currency formatting, such as adding a
currency symbol (e.g., “$”) and appropriate delimiters.

* **Tag Format:** `currency.{CURRENCY_CODE}`
  * `CURRENCY_CODE`: The standard three-letter ISO 4217 currency code
    (e.g., `USD`, `EUR`, `JPY`).

<span id="example-6" />

Example [#example-6]

You have a field for `premiumAmount` that should be treated as US
Dollars.

**Data Model Configuration:**

On your `premiumAmount` field, you add the `currency.USD` tag.

```json
{
	"premiumAmount": {
		"type": "decimal",
		"displayName": "Premium Amount",
		"tag": ["currency.USD"]
	}
}
```

**Result:**

The UI will render the “Premium Amount” field as a currency input. As
the user types, it will automatically be formatted with a dollar sign,
commas for thousands separators, and will handle decimal places
appropriately, for example, displaying `$1,234.50`.

Disable Fields [#disable-fields]

For fields that should be visible in the UI but should not be editable
by users, you can use the `readOnly` tag. This tag renders the field
as a read-only input, displaying the current value but preventing user
interaction. This is useful for displaying calculated values,
system-generated data, or fields that should only be modified under
specific conditions.

* **Tag Format:** `readOnly`

<span id="example-7" />

Example [#example-7]

Imagine you have a `policyNumber` field that is automatically
generated by the system and should not be editable by users, but they
should be able to see it.

**Data Model Configuration:**

On your `policyNumber` field, you add the `readOnly` tag.

```json
{
	"policyNumber": {
		"type": "string",
		"displayName": "Policy Number",
		"tag": ["readOnly"]
	},
	"premiumAmount": {
		"type": "decimal",
		"displayName": "Premium Amount",
		"tag": ["currency.USD"]
	}
}
```

**Result:**

* The “Policy Number” field will be rendered as a disabled input field,
  showing the current value but preventing the user from typing or
  modifying it.
* The field will appear grayed out or with a different visual style to
  indicate it’s read-only.
* The value will still be included in form submissions and data
  validation.
