# How do I pass custom props?

**URL:** <https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110>\
**Category:** General\
**Created:** [May 1, 2024, 10:42pm UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110 "2024-05-01T22:42:57Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![lll](https://avatars.discourse-cdn.com/v4/letter/l/4491bb/32.png) [@lll](https://jsonforms.discourse.group/u/lll)\
**Post date:** [May 1, 2024, 10:42pm UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/1 "2024-05-01T22:42:57Z")

</div>

Hello,

My company has decided that we are going to use this package and I have been given the task to implement it, but I’m having great difficulty understanding it. It would be great if you guys made some more advanced examples with custom renderers.

In my case, I want to implement a radio list that has both a primary and secondary text per option. Something akin to this: [https://imgur.com/sbd6EUs](https://imgur.com/sbd6EUs).

So I tried downloading the React seed, and following the custom renderer tutorial, but I for the life of me cannot figure out how to pass custom props to this renderer. Where would I put the array containing the options with the properties primaryText, secondaryText and value?

---

<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:** [May 2, 2024, 7:24am UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/2 "2024-05-02T07:24:34Z")

</div>

Hi @lll,

JSON Forms has two main artifacts: The JSON Schema, describing the data, and the UI Schema (optionally) describing the layout. Rendering is taken over by renderer-tester pairs: Whenever an UI Element is to be rendered, the testers will receive the UI element as well as the corresponding (sub)-JSON schema and then indicate whether they want to take over rendering that element.

The renderer then receives the same props which were used for the dispatching process and they also have access to the form wide state. Our bindings then take the props and the form-wide state and derive all the necessary props for the renderer, e.g. `label`, `errors`, `visible`, `enabled` etc.

The renderer is also given the respective `schema` and `uischema` as props.

Usually that information is enough to render everything needed. The benefit of being `JSON Schema` based is that most data should be handed over in a declarative way. In your case I would expect that the JSON Schema contains a `oneOf` construct of `const` values which each have a `title` and/or description, e.g.

```json
{
  "type": "object",
  "properties": {
    "plan": {
      "type": "string",
      "description": "Select a plan based on the size and needs of your team.",
      "oneOf": [
        {
          "const": "basic",
          "title": "Basic",
          "description": "Perfect for individuals and small teams."
        },
        {
          "const": "pro",
          "title": "Pro",
          "description": "For growing teams and businesses."
        },
        {
          "const": "enterprise",
          "title": "Enterprise",
          "description": "For large organizations and custom solutions."
        }
      ]
    }
  },
}

```

In this case you can access all of this information in the `schema` prop handed over to your custom renderer for `plan`, no custom props are needed.

* * *

In case you can’t adapt the schemas used and you actually need to inject some custom props into your renderer, then you need to use [React contexts](https://react.dev/learn/passing-data-deeply-with-context). With them you can inject arbitrary information and callbacks into your renderers from outside of JSON Forms.

Alternatively, if your schemas are more simple, for example like this:

```auto
{
  "type": "object",
  "properties": {
    "plan": {
      "type": "string",
      "enum": ["basic", "pro", "enterprise"],
    }
  },
}

```

Then you could either add all the additional text in your UI Schema element, or you use the [i18n support](https://jsonforms.io/docs/i18n) of JSON Forms to derive the additional labels in your custom renderer.

---

<div class="post-metadata">

**Author:** ![lll](https://avatars.discourse-cdn.com/v4/letter/l/4491bb/32.png) [@lll](https://jsonforms.discourse.group/u/lll)\
**Post date:** [May 2, 2024, 8:33am UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/3 "2024-05-02T08:33:10Z")

</div>

Hello Stefan

Thank you for your reply!

I tried something similar to what you’ve suggested earlier and thought I was doing it wrong. I now implemented what you did, and this is the console-log from my custom “control”: [https://imgur.com/c1heEWN](https://imgur.com/c1heEWN)

I only see the “oneOf” props deeply nested in schema \> properties \> myRadioObject \> oneOf.  
Surely these should be on the top level along with data, description, errors, label, path and such, no?

---

<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:** [May 2, 2024, 9:28am UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/4 "2024-05-02T09:28:18Z")

</div>

Something does not fit on your side. You have a UI Schema with a scope `#/properties/myRadioObject/radioList` but this does not exist in your `schema`. That’s probably why your `schema` is also not properly resolved. The UI Schema element should only point to `#/properties/myRadioObject`.

Can you post your full `schema`, `uischema` and custom renderer code? It’s difficult to help properly without that information.

---

<div class="post-metadata">

**Author:** ![lll](https://avatars.discourse-cdn.com/v4/letter/l/4491bb/32.png) [@lll](https://jsonforms.discourse.group/u/lll)\
**Post date:** [May 2, 2024, 9:55am UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/5 "2024-05-02T09:55:04Z")

</div>

Sure. Here’s the schema:

```auto

const schema1 = {
  type: "object",
  properties: {
    myRadioObject: {
      type: "string",
      oneOf: [
        {
          const: "1",
          title: "First title",
          description: "First description",
        },
        {
          const: "2",
          title: "Second title",
        },
      ],
    },
  },
};

```

here is the ui schema:

```auto

const uiSchema1 = {
  type: "VerticalLayout",
  elements: [
    {
      type: "Control",
      scope: "#/properties/myRadioObject/radioList",
      label: "myRadioObject",
    },
  ],
};

```

and here is the control I am logging from:

```auto
const RadioListControl = (props: Props) => {
  console.log("all props", props);
  return (
    <RadioList
      onSelect={(newValue) => props.handleChange(props.path, newValue)}
      {...props}
    />
  );
};

export default withJsonFormsOneOfProps(RadioListControl);

```

here’s the radio list:

```auto

const RadioList = (props: RadioListProps) => {
  console.log("props from the actual radio list", props);
  return <h1 id="#/properties/radioList">Hey from Radio List</h1>;
};

```

(This console logs the same as the control)

---

<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:** [May 2, 2024, 10:51am UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/6 "2024-05-02T10:51:08Z")

</div>

Hi @lll,

As mentioned above, the `scope` in the UI schema should look like this:

```auto
const uiSchema1 = {
  type: "VerticalLayout",
  elements: [
    {
      type: "Control",
      scope: "#/properties/myRadioObject",
      label: "myRadioObject",
    },
  ],
};

```

The `scope` in a control needs to be resolvable against the `schema`.

* * *

In the renderer you are using `withJsonFormsOneOfProps` which is a very generic binding for `oneOf`s. In your case you can use the more specialized `withJsonFormsOneOfEnumProps` which already resolve the options for you. If you want to do it fully “manually” then just use the `withJsonFormsControlProps`.

---

<div class="post-metadata">

**Author:** ![lll](https://avatars.discourse-cdn.com/v4/letter/l/4491bb/32.png) [@lll](https://jsonforms.discourse.group/u/lll)\
**Post date:** [May 2, 2024, 11:24am UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/7 "2024-05-02T11:24:37Z")

</div>

I’m not understanding this scoping part. If I remove the reference to “radioList”, and use the scope you suggest, then it doesn’t render my custom control anymore, but a default input?

this is my tester:

```auto
export default rankWith(
  scopeEndsWith("radioList"),
);

```

I assume I can’t name the scope “#/properties/radioList” if I want to be able to reusse this component multiple times?

---

<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:** [May 2, 2024, 12:22pm UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/8 "2024-05-02T12:22:38Z")

</div>

Hi @lll,

The `scope` should not be used as a free-form field. At least our bindings assume that it contains a valid pointer into the `schema` and use it accordingly. So I would recommend to not encode additional information in there. If you add additional information there, you would need to copy/adapt a larger part of our bindings and the gain is minuscule compared to the effort.

Instead you should write a “smarter” tester. Our `RankedTester` look like this:

```auto
(uischema, schema, context) => number

```

The `rankWith` and `scopeEndsWith` etc. are just helpers we provide to more easily create such a tester.

In case you want to reuse a component multiple times, then you usually not use the `scopeEndsWith` helper as you then need to name all your properties the same. Instead you can check a specfic `schema` structure or `uischema` property, and then react accordingly.

Let’s say you want to save a rendering-hint in the JSON Schema, for example like this:

```auto
const schema1 = {
  type: "object",
  properties: {
    myRadioObject: {
      type: "string",
      x-rendering-hint: "radioList",
      oneOf: [
        {
          const: "1",
          title: "First title",
          description: "First description",
        },
        {
          const: "2",
          title: "Second title",
        },
      ],
    },
  },
};

```

Then your tester could look like this:

```auto
rankWith(10, and(isOneOfEnumControl, schemaMatches(schema => schema.x-rendering-hint === 'radioList')));

```

See [here](https://github.com/Maxouwell/jsonforms/blob/13fa9c5c0b4052a0dc7a2166c2ff0db505c754db/packages/core/src/testers/testers.ts#L381) for all our exported helpers.

---

<div class="post-metadata">

**Author:** ![lll](https://avatars.discourse-cdn.com/v4/letter/l/4491bb/32.png) [@lll](https://jsonforms.discourse.group/u/lll)\
**Post date:** [May 2, 2024, 1:18pm UTC](https://jsonforms.discourse.group/t/how-do-i-pass-custom-props/2110/9 "2024-05-02T13:18:54Z")

</div>

WIth some modifications to your last reply I seem to finally have made it work. Thank you SO much for your help! I truly appreciate it.
