Custom string renderer

Hi,

I try to make my own string renderer, which replace original material renderer for all string inputs. I find you tutorial for the custom “Rating” renderer, but I didn’t find how to replace all the string input renderers with my custom one.

The goal is, to make a component, which combines classic string input with some auto-suggestion trigged when user enter some special character (e.g. $ or @).

My questions are:

  1. How can I replace string renderer with my custom one?
  2. Have you ever made similar component as customer renderer? Is it even possible?
  3. Is it possible to agree on cooperation between yours and ours companies? Jsonforms is core in our app, and sometimes we face various problems that we solve for a very long time.

Thank you for reply,
Adam

JSON FORM:


const MSLIBComponentFormContainer = () => {
    const dispatch = useDispatch();

    const selectedMSLIBComponent = useSelector(selectedMSLIBComponentSelector);
    const formResult = useSelector(formResultSelector);

    const renderers = [...materialRenderers, { tester: autoCompleteRendererTester, renderer: AutoCompleteRenderer }];

    return (
        <>
            <JsonForms
                schema={JSON.parse(selectedMSLIBComponent.jsonSchema)}
                uischema={JSON.parse(selectedMSLIBComponent.uiSchema)}
                data={formResult}
                renderers={renderers}
                cells={materialCells}
                onChange={({ data, errors }) => {
                    dispatch(setFormResult(data));
                }}
            />
        </>
    );
};

export default MSLIBComponentFormContainer;

My tester:

import { rankWith, isStringControl } from '@jsonforms/core';

export default rankWith(
    3, //increase rank as needed
    isStringControl
);

My custom string renderer: (super simple, only for test)

import React from 'react';
import { withJsonFormsControlProps } from '@jsonforms/react';
import { TextField } from '@material-ui/core';

interface AutoCompleteRendererProps {
    data: any;
    handleChange(path: string, value: any): void;
    path: string;
}

const AutoCompleteRenderer = ({ data, handleChange, path }: AutoCompleteRendererProps) => {
    return <TextField value={data} onChange={(ev: any) => handleChange(path, ev.value)} />;
};

export default withJsonFormsControlProps(AutoCompleteRenderer);

When I am using this, nothing is renderer.

Hi @adam.cernohorsky!

Nice to hear that you’re using JSON Forms in your product :wink:

  1. How can I replace string renderer with my custom one?

All our off-the-shelf renderers use exactly the same mechanism as custom renderers, so it’s easy to overwrite them. For your use case you need to register a renderer which returns a higher rank than our included MaterialTextControl.

Looking at the code you posted, it looks mostly fine. Which version of JSON Forms and which version of Material UI are you using?

However note that any prop you hand over to JSON Forms should be stable or memoized. You are handing over new schema, uischema and renderers instances with every render pass. Therefore JSON Forms will almost fully rerender with every pass with additional, probably unwanted, change events. onChange will not lead to a rerender.

I would like to suggest to move the renderers out of the component and to useMemo the schema and uischema.

From your information alone I can’t determine why “nothing is rendered”. Can you replicate the problem with our seed app and push a branch? If not, I need more detailed information, e.g. how the schema and uischema look like and what exactly the error is, e.g. only the new renderer not working or the whole form etc.

  1. Have you ever made similar component as customer renderer? Is it even possible?

Yes definitely. Custom text renderers with auto suggestions etc. is a very common use case (e.g. text controls bound to databases and dynamic suggestions retrieval) and definitely possible.

  1. Is it possible to agree on cooperation between yours and ours companies? Jsonforms is core in our app, and sometimes we face various problems that we solve for a very long time.

Definitely. Please take a look at our support options and contact us directly.