Giter Club home page Giter Club logo

json-schema-form's People

Contributors

arjunan-k avatar brennj avatar davelange avatar dilvane avatar eng-almeida avatar gabrielremote avatar gabrielseco avatar jguddas avatar joaoalmeida-remote avatar joeynimu avatar maciej-remote avatar ollyd avatar remotecom avatar rylek90 avatar sandrina-p avatar tugayac avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json-schema-form's Issues

Conditionals attributes are not removed after the condition is unmatched

Problem

The following example is about description, but this happens with any conditional attribute (title, minimum, etc).

Given a form that asks for two fields is_full_time (yes/no) and hours (number). If yes is selected, then it shows a description warning about the maximum hours.

The JSON Schema is the following:

{
  "properties": {
    "is_full_time": {
      "type": "string",
      "title": "Is full time",
      "oneOf": [{ "const": "yes", "title": "Yes" }, { "const": "no", "title": "No" }]
    },
    "hours": { "type": "number", "title": "Hours per day" }
  },
  "allOf": [
    {
      "if": {
        "properties": { "is_full_time": { "const": "yes" } },
        "required": ["is_full_time"]
      },
      "then": {
        "properties": {
          "hours": {
            "description": "We recommend no more than 8 hours."
          }
        }
      }
    }
  ]
}

Steps to reproduce:

  1. In the playground add the schema above.
  2. Select Yes, the description shows up.
  3. Select No. The description should disappear but it remains 🐛
image

For this scenario, a workaround could be to undo the value by set description: "" in the else statement, like this:

"else": {
  "properties": {
    "hours": {
      "description": ""
     }
   }
}

But this ain't possible for every attribute. For example, if you set const: 10, there's no way to "undo" it. Same for any other type of validation.

Add support for $ref keyword

Hello!

First off I just want to share that this looks really great, and I'd love to be able to make use of the package!

Currently however I'm blocked by the missing support for the $ref keyword - I'm working with a pretty complicated schema (it's defined in multiple different files, but is almost 1000 lines when bundled together), and using internal $refs for organizational purposes.

I think there's a workaround here that would work for most of my use case, which is just to dereference those $refs in all locations when rendering the form; however we'd really prefer not to have to do that if at all possible!

Would you all be open to adding this to your roadmap, and if so, what sort of timeline do you think we'd be looking at for getting that change in?

Consider support `$ref` in jsonschema

Thanks for the great tool json-schema-form!
it is very helpful because it is headless and can be used in any framework.

In many json schemas generated by other tools (e.g. OpenAPI, Pydantic, ...), you may see the keyword $ref which is used to reference another schema. This is a very useful feature to avoid duplication and keep the schema DRY.

It would be great if json-schema-form can support this feature. I have tried to use it but it seems not working. I have also checked the documentation and the source code but I cannot find any information about this.

Most of cases, the $defs is defined in the same definition, so it should be easy to implement.

ex) #/$defs/Person will point to the definition of {"$defs": { "Person": {... } } } in the same file.

So, before parsing the schema, we can resolve the $ref and replace it with the actual definition.
I've wrote some simple pseudo code to demonstrate how it can be implemented. I hope this will be helpful.

function getRef(path: string, object: any): any {
  const keys = path.replace(/^#/, '').split('/');

  let current = object;
  for (const key of keys) {
    if (key in current) {
      current = current[key];
    } else {
      return null;
    }
  }

  return current;
}

function resolveRefs(object: any, rootObject: any = object): any {
  for (const key in object) {
    const value = object[key];
    if (typeof value === 'object' && value !== null) {
      if ('$ref' in value) {
        const resolved = getRef(value['$ref'], rootObject);
        if (resolved) {
          object[key] = resolved;
        } else {
          // throw new Error('Cannot resolve reference: ' + value['$ref']);
          console.error('Cannot resolve reference:', value['$ref']);
        }
      } else {
        // go recursive
        resolveRefs(value, rootObject);
      }
    }
  }
  return object;
}

Then, add option to the createHeadlessForm function to enable this feature.

const { fields, handleValidation } = createHeadlessForm(schema, {
  resolveRefs: true, // or the referable other schema
})

I hope this feature will be implemented in the future. Thanks!

Inquiry about Roadmap

I've been using the library for my personal projects, and it's been excellent. I plan on using the library for a work project and was wondering if we could get some information on the future plans/roadmap for a stable release version.

Thanks!

Public roadmap

Currently the roadmap for json-schema-form is private for Remote only. We plan to move it to GitHub soon.

Custom Error Messages doesn't work in JSF Config

Given the following JSON Schema, I cannot override errorMessage using createHeadlessForm()

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "browsers": {
      "title": "Browsers (solo)",
      "description": "This solo select also includes a disabled option.",
      "type": "string",
      "oneOf": [
        {
          "const": "chr",
          "title": "Chrome"
        },
        {
          "const": "ff",
          "title": "Firefox"
        },
        {
          "const": "ie",
          "title": "Internet Explorer",
          "disabled": true
        }
      ],
      "x-jsf-presentation": {
        "inputType": "select"
      }
    },
    "has_pet": {
      "title": "Has Pet",
      "description": "Do you have a pet?",
      "oneOf": [
        {
          "title": "Yes",
          "const": "yes"
        },
        {
          "title": "No",
          "const": "no"
        }
      ],
      "x-jsf-presentation": {
        "inputType": "radio"
      },
      "type": "string"
    },
    "pet_name": {
      "title": "Pet's name",
      "description": "What's your pet's name?",
      "x-jsf-presentation": {
        "inputType": "text"
      },
      "type": "string",
      "errorMessage": "string"
    }
  },
  "required": ["has_pet"],
  "x-jsf-order": ["has_pet", "pet_name"],
  "allOf": [
    {
      "if": {
        "properties": {
          "has_pet": {
            "const": "yes"
          }
        },
        "required": ["has_pet"]
      },
      "then": {
        "required": ["pet_name"]
      },
      "else": {
        "properties": {
          "pet_name": false
        }
      }
    }
  ]
}

JSF Config:

    const { fields, handleValidation } = createHeadlessForm(Schema, {
      inputTypes: {
        errorMessage: {
          required: 'This cannot be empty.',
        },
      },
    });

This is very important to be able to i18n in the application

bug: breaks with complex schema

Screenshot 2023-06-23 at 11 13 04
{
  $schema: 'http://json-schema.org/draft-04/schema#',
  $id: 'https://example.com/employee.schema.json',
  title: 'Input',
  description: 'Soooooooo meee',
  type: 'object',
  properties: {
    id: {
      description: 'A unique identifier for an employee',
      type: 'number',
    },
    name: {
      description: 'Full name of the employee',
      type: 'string',
    },
    age: {
      description: 'Age of the employee',
      placeholder: 'Age of the employee',
      type: 'number',
    },
    maggies: {
      description: 'maggies of the employee',
      type: 'object',
      properties: {
        name: {
          description: 'Full name of the employee',
          type: 'string',
        },
        age: {
          description: 'Age of the employee',
          placeholder: 'Age of the employee',
          type: 'number',
        },
      },
    },
    dependent_details: {
      items: {
        properties: {
          birthdate: {
            description: 'Enter your child’s date of birth',
            format: 'date',
            'x-jsf-presentation': {
              inputType: 'date',
            },
            title: 'Child Birthdate',
            type: 'string',
            maxLength: 255,
          },
          full_name: {
            description: 'Enter your child’s full name',
            'x-jsf-presentation': {
              inputType: 'text',
            },
            title: 'Child Full Name',
            type: 'string',
            maxLength: 255,
          },
          sex: {
            description:
              'We know sex is non-binary but for insurance and payroll purposes, we need to collect this information.',
            enum: ['female', 'male'],
            'x-jsf-presentation': {
              inputType: 'radio',
              options: [
                {
                  label: 'Male',
                  value: 'male',
                },
                {
                  label: 'Female',
                  value: 'female',
                },
              ],
            },
            title: 'Child Sex',
          },
        },
        'x-jsf-order': ['full_name', 'birthdate', 'sex'],
        required: ['full_name', 'birthdate', 'sex'],
        type: 'object',
      },
      'x-jsf-presentation': {
        inputType: 'group-array',
        addFieldText: 'Add new field',
      },
      title: 'Child details',
      description: 'Add the dependents you claim below',
      type: 'array',
    },
    optional_dependent_details: {
      items: {
        properties: {
          birthdate: {
            description: 'Enter your child’s date of birth',
            format: 'date',
            'x-jsf-presentation': {
              inputType: 'date',
            },
            title: 'Child Birthdate',
            type: 'string',
            maxLength: 255,
          },
          full_name: {
            description: 'Enter your child’s full name',
            'x-jsf-presentation': {
              inputType: 'text',
            },
            title: 'Child Full Name',
            type: 'string',
            maxLength: 255,
          },
          sex: {
            description:
              'We know sex is non-binary but for insurance and payroll purposes, we need to collect this information.',
            enum: ['female', 'male'],
            'x-jsf-presentation': {
              inputType: 'radio',
              options: [
                {
                  label: 'Male',
                  value: 'male',
                },
                {
                  label: 'Female',
                  value: 'female',
                },
              ],
            },
            title: 'Child Sex',
          },
        },
        'x-jsf-order': ['full_name', 'birthdate', 'sex'],
        required: ['full_name', 'birthdate', 'sex'],
        type: 'object',
      },
      'x-jsf-presentation': {
        inputType: 'group-array',
        addFieldText: 'Add new field',
      },
      title: 'Child details (optional)',
      description:
        'This is an optional group-array. For a better UX, this Component asks a Yes/No question before allowing to add new field entries.',
      type: 'array',
    },
    hobbies: {
      description: 'Hobbies of the employee',
      type: 'object',
      properties: {
        indoor: {
          type: 'array',
          items: {
            'x-jsf-presentation': {
              inputType: 'text',
            },
            description: 'List of indoor hobbies',
            type: 'string',
          },
        },
        outdoor: {
          type: 'array',
          title: 'Child details',
          description: 'List of outdoor hobbies',
          items: {
            description: 'List of outdoor hobbies',
            type: 'object',
            properties: {
              indoor: {
                type: 'array',
                items: {
                  description: 'List of indoor hobbies',
                  type: 'string',
                },
              },
              outdoor: {
                type: 'array',
                items: {
                  description: 'List of outdoor hobbies',
                  type: 'string',
                },
              },
            },
          },
        },
        maggies: {
          description: 'Hobbies of the employee',
          type: 'object',
          properties: {
            indoor: {
              type: 'array',
              items: {
                description: 'List of indoor hobbies',
                type: 'string',
              },
            },
            outdoor: {
              type: 'array',
              items: {
                description: 'List of outdoor hobbies',
                type: 'string',
              },
            },
          },
        },
      },
    },
  },
  required: ['id'],
}

The above schema breaks the form due to this part here

outdoor: {
          type: 'array',
          title: 'Child details',
          description: 'List of outdoor hobbies',
          items: {
            description: 'List of outdoor hobbies',
            type: 'object',
            properties: {
              indoor: {
                type: 'array',
                items: {
                  description: 'List of indoor hobbies',
                  type: 'string',
                },
              },
              outdoor: {
                type: 'array',
                items: {
                  description: 'List of outdoor hobbies',
                  type: 'string',
                },
              },
            },
          },
        },

Would have loved to make a fix, but I'm encumbered

custom errorMessage by field name doesn't work.

Given the following JSON Schema, I cannot override its errorMessage using createHeadlessForm()

{
  "properties": {
    "year": {
      "title": "Year",
      "type": "number",
      "presentation": {
        "inputType": "number"
      },
      "x-jsf-errorMessage": {
        "required": "Cannot be empty."
      },
      "minimum": 1900,
      "maximum": 2023
    }
  },
  "required": ["year"]
}

JSF Config:

const { fields } = createHeadlessForm(schemaAbove, {
  customProperties: {
    year: {
      errorMessage: {
        required: "The year is mandatory."
      }
    }
  }
})

Missing documentation for 'formValuesToJsonValues'

It looks like yall are trying to put this function in to the repo so it simplifies for those looking to implement your library. I have come across your library and I am using it for my SaaS platform. Its been good so far pretty straight forward with good enough documentation. How ever I am stuck on shaping the jsonValues in regards to the group-array type so I can get some validation running. Everything else is working fine with validation and errors for my form except for the nested inputs inside my group-arrays. How should I approach this or can you get me a developer preview on what the 'formValuesToJsonValues' function is going to look like that y'all are planning to ship with the library.

Example of Json Values I'm passing to handleValidation:

{ "club_code": "Dallas - Uptown", "team_member_last_name": "d", "team_member_email": "[email protected]", "team_member_street_address": "409 St", "team_member_city": "Bville", "team_member_state": "AK", "expense_details": [ { "amount": "32324", "receipt": "<redacted url>" } ] }

The group array expense_details has 5 required fields and the overall form has many required fields and returns back

{ "team_member_first_name": "Required field" }

Which is accurate for the main part of the form its just not validating my group-array.

Any assistance on this would be greatly appreciated. Also happy to provide more details as needed. Thanks.

docs examples

Maybe you can make public the docs examples, that would be of help to many.

Add a default export

Only one issue with sveltekit, I had to manually jam a default eport in there, could you please add a default clause?

Better error messages when given a non-supported JSON Schema

Problem

Currently, given a JSON Schema not supported by json-schema-form, the error message is hard to understand and trace back to where the problem originates from.

Solution

Evaluate a JSON Schema structure before trying to parse it, to spot and warn about invalid types.

For example, in this #21 , the error should be:

- JSON Schema invalid TypeError: innerFields.forEach is not a function
+ JSON Schema invalid: data/properties/hobbies/items/type must be object

Investigate the possibility of using TypeScript, Zod, or any other typing tool for this type check.

InitialValues Problem

Hi,

I am evaluating your library. Therefore I would like to prefill a form with values.

I use pass initialValues to createHeadlessForm() like this

export default function WithReact() {
  const { fields, handleValidation } = createHeadlessForm(jsonSchemaDemo, {
    strictInputType: false, // so you don't need to pass presentation.inputType
    initialValues: { name: "Initial value" },
  });
...

I can't get this to work tough with your demo on the quickstart page. The initialValue is ignored.
Is this the correct way or am I missing something?

Here is an example btw:
https://codesandbox.io/p/sandbox/json-schema-form-demo-react-forked-5sfc7d

select inputType and number type

i have this json schema

{
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "AccountType": {
            "title": "Select account type",
            "description": "",
            "x-jsf-presentation": {
                "inputType": "select"
            },
            "oneOf": [
                {
                    "title": "Normal User",
                    "const": 0
                },
                {
                    "title": "Business",
                    "const": 1
                },
                {
                    "title": "Services Provider",
                    "const": 2
                }
            ],
            "type": "number"
        }
    },
    "required": [],
    "x-jsf-order": [
        "AccountType"
    ]
}

and on validation cannot accepts that value must be number and not string
as the output field is (it has schema type : string)

{
    "type": "select",
    "name": "AccountType",
    "label": "Select account type",
    "options": [
        {
            "label": "Normal User",
            "value": 0
        },
        {
            "label": "Business",
            "value": 1
        },
        {
            "label": "Services Provider",
            "value": 2
        }
    ],
    "required": false,
    "inputType": "select",
    "jsonType": "number",
    "computedAttributes": {},
    "description": "",
    "errorMessage": {},
    "schema": {
        "_deps": [],
        "_conditions": [],
        "_options": {
            "abortEarly": true,
            "recursive": true
        },
        "_exclusive": {},
        "_whitelist": {
            "list": {},
            "refs": {}
        },
        "_blacklist": {
            "list": {},
            "refs": {}
        },
        "tests": [],
        "transforms": [
            null,
            null
        ],
        "type": "string",
        "_type": "string",
        "_nullable": true
    },
    "scopedJsonSchema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
            "AccountType": {
                "title": "Select account type",
                "description": "",
                "x-jsf-presentation": {
                    "inputType": "select"
                },
                "oneOf": [
                    {
                        "title": "Normal User",
                        "const": 0
                    },
                    {
                        "title": "Business",
                        "const": 1
                    },
                    {
                        "title": "Services Provider",
                        "const": 2
                    }
                ],
                "type": "number"
            }
        },
        "required": [],
        "x-jsf-order": [
            "AccountType"
        ]
    },
    "isVisible": true
}

handleValidation for nested conditions is not working

Given the following JSON Schema, and handleValidation({}) for nested conditions is not working: Cannot read properties of undefined (reading 'country')

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "location": {
            "title": "Delivery location",
            "x-jsf-presentation": {
                "inputType": "fieldset"
            },
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "address1": {
                    "type": "string"
                },
                "address2": {
                    "type": "string"
                },
                "city": {
                    "type": "string"
                },
                "country": {
                    "type": "string"
                },
                "state": {
                    "type": "string"
                },
                "zip": {
                    "type": "string"
                }
            },
            "required": [
                "country"
            ]
        },
        "test": {
            "title": "Test",
            "type": "string",
            "x-jsf-presentation": {
                "inputType": "text",
                "step": "additional"
            }
        }
    },
    "required": [
        "location"
    ],
    "allOf": [
        {
            "if": {
                "properties": {
                    "location": {
                        "properties": {
                            "country": {
                                "const": "US"
                            }
                        },
                        "required": [
                            "country"
                        ]
                    }
                },
                "required": [
                    "location"
                ]
            },
            "then": {
                "required": [
                    "test"
                ]
            },
            "else": {
                "properties": {
                    "test": false
                }
            }
        }
    ]
}

Github: Create templates for issues and PR

Problem

Currently we do not have any github template for issues or PR.

Proposal

Create:

  • Issue template for feature requests
  • Issue templates for bugs
  • Issue templates for questions
  • PR template

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.