rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.
https://rjsf-team.github.io/react-jsonschema-form/
Apache License 2.0
14.35k stars 2.19k forks source link

Can not replace "integer" widget #4163

Open gitdrums opened 7 months ago

gitdrums commented 7 months ago

Prerequisites

What theme are you using?

antd

Version

5.x

Current Behavior

I can succesfully replace the "uri" widget with a custom one, but whatever i try I cant replace "integer". Why?

... const widgets = { uri: MyForm_Uploader, integer: MyForm_Integer, };

return (

{schema && (
{/* Empty fragment = No Submit Button */} <>
### Expected Behavior To see my custom widget in the form (I can only see the default one) ### Steps To Reproduce _No response_ ### Environment ```markdown - OS: Windows 10 - Node: 20.11.0 - npm: 10.2.4 ``` ### Anything else? _No response_
nickgros commented 7 months ago

uri is an existing widget keyword and integer is not. See the Widgets documentation.

You probably want to override the 'updown' widget.

gitdrums commented 7 months ago

Thanks for your suggestion. I did try to override the "updown" and even "range" and "radio" but the problem persists.

here is my simple schema:

{
    "type": "object",
    "title": "",
    "properties": {

        "num_outputs": {
            "type": "integer",
            "title": "Num Outputs",
            "default": 1,
            "maximum": 4,
            "minimum": 1,
            "x-order": 4,
            "description": "Items to order."
        },
    }
}

I am out of ideas! Any help?

gitdrums commented 7 months ago

Here is the funny thing: when I replace text, with my custom integer compoment

  const widgets = {
    uri: MyForm_Uploader,
    text: MyForm_Integer,
    //updown: MyForm_Integer,
  };

text AND integer fields change to my component. I am confused.

gitdrums commented 7 months ago

This is the only workaround I found to replace "integer" with a custom widget: There must be a simpler way. Ideas?

"use client";

import React from "react";
import { RJSFSchema, UiSchema, WidgetProps } from "@rjsf/utils";
import validator from "@rjsf/validator-ajv8";
import Form from "@rjsf/antd";

const MyTest = () => {
  const ReplaceWidget = (uiSchema, type, custom_widget) => {
    // Iterate over schema properties
    Object.keys(schema.properties).forEach((key) => {
      const property = schema.properties[key];
      if (property.type === type) {
        // Apply custom widget for number type fields
        uiSchema[key] = { "ui:widget": custom_widget };
      }
    });
  };
  const schema: RJSFSchema = {
    type: "object",
    properties: {
      numberField1: {
        type: "integer",
      },
      numberField2: {
        type: "integer",
      },
      textField: {
        type: "string",
      },
    },
  };

  const CustomIntegerWidget = (props: WidgetProps) => {
    return (
      <div>
        <p>*Custom Widget*</p>
        <input
          type="number"
          className="custom-number-widget"
          value={props.value}
          required={props.required}
          onChange={(event) => props.onChange(event.target.value)}
        />
      </div>
    );
  };

  const uiSchema = {};
  ReplaceWidget(uiSchema, "integer", CustomIntegerWidget);

  return <Form schema={schema} uiSchema={uiSchema} validator={validator} />;
};

export default MyTest;
heath-freenome commented 4 months ago

@gitdrums By default updown widgets aren't used for numbers unless you update the uiSchema to tell it to. And it seems like you are already modifying the schema. Short of implementing this feature https://github.com/rjsf-team/react-jsonschema-form/issues/3960, what you are doing seems like the best approach.