# How to style a specefic deep neasted element

**URL:** <https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274>\
**Category:** General\
**Created:** [August 9, 2024, 4:11pm UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274 "2024-08-09T16:11:21Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![stephan1](https://avatars.discourse-cdn.com/v4/letter/s/cdc98d/32.png) [@stephan1](https://jsonforms.discourse.group/u/stephan1)\
**Post date:** [August 9, 2024, 4:11pm UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/1 "2024-08-09T16:11:21Z")

</div>

Hello,  
i have a complex structure with many levels. It looks fine so far, but now i want to change some options like “elementLabelProp”: “type” for a deep array (“styleRule”). Also this is only the beginning, it will get more deeper levels.

- Is it possible to work with deep structures?
- can i export the generated uiSchema.json or is there a ui generator for the data-schema?
- can i set the options of a specific element?

 ![image](https://global.discourse-cdn.com/free1/uploads/jsonforms/original/2X/d/d748189d29e8996d4a749e0dd67d16e8f61e1bba.png)

> **schema**
>
> ```auto
> {
> "definitions": {
> "styleRule": {
> "type": "array",
> "items": {
> "anyOf": [
> {
> "type": "object",
> "title": "default",
> "properties": {
> "type": {
> "type": "string",
> "enum": ["default"],
> "default": "default"
> },
> "output": {
> "type": "string"
> }
> }
> },
> {
> "type": "object",
> "title": "min",
> "properties": {
> "type": {
> "type": "string",
> "enum": ["default"],
> "default": "default"
> },
> "output": {
> "type": "string"
> }
> }
> },
> {
> "type": "object",
> "title": "category",
> "properties": {
> "type": {
> "type": "string",
> "enum": ["default"],
> "default": "default"
> },
> "output": {
> "type": "string"
> }
> }
> }
> ]
> }
> },
> "layer": {
> "type": "object",
> "properties": {
> "id": {
> "type": "string"
> },
> "type": {
> "type": "string",
> "enum": ["fill", "line"]
> },
> "styleRules": {
> "type": "object",
> "properties": {
> "color": {
> "$ref": "#/definitions/styleRule"
> }
> }
> }
> }
> },
> "atlas": {
> "source": {
> "type": "object",
> "title": "Source",
> "properties": {
> "type": {
> "type": "string",
> "enum": ["vector", "geojson"],
> "default": "vector"
> },
> "provider": {
> "type": "string",
> "enum": ["tileserver", "publicTileserver"],
> "default": "tileserver"
> },
> "providerId": {
> "type": "string"
> },
> "maxzoom": {
> "type": "number",
> "default": 18
> },
> "minzoom": {
> "type": "number",
> "default": 5
> }
> },
> "required": ["label"]
> }
> },
> "sectionObj": {
> "type": "object",
> "title": "New Section",
> "properties": {
> "id": {
> "type": "string"
> },
> "label": {
> "type": "string"
> },
> "parentId": {
> "type": "string"
> },
> "childrenType": {
> "type": "string",
> "enum": ["switch", "radio"]
> },
> "activityControlType": {
> "type": "string",
> "enum": ["switch", "icon"]
> }
> },
> "required": ["label"]
> }
> },
> "type": "object",
> "properties": {
> "mainType": {
> "type": "string",
> "enum": ["layerPackage"]
> },
> "section": {
> "oneOf": [
> {
> "type": "string",
> "title": "parentId",
> "minLength": 1
> },
> {
> "type": "null",
> "title": "unset",
> "minLength": 1
> },
> {
> "$ref": "#/definitions/sectionObj"
> }
> ]
> },
> "source": {
> "$ref": "#/definitions/atlas/source"
> },
> "layers": {
> "type": "array",
> "items": { "$ref": "#/definitions/layer" }
> }
> }
> }
> 
> ```

> **ui-schema**
>
> ```auto
> {
> "type": "VerticalLayout",
> "elements": [
> {
> "type": "Control",
> "label": "MainType",
> "scope": "#/properties/mainType"
> },
> {
> "type": "Group",
> "label": "Section",
> "elements": [
> {
> "type": "Control",
> "label": "MainSection",
> "scope": "#/properties/section"
> }
> ]
> },
> 
> {
> "type": "Control",
> "label": "Main Source",
> "scope": "#/properties/source"
> },
> 
> {
> "type": "Control",
> "label": "layers",
> "scope": "#/properties/layers",
> "options": {
> "showSortButtons": true
> }
> }
> ]
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![sdirix](https://yyz2.discourse-cdn.com/free1/user_avatar/jsonforms.discourse.group/sdirix/32/1073_2.png) [@sdirix](https://jsonforms.discourse.group/u/sdirix)\
**Post date:** [August 12, 2024, 11:09am UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/2 "2024-08-12T11:09:45Z")

</div>

Hi @stephan1,

There are two built-in mechanisms to handle “deep” Ui Schemas:

- You can directly specify it by providing nested ui schemas via `options.detail`. See here for the [documentation](https://jsonforms.io/docs/uischema/controls#the-detail-option). This will result in one very large UI Schema, or
- You can use the `uischemas` registry which is handed over to JSON Forms similar to the `renderers` registry. It contains `(tester, uischema)` tuples. This allows to only hand over the UI Schema for the nested level you want to customize. The `uischemas` registry is queried whenever a `detail` shall be rendered, e.g. when rendering objects or arrays.

Alternatively you can always express all customizations via custom renderers in case you don’t want to maintain UI Schemas.

---

<div class="post-metadata">

**Author:** ![stephan1](https://avatars.discourse-cdn.com/v4/letter/s/cdc98d/32.png) [@stephan1](https://jsonforms.discourse.group/u/stephan1)\
**Post date:** [August 13, 2024, 8:14am UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/3 "2024-08-13T08:14:05Z")

</div>

Hey @sdirix  
thanks for your solutions.

is there a example for `uischemas` registry?

i found this

> **registerUISchema example**
>
> ```auto
> import { Actions, NOT_APPLICABLE } from '@jsonforms/core';
> 
> store.dispatch(
> Actions.registerUISchema(
> (jsonSchema, schemaPath) => {
> return schemaPath === '#/properties/firstarray' ? 2 : NOT_APPLICABLE;
> },
> {
> type: 'VerticalLayout',
> elements: [
> {
> type: 'Control',
> scope: '#/properties/firstName',
> },
> {
> type: 'Control',
> scope: '#/properties/lastName',
> },
> ],
> }
> )
> );
> 
> ```

but dont know how to integrate it into the jsonforms-react-seed demo

> **jsonformsDemo.tsx**
>
> ```auto
> import {
> materialCells,
> materialRenderers,
> } from '@jsonforms/material-renderers';
> import { JsonForms } from '@jsonforms/react';
> import Button from '@mui/material/Button';
> import Grid from '@mui/material/Grid';
> import Typography from '@mui/material/Typography';
> import { FC, useMemo, useState } from 'react';
> import ratingControlTester from '../ratingControlTester';
> import schema from '../schema.json';
> import uischema from '../uischema.json';
> import RatingControl from './RatingControl';
> 
> const classes = {
> container: {
> padding: '1em',
> width: '100%',
> },
> title: {
> textAlign: 'center',
> padding: '0.25em',
> },
> dataContent: {
> display: 'flex',
> justifyContent: 'center',
> borderRadius: '0.25em',
> backgroundColor: '#cecece',
> marginBottom: '1rem',
> },
> resetButton: {
> margin: 'auto !important',
> display: 'block !important',
> },
> demoform: {
> margin: 'auto',
> padding: '1rem',
> },
> };
> 
> const initialData = {
> name: 'Send email to Adrian',
> description: 'Confirm if you have passed the subject\nHereby ...',
> done: true,
> recurrence: 'Daily',
> rating: 3,
> section: {
> id: 'test',
> label: 'test labek',
> },
> };
> 
> const renderers = [
> ...materialRenderers,
> //register custom renderers
> { tester: ratingControlTester, renderer: RatingControl },
> ];
> 
> export const JsonFormsDemo: FC = () => {
> const [data, setData] = useState<object>(initialData);
> const stringifiedData = useMemo(() => JSON.stringify(data, null, 2), [data]);
> 
> const clearData = () => {
> setData({});
> };
> return (
> <Grid
> container
> justifyContent={'center'}
> spacing={1}
> style={classes.container}>
> <Grid item sm={6}>
> <Typography variant={'h4'}>Bound data</Typography>
> <div style={classes.dataContent}>
> <pre id="boundData">{stringifiedData}</pre>
> </div>
> <Button
> style={classes.resetButton}
> onClick={clearData}
> color="primary"
> variant="contained"
> data-testid="clear-data">
> Clear data
> </Button>
> </Grid>
> <Grid item sm={6}>
> <Typography variant={'h4'}>Rendered form</Typography>
> <div style={classes.demoform}>
> <JsonForms
> schema={schema}
> uischema={uischema}
> data={data}
> renderers={renderers}
> cells={materialCells}
> onChange={({ data }) => setData(data)}
> />
> </div>
> </Grid>
> </Grid>
> );
> };
> 
> ```

---

<div class="post-metadata">

**Author:** ![sdirix](https://yyz2.discourse-cdn.com/free1/user_avatar/jsonforms.discourse.group/sdirix/32/1073_2.png) [@sdirix](https://jsonforms.discourse.group/u/sdirix)\
**Post date:** [August 13, 2024, 9:15am UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/4 "2024-08-13T09:15:44Z")

</div>

The example you posted is for a very old version of JSON Forms and is no longer applicable.

You just need to hand over a `uischemas` prop to JSON Forms. It is structured exactly like the `renderers` prop. See [here](https://github.com/eclipsesource/jsonforms/blob/26fd0e90fc1f771630cb678399456e18f8cb9acd/packages/core/src/store/store.ts#L71), [here](https://github.com/eclipsesource/jsonforms/blob/26fd0e90fc1f771630cb678399456e18f8cb9acd/packages/core/src/store/store.ts#L101-L105) and [here](https://github.com/eclipsesource/jsonforms/blob/26fd0e90fc1f771630cb678399456e18f8cb9acd/packages/core/src/testers/testers.ts#L84-L89) for the types.

I don’t think we have an example on the website, however there is one in our internal dev app, see [here](https://github.com/eclipsesource/jsonforms/blob/26fd0e90fc1f771630cb678399456e18f8cb9acd/packages/examples/src/examples/nestedArrays.ts#L93-L104).

---

<div class="post-metadata">

**Author:** ![stephan1](https://avatars.discourse-cdn.com/v4/letter/s/cdc98d/32.png) [@stephan1](https://jsonforms.discourse.group/u/stephan1)\
**Post date:** [August 13, 2024, 10:26am UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/5 "2024-08-13T10:26:07Z")

</div>

ok i create a list of regietries and add them to the element

> **uiSchemas**
>
> ```auto
> const uiSchemas: Array<JsonFormsUISchemaRegistryEntry> = [
> {
> tester: (schema, schemaPath, path) => {
> console.log(schema, schemaPath, path);
> return schemaPath === '#/properties/layers' ? 1 : -1;
> },
> uischema: {
> type: 'array',
> options: { showSortButtons: true },
> },
> },
> ];
> 
> ```

> **JsonForms**
>
> ```auto
> <JsonForms
> schema={schema}
> uischema={uischema}
> uischemas={uiSchemas}
> data={data}
> renderers={renderers}
> cells={materialCells}
> onChange={({ data }) => setData(data)}
> />
> 
> ```

it shows me some schemas but there are no array entries.  
If i run it like that i will get ‘No applicable renderer found.’ inside the array entry.  
Also what does the number means, which need to be returnd inside tester?

---

<div class="post-metadata">

**Author:** ![sdirix](https://yyz2.discourse-cdn.com/free1/user_avatar/jsonforms.discourse.group/sdirix/32/1073_2.png) [@sdirix](https://jsonforms.discourse.group/u/sdirix)\
**Post date:** [August 13, 2024, 12:09pm UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/6 "2024-08-13T12:09:41Z")

</div>

Hi @stephan1,

Your registered UI Schema needs to be valid. We don’t define a uischema with `type: 'array'`, therefore there is no off-the-shelf renderer which reacts to that and you get the “no applicable renderer” found message.

The `uischemas` registry is called for all objects and arrays. So if you want to customize the `showSortButtons` of an array within your schema, then you need test for and return the ui schema of the parent of the array.

---

<div class="post-metadata">

**Author:** ![stephan1](https://avatars.discourse-cdn.com/v4/letter/s/cdc98d/32.png) [@stephan1](https://jsonforms.discourse.group/u/stephan1)\
**Post date:** [August 13, 2024, 3:17pm UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/7 "2024-08-13T15:17:53Z")

</div>

i checked your example [here](https://github.com/eclipsesource/jsonforms/blob/26fd0e90fc1f771630cb678399456e18f8cb9acd/packages/examples/src/examples/nestedArrays.ts#L93-L104)

but there is no `elements` property of `JsonFormsUISchemaRegistryEntry`

 ![image](https://global.discourse-cdn.com/free1/uploads/jsonforms/original/2X/4/437ad511f5e7bcb473f913a997ea00f88e686bb7.png)

and also here the question, where to put the `options: { showSortButtons: true },`

there is no exporter which returns the generated uiSchema of a given jsonSchema, right?

---

<div class="post-metadata">

**Author:** ![sdirix](https://yyz2.discourse-cdn.com/free1/user_avatar/jsonforms.discourse.group/sdirix/32/1073_2.png) [@sdirix](https://jsonforms.discourse.group/u/sdirix)\
**Post date:** [August 16, 2024, 10:01am UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/8 "2024-08-16T10:01:38Z")

</div>

Hi @stephan1,

`Layout` extends `UISchemaElement` and thereby adds the `elements` property, see [here](https://github.com/eclipsesource/jsonforms/blob/26fd0e90fc1f771630cb678399456e18f8cb9acd/packages/core/src/models/uischema.ts#L194-L218).

You can invoke the UI Schema generator manually via `Generate.uiSchema`. `Generate` can be imported from `@jsonforms/core`.

> [@stephan1](#):
>
> where to put the `options: { showSortButtons: true },`

As part of the control referring to the array, e.g.

```auto
{
  "type": "VerticalLayout",
  "elements": [
    {
      "type": "Control",
      "label": "First Name",
      "scope": "#/properties/firstName"
    },
    {
      "type": "Control",
      "label": "Last Name",
      "scope": "#/properties/lastName"
    },
    {
      "type": "Control",
      "label": "Age",
      "scope": "#/properties/age"
    },
    {
      "type": "Control",
      "label": "Children",
      "scope": "#/properties/children",
      "options": { "showSortButtons": true }
    }
  ]
}

```

Fyi, if you want to use `showSortButtons` on ALL arrays, then you can simply hand this option over in the `config` prop. It will then be respected by all array renderers.

---

<div class="post-metadata">

**Author:** ![stephan1](https://avatars.discourse-cdn.com/v4/letter/s/cdc98d/32.png) [@stephan1](https://jsonforms.discourse.group/u/stephan1)\
**Post date:** [August 16, 2024, 12:43pm UTC](https://jsonforms.discourse.group/t/how-to-style-a-specefic-deep-neasted-element/2274/9 "2024-08-16T12:43:19Z")

</div>

> [@sdirix](#):
>
> Fyi, if you want to use `showSortButtons` on ALL arrays, then you can simply hand this option over in the `config` prop. It will then be respected by all array renderers.

nice 🙂 i will test it. Is there a documentation of the config?

it it also possible to have `null` or better `undefined` as a type?  
i have a property which can be a object or can be leaved unset. but im not shure how to leave it unset.
