Change MaterialOneOfRenderer to use Select instead of Tabs

Hello,

I am trying to change the MaterialOneOfRenderer to use a Select Input instead of the Tabs that it has by default. This is my modified code:

import { useCallback, useState } from 'react';
import isEmpty from 'lodash/isEmpty';

import { TabSwitchConfirmDialog } from './TabSwitchConfirmDialog';

import {
  CombinatorRendererProps,
  createCombinatorRenderInfos,
  createDefaultValue,
  isOneOfControl,
  JsonSchema,
  OwnPropsOfControl,
  RankedTester,
  rankWith,
} from '@jsonforms/core';
import { Hidden, MenuItem, Select } from '@mui/material';
import { JsonFormsDispatch, withJsonFormsOneOfProps } from '@jsonforms/react';
import CombinatorProperties from './CombinatorProperties';

export interface OwnOneOfProps extends OwnPropsOfControl {
  indexOfFittingSchema?: number;
}

export const OneOfRenderer = ({
  handleChange,
  schema,
  path,
  renderers,
  cells,
  rootSchema,
  id,
  visible,
  indexOfFittingSchema,
  uischema,
  uischemas,
  data,
}: CombinatorRendererProps) => {
  const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
  const [selectedIndex, setSelectedIndex] = useState(indexOfFittingSchema || 0);
  const [newSelectedIndex, setNewSelectedIndex] = useState(0);
  const handleClose = useCallback(
    () => setConfirmDialogOpen(false),
    [setConfirmDialogOpen]
  );
  const cancel = useCallback(() => {
    setConfirmDialogOpen(false);
  }, [setConfirmDialogOpen]);
  const oneOfRenderInfos = createCombinatorRenderInfos(
    (schema as JsonSchema).oneOf as JsonSchema[],
    rootSchema,
    'oneOf',
    uischema,
    path,
    uischemas
  );

  const openNewTab = (newIndex: number) => {
    handleChange(
      path,
      createDefaultValue(oneOfRenderInfos[newIndex].schema)
    );
    setSelectedIndex(newIndex);
  };

  const confirm = useCallback(() => {
    openNewTab(newSelectedIndex);
    setConfirmDialogOpen(false);
  }, [handleChange, createDefaultValue, newSelectedIndex]);

  const handleSelectChange = (event : any) => {
    const newOneOfIndex = event.target.value;
    setNewSelectedIndex(newOneOfIndex);
    if (isEmpty(data)) {
      openNewTab(newOneOfIndex);
    } else {
      setConfirmDialogOpen(true);
    }
  };

  return (
   <div>
    <Select value={newSelectedIndex} onChange={handleSelectChange}>
        {oneOfRenderInfos.map((oneOfRenderInfo, index) => (
          <MenuItem key={oneOfRenderInfo.label} value={index}>
            {oneOfRenderInfo.label}
          </MenuItem>
        ))}
      </Select>
      {oneOfRenderInfos.map(
        (oneOfRenderInfo, oneOfIndex) =>
          selectedIndex === oneOfIndex && (
            <JsonFormsDispatch
              key={oneOfIndex}
              schema={oneOfRenderInfo.schema}
              uischema={oneOfRenderInfo.uischema}
              path={path}
              renderers={renderers}
              cells={cells}
            />
          )
      )}
      <TabSwitchConfirmDialog
        cancel={cancel}
        confirm={confirm}
        id={'oneOf-' + id}
        open={confirmDialogOpen}
        handleClose={handleClose}
      />
   </div>
      
  );
};

export const oneOfControlTester: RankedTester = rankWith(
  10,
  isOneOfControl
);

export default withJsonFormsOneOfProps(OneOfRenderer);

Now I have the problem, that when I select something within the Select Input the function “handleChange” throws an error:

Uncaught TypeError: handleChange is not a function
    at openNewTab (OneOfRenderer.tsx?t=1703855451425:63:5)
    at handleSelectChange (OneOfRenderer.tsx?t=1703855451425:77:7)
    at handleChange (chunk-TKDOGVKA.js?v=2bf2f5cb:4094:7)

Can someone help and tell me what I am doing wrong? Thank you very much in advance!

Best regards,
Philip

Hi @pbarth,

You are exporting both the OneOfRenderer as well as the wrapped variant (i.e. withJsonFormsControlProps(OneOfRenderer) as a default.

Are you registering the wrapped variant as the custom renderer?

1 Like

Hi @sdirix,

this hint already fixed my problem. Now I changed the component to only export the wrapped variant and everything works. Thank you very much!

Best regards,
Philip

1 Like