Custom object renderer

Hey,

I’m trying to create a custom renderer that detects if the object has a custom metadata property (i.e. "languageKeys": true) and in those cases renders a custom component that allows settings the property value for each language.

An example schema could be

    "specialFactors": {
      "type": "object",
      "languageKeys": true,
      "additionalProperties": {
        "type": "string"
      }
    },

I tried to implement the custom renderer as such (just to proof of concept the idea first):

const ForEachLangWrapper = (props: ControlProps) => {
  const { uischema, schema, path, enabled } = props;

  return (
    <div>
      <div>Language picker</div>
      <JsonFormsDispatch
        uischema={{ type: "Control", scope: `${uischema.scope}/fi` } as any}
        schema={(schema as any).additionalProperties}
        path={composePaths(path, "fi")}
        enabled={enabled}
      />
    </div>
  );
};
const WrappedForEachLangWrapper = withJsonFormsControlProps(ForEachLangWrapper);

const renderers = [
  ...vanillaRenderers,
  {
    tester: rankWith(
      10,
      schemaMatches((schema) => {
        return schema.type === "object" && !!(schema as any).languageKeys;
      })
    ),
    renderer: WrappedForEachLangWrapper,
  },
];

As far as I understand, this should render “Language picker” with a textinput below it, however all I get is

No applicable cell found.
Object { type: “Control”, scope: “#/properties/specialFactors/fi” }

What would be the right way to go by this?

Using jsonforms with react and vanilla renderers v3.0.0

Hello @wyozi ,
It is not immediately clear to me why the “Language picker” text is not shown but it makes sense that the text renderer is not found.
The reason for this is that the scope of the uischema handed into JsonFormsDispatch must be relative to the schema handed into the JsonFormsDispatch.
Consequently, you need to adapt your JsonFormsDispatch code:

<JsonFormsDispatch
        uischema={{ type: "Control", scope: `#` } as ControlElement}
        schema={(schema as any).additionalProperties}
        path={composePaths(path, "fi")}
        enabled={enabled}
/>

The scope becomes simply the root # because the schema you hand in is only the schema defining the additionalProperties, i.e. { "type": "string" } based on your example schema.

Note that it is probably cleaner to define the fi property explicitly in your schema instead of just relying on additionalProperties. But both should work.

I hope that helps,
Lucas