Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Widgets with custom formData json output #1225

Closed
2 of 3 tasks
MoshiMoshi0 opened this issue Mar 17, 2019 · 10 comments
Closed
2 of 3 tasks

Widgets with custom formData json output #1225

MoshiMoshi0 opened this issue Mar 17, 2019 · 10 comments
Labels

Comments

@MoshiMoshi0
Copy link

Prerequisites

Description

Given this schema:

{
  "definitions": {
    "Color": {
      "type": "object",
      "properties": {
        "R": {
          "type": "integer"
        },
        "G": {
          "type": "integer"
        },
        "B": {
          "type": "integer"
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "Color": {
      "$ref": "#/definitions/Color"
    }
  }
}

the formData looks like this:

Actual behavior

{
  "Color": {
    "R": 255,
    "G": 0,
    "B": 0
  }
}

But is possible to make a widget that will make the output look like this?:

Expected behavior

{
  "Color": [255, 0, 0]
}

Looking at the docs the object widgets are not supported and I was not able to find any issues/feature request similar to this.

So I guess this is more of a feature request to support custom object type widgets and/or ability for widgets to output customizable formData.

In the end I wanted to create a color picker widget that would fill the R/G/B properties and then convert them to json array.

@epicfaace
Copy link
Member

Have you tried using ui:field, but with an array schema instead of an object schema? https://react-jsonschema-form.readthedocs.io/en/latest/advanced-customization/#custom-field-components

@MoshiMoshi0
Copy link
Author

So if I understand correctly you mean change the schema to this:

{
  "definitions": {
    "Color": {
      "type": "array",
      "minItems": 3,
      "maxItems": 3,
      "items": {
        "type": "integer"
      }
    }
  },
  "type": "object",
  "properties": {
    "Color": {
      "$ref": "#/definitions/Color"
    }
  }
}

And use ui:field to change how it is rendered on the form?

I guess that will work. But this was just a simple example, I have a few more cases like this, for example:

Schema:

{
  "definitions": {
    "List<Foo>": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/Foo"
      }
    },
    "Foo": {
      "type": "object",
      "oneOf": [
        {
          "title": "Bar",
          "$ref": "#/definitions/Bar"
        },
        {
          "title": "Baz",
          "$ref": "#/definitions/Baz"
        }
      ]
    },
    "Bar": {
      "type": "object",
      "properties": {
        "BarP": {
          "type": "integer"
        }
      }
    },
    "Baz": {
      "type": "object",
      "properties": {
        "BazP": {
          "type": "integer"
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "Test": {
      "$ref": "#/definitions/List<Foo>"
    }
  }
}

Current formData:

{
  "Test": [
    {
      "BarP": 1
    },
    {
      "BazP": 2
    }
  ]
}

But I need to include the selected option in the formData like this:

{
  "Test": [
    {
      "Type": "Bar",
      "BarP": 1
    },
    {
      "Type": "Baz",
      "BazP": 2
    }
  ]
}

@epicfaace
Copy link
Member

@devcompl I don't see how one could create a formData with properties (Type) that are not in the schema. For your example, we can modify the schema to look like this (and maybe use uiSchema to hide the Type field):

{
  "definitions": {
    "List<Foo>": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/Foo"
      }
    },
    "Foo": {
      "type": "object",
      "oneOf": [
        {
          "title": "Bar",
          "$ref": "#/definitions/Bar"
        },
        {
          "title": "Baz",
          "$ref": "#/definitions/Baz"
        }
      ]
    },
    "Bar": {
      "type": "object",
      "properties": {
        "Type": {
           "const": "Bar"
       },
        "BarP": {
          "type": "integer"
        }
      }
    },
    "Baz": {
      "type": "object",
      "properties": {
        "Type": {
           "const": "Baz"
        },
        "BazP": {
          "type": "integer"
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "Test": {
      "$ref": "#/definitions/List<Foo>"
    }
  }
}

Then your data would look like:

{
  "Test": [
    {
      "Type": "Bar",
      "BarP": 1
    },
    {
      "Type": "Baz",
      "BazP": 2
    }
  ]
}

@MoshiMoshi0
Copy link
Author

@epicfaace
thats why I thought about a feature where widgets could generate custom json, I guess this might be slightly out of scope for this project.

The const value should work, I will just add it when generating the schema. But it seems the form is not populated with the const value (demo), might be a bug?

@epicfaace
Copy link
Member

@devcompl Oh, I missed something in my schema -- it should also include "default": "Bar" etc. -- only then is the form actually populated with the value.

So the schema would look like this:

{
  "definitions": {
    "List<Foo>": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/Foo"
      }
    },
    "Foo": {
      "type": "object",
      "oneOf": [
        {
          "title": "Bar",
          "$ref": "#/definitions/Bar"
        },
        {
          "title": "Baz",
          "$ref": "#/definitions/Baz"
        }
      ]
    },
    "Bar": {
      "type": "object",
      "properties": {
        "Type": {
           "const": "Bar",
           "default": "Bar"
       },
        "BarP": {
          "type": "integer"
        }
      }
    },
    "Baz": {
      "type": "object",
      "properties": {
        "Type": {
           "const": "Baz",
           "default": "Baz"
        },
        "BazP": {
          "type": "integer"
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "Test": {
      "$ref": "#/definitions/List<Foo>"
    }
  }
}

@MoshiMoshi0
Copy link
Author

@epicfaace
It does not seem to work with oneOf, when you select a different option the const values are not populated in the form (demo)

@epicfaace
Copy link
Member

epicfaace commented Mar 19, 2019

@devcompl I believe your schema in the linked codepen has a small error, it should look like this: https://jsfiddle.net/epicfaace/j27t4rLq/

However, you are right in that the default value does not work when using oneOf. Do you mind opening up a separate issue about this?

@MoshiMoshi0
Copy link
Author

@epicfaace
I changed the schema a little to show that the default values are working, and that they dont work when using oneOf.

I found a few issues that seem similar to this: #1043, #768 and pr that aims to solve it: #579
Do you still want me to make a new issue?

@epicfaace
Copy link
Member

@devcompl

Do you still want me to make a new issue?

I think you should, this seems to be a problem specifically within oneOf which the other issues do not address. Also, it looks like #579 is stalled and no one is working on it, so if you think of another solution or want to work off of that PR I'd be glad to review that PR.

@MoshiMoshi0
Copy link
Author

@epicfaace
Ok, added #1229.

I'm closing this as its kinda off topic now.
Thanks for help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants