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

@ngx-formly/json-schema #1459

Closed
31 of 52 tasks
juristr opened this issue Mar 7, 2019 · 93 comments
Closed
31 of 52 tasks

@ngx-formly/json-schema #1459

juristr opened this issue Mar 7, 2019 · 93 comments

Comments

@juristr
Copy link
Collaborator

juristr commented Mar 7, 2019

1. Progress of supported schema:

  • string
    • Length (minLength, maxLength)
    • Regular Expressions (pattern)
    • Format
  • Numeric types
    • integer
    • number
    • Multiples (multipleOf)
    • Range (minimum, exclusiveMinimum, maximum and exclusiveMaximum)
      • minimum and maximum
      • exclusiveMinimum and exclusiveMaximum
  • object
    • Properties
    • Required Properties
    • Property names
    • Size
    • Dependencies
    • Pattern Properties
  • array
    • Items
    • Length
    • Uniqueness
    • contains
  • boolean
  • null
  • Generic keywords
    • Annotations (title, description, default)
    • Enumerated values
    • Constant values
  • Media: string-encoding non-JSON data
    • contentMediaType
    • contentEncoding
  • Combining schemas
    • allOf
    • anyOf
    • oneOf
    • not
  • Applying subschemas conditionally (if, then and else)
  • Structuring a complex schema
    • $ref
    • $id
  • extra options
    • widget
    • map
    • uiSchema
    • convert formly schema to json-schema

2. add @ngx-formly/json-schema

3.Docs

  • add guide section
  • improve demo examples
  • options
    • widget
    • map
    • uiSchema
@juristr
Copy link
Collaborator Author

juristr commented Mar 7, 2019

@aitboudad @kenisteward I've followed your issue #1348 and I'd like to start developing on some of those things (as mentioned in my original issue description), specifically I'd need

  • dynamic select boxes/autocompletes (i.e. where the data is fetched on the fly by giving it a source URL to the API)
  • datepickers

And for those, the main issues I'm currently encountering is

  1. where to define the "widget" to use, i.e. <select> or some custom autocomplete, basically what would then translate to some formly type.
  2. where to put custom attributes, like the source (or how you'd call it) property that specifies the URL where to fetch the entries for the select box

I started giving a look to:

They often use a widget property, which seems to be custom though, as I couldn't find it in the spec. We had a similar strategy, like for mapping an autocomplete of people like

{
  "title": "test",
  "type": "object",
  "properties": {
    "personId": {
      "type": "integer",
      "title": "Owner",
      "widget": {
        "type": "autocomplete",
        "source": "/api/options/people.json"
      }
    }
  }
}

What's your opinion on this?

@kenisteward
Copy link
Collaborator

kenisteward commented Mar 7, 2019 via email

@kenisteward
Copy link
Collaborator

kenisteward commented Mar 7, 2019 via email

@aitboudad
Copy link
Member

If you're ok with that, I'll post ideas on how to evolve the current implementation here to discuss with you

that's a good news, my thought about this part can be found here #1056 (comment)

what's currently possible

the majority of use-cases, except two parts which are mentioned in the V6 roadmap:

  • custom validation
  • allow passing custom UISchema

react-jsonschema-form is a good lib to follow, once we've done with that part, the next step is to wrap the FormlyJsonschema service within a component.

@juristr
Copy link
Collaborator Author

juristr commented Mar 7, 2019

I can post my findings here or start a new issue
for it

If ur ok, let's post here and use this as the main discussion issue around evolving the json-schema part of formly (if also @aitboudad agrees).

I've also taken some inspiration from
Angular6-json-schema-form.
The biggest issue with that project is it is not maintained.

Ya, I've quickly seen that one too. Well, if it is not maintained, we might take inspiration from their ideas and port it over.

Also one of the key things I wanted to do was to make sure we started with
the separate layout.json and allowed it to be combined later.

Sounds good for me, would love to get some more insight in your ideas.

Also one of the issues with the form given now is that you can't make
arbitrary wrapper elements in that form. You can only define fields for
elements. Defining arbitrary wrapper elements for grouping of elements is
basically a must have.

💯 agree.

@juristr
Copy link
Collaborator Author

juristr commented Mar 7, 2019

the majority of use-cases

@aitboudad how would you implement the "widget" scenario though? Like distinguishing between an autocomplete, date picker,...?

@aitboudad
Copy link
Member

how would you implement the "widget" scenario though? Like distinguishing between an autocomplete, date picker,...?

If I'm not mistaken that would be solved by UISchema which can be passed as a second argument to
FormlyJsonschema::toFieldConfig but I think your proposal is better if it's a valid json-schema.

@juristr
Copy link
Collaborator Author

juristr commented Mar 7, 2019

If I'm not mistaken that would be solved by UISchema

Yep I've seen the usage of UISchema in the react form example. The UISchema allows for sure to have more complex configurations, having a widget directly attached, makes it a bit easier to handle everything though, from the server side that generates the JSONSchema as well as the client-side. I've seen that being used in ngx-schema-form.
From a first check it seems to be "valid", in the sense it's being ignored as far as I could tell. Pasted it into the https://www.jsonschemavalidator.net/, although I'm not 100% sure that tool does a proper validation. I'll check.

Do you have any prefs on how that widget should be structured internally?

@aitboudad
Copy link
Member

Do you have any prefs on how that widget should be structured internally?

The more we're in line with the existing solution the more is better but always keep it simple,
if possible widget should be FormyFieldConfig which will be merged with the converted field:

mySchema = {
  "properties": {
    "pageContent": {
      "type": "string",
      "description": "Page content",
      "widget": {
        "type": "select",
        "templateOptions": {
          ...
        }
      }
    }
  }
}

well if that is allowed, it can be implemented easily by merging the converted field with the widget

@juristr
Copy link
Collaborator Author

juristr commented Mar 7, 2019

well if that is allowed, it can be implemented easily by merging the converted field with the widget

Agree 👍 . @kenisteward any insights from your part? Otherwise I'll provide a PR with a 1st implementation of the widget prop.

the widget.type would then overwrite the formlyFieldConfig.type in case it is specified. Thus if I have a formly type registered - say ng-select, then I could specify ng-select on that widget.type & it would automatically instantiate that formly field.

@kenisteward
Copy link
Collaborator

kenisteward commented Mar 7, 2019

@juristr

https://www.jsonschemavalidator.net/

is a reference to using schema 7 spec. In that, you are allowed to have any additional properties based on the base schema spec for a jsonSchema. That is why it doesn't fail.

Via remote url that returns [{ label: '...', value: ...}, ...]

The proper utilization for what should be returned in a schema is defined here:
json-schema-org/json-schema-spec#57 (comment)

This basically states that a value will be oneOf these schemas which are represented by const/title combination. Other libraries implement this as should we. This allows for your schema to define what your select list options should be.

https://hamidihamza.com/Angular6-json-schema-form/?set=ng-jsf&example=ng-jsf-select-list-examples&framework=material-design&language=en

is an example of the idea in angular6-json-schema-form

The reason I bring this up is what you could do is for the field add a $ref link to get a "schema" that is dynamically generated based on the values you want it in. That way when the fields are being built from the schema we can have them there. If your use case is for live updates as they type though then we'd just have to implement it in the field like you have it.

well if that is allowed, it can be implemented easily by merging the converted field with the widget

Agree 👍 . @kenisteward any insights from your part? Otherwise I'll provide a PR with a 1st implementation of the widget prop.

I'm not sure currently how we can use this setup to allow arbitrary wrappers for fields.
Example: https://hamidihamza.com/Angular6-json-schema-form/?set=ng-jsf&example=ng-jsf-flex-layout&framework=material-design&language=en

Adding the widget option would 100 percent allow us to have layout information for specific fields but I don't think it allows us to say:

with this example schema:

 {
   "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
      "first_name": { "type": "string" },
      "last_name": { "type": "string" },
      "address": {
        "type": "object",
        "properties": {
          "street_1": { "type": "string" },
          "street_2": { "type": "string" },
          "city": { "type": "string" },
          "state": {
            "type": "string",
            "enum": [ "AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE",
                "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA",
                "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS",
                "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND",
                "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD",
                "TN", "TX", "UT", "VT", "VI", "VA", "WA", "WV", "WI", "WY" ]
          },
          "zip_code": { "type": "string" }
        }
      }
    },
    "required": [ "last_name" ]
  }

Say:

I want to put first_name and last_name with address.street_1 on the same row
then put the rest of the fields within address inside a wrapper container element.

I think with formly, you normally have to create those "wrapper container" formgroups by hand and put what fields you want to in them (I did this with the first iteration of the form maker I'm trying internally).

Sorry for the wall of text :(

@aitboudad
Copy link
Member

I want to put first_name and last_name with address.street_1 on the same row
then put the rest of the fields within address inside a wrapper container element.

well it can be done :) here is an early implementation: https://stackblitz.com/edit/angular-rbv4qw

@aitboudad
Copy link
Member

in the end, I think we should provide both ways because for a large form it's better to separate your UI config from your schema.

@kenisteward
Copy link
Collaborator

@aitboudad THIS IS EVIL MAGIC SORCERY AND I LOVE IT!

I'm all for this type of layout.json.

If I understand this correct, we could also set a formly wrapper component set and have it generically handle making "sections". I see you just used a class here to get the point across and it looks great!

The only thing that was throwing me off is that in the schema that was input into the toFormlyConfig() function, it had the address.street1 in a different place than it should show in the original schema when validated but it properly was in the correct place in the form data. That may be because they are combined and so in the combined state it represents layout first and then the underlying data with the key names. the most important thing is to make sure that when the data is sent across it is in the proper format of the original "data schema" which I think this covers anyway.

in the end, I think we should provide both ways because for a large form it's better to separate your UI config from your schema.

100% agree. I'm personally working on multiple large form sets and have had to split them down and found it easier to work on with the two separate.

@juristr
Copy link
Collaborator Author

juristr commented Mar 8, 2019

Awesome guys 🎉. So I guess we can agree on the widget object being used. Let's start incrementally. Most probably on Monday I'll start with a first PR for implementing a select that can be bound to an API endpoint for fetching the data. I'll post my JSONSchema definition here before starting the implementation.

Thx for now :)

@kenisteward
Copy link
Collaborator

https://json-schema.org/understanding-json-schema/structuring.html

https://json-schema.org/latest/json-schema-core.html#rfc.section.8.3

This is something else I thought we want to make sure we support. Right now, the implementation knows nothing of $ref ( local or external reference ) the spec right now states that if $ref is found all of the validation keys ( type, minlength, maximum etc) should be pulled from ref and ignored in the schema referencing it. Annotations like $comment , title, description etc don't have to be. Different forms validators handle it differently.

Also in spec 8 (coming soon) there will be a definition for saying which pieces in a ref you want to take ( I think ).

@juristr
Copy link
Collaborator Author

juristr commented Mar 11, 2019

Alright, so I started implementing the select with dynamic data. @aitboudad I like the "MAGIC SORCERY" (as @kenisteward called it 😄 ) from your example.

I'd add the..

if (schema['widget']) {
    return reverseDeepMerge(field, schema['widget']);
}

...part into the current FormlyJsonschema. The only thing I'd change is to maybe move it into a sub-property of the widget. like

{
   ...
   widget: {
      formlyConfig: { ... }
   }
}

The main reason is to allow having other configs in the widget part as well, which Formly shouldn't just merge onto the config by default. Just like in my case with the select, I'm having

{
   ...
   widget: {
      source: '/api/options/people.json',
      formlyConfig: { 
        type: 'select'
     }
   }
}

That way, Formly automatically merges the select configuration, and after that I check for the source property and load the according data onto that templateOptions.options in whatever way I like.


Another point: What do you think about changing the current signature of the toFieldConfig in a way to add an optional mapFn?

toFieldConfig(jsonSchema: JSONSchema7, mapFn?: mappingCallbackFn): FormlyFieldConfig {
  ...
}

..where the mapFn is defined as

export type mappingCallbackFn = (mappedField: FormlyFieldConfig, mapSource: JSONSchema7) => FormlyFieldConfig;

That allows to hook that in and get called back by Formly for each field config. Basically the FormlyJsonschema would do its mapping first and then call the mapFn (if defined), passing the mapped FormlyFieldConfig + the original JSONSchema part that was used to create it.

This gives you full flexibility to hook into the mapping process if needed.

Any thoughts on this?

@aitboudad
Copy link
Member

Alright, so I started implementing the select with dynamic data. @aitboudad I like the "MAGIC SORCERY" (as @kenisteward called it smile ) from your example.

me too, that comment is much magic too 😄

The only thing I'd change is to maybe move it into a sub-property of the widget. like ...

it makes sense

Another point: What do you think about changing the current signature of the toFieldConfig in a way to add an optional mapFn?

I'm ok with that but I would prefer the following signature instead, to allow adding more options if needed.

toFieldConfig(jsonSchema: JSONSchema7, options: { mapFn?: mappingCallbackFn}): FormlyFieldConfig {
}

@juristr
Copy link
Collaborator Author

juristr commented Mar 11, 2019

I'm ok with that but I would prefer the following signature instead, to allow adding more options if needed.

Oh yes absolutely 👍

I'll submit a PR once I have it. (working on it again tomorrow probably)

@Adam-Michalski
Copy link

What about allowing a value to be validated against multiple criteria at the same time.

https://json-schema.org/understanding-json-schema/reference/combining.html

{
  "anyOf": [
    { "type": "string", "maxLength": 5 },
    { "type": "number", "minimum": 0 }
  ]
}
The keywords used to combine schemas are:

allOf: Must be valid against all of the subschemas
anyOf: Must be valid against any of the subschemas
oneOf: Must be valid against exactly one of the subschemas
All of these keywords must be set to an array, where each item is a schema.

In addition, there is:

not: Must not be valid against the given schema

Or
Is this element already implemented? I couldn't find it.

@aitboudad
Copy link
Member

@Adam-Michalski not yet, based on the provided description it shouldn't be hard to implement using the map callback until formly support that part.

I'll try to provide an example when time allows.

@aitboudad aitboudad changed the title WIP: Discussion around evolving @ngx-formly/core/json-schema @ngx-formly/json-schema Jun 2, 2019
@aitboudad aitboudad pinned this issue Jun 2, 2019
@aitboudad
Copy link
Member

Updated the summary of this issue :) to track all remaining features.
The $ref and dependencies are implemented a PR is scheduled next week 👍

Once done with the remaining part, in V6.1 the FormlyJsonschema service will be wrapped within a component and moved into a sub-package @ngx-formly/json-schema:

<formly-json-schema [schema]="schema" [uiSchema]="uiSchema" [options]="options">
<formly-json-schema>

@classifieds-dev
Copy link

classifieds-dev commented May 7, 2020

Would this issue be related to the error below?

zone-evergreen.js:171 Uncaught Error: [Formly Error] There is no type by the name of "object"

On the docs website object is being used. However, on my local when I use it I see that an error is thrown because object is not a valid type.

@aitboudad
Copy link
Member

@classifieds-dev you may need to register json-schema types as shown in our demo example json-schema/app.module.ts

@classifieds-dev
Copy link

Ah… thanks. That looks like the missing piece.

@classifieds-dev
Copy link

It doesn't look there is a release of this module yet. So it looks like I need to create my own module for now and copy over whatever I need and register it in the root right?

@aitboudad
Copy link
Member

@classifieds-dev yep, but the plan is to provide those types out of the box!

@beeman
Copy link
Collaborator

beeman commented May 7, 2020

@classifieds-dev yep, but the plan is to provide those types out of the box!

This sounds awesome, I'm happy to take a shot at implementing that.

Does that mean we need to implement those json-schema related types for each of the UI libs we support?

@aitboudad
Copy link
Member

@beeman Well we can start with the basic types already my main idea is to use the existing UI.

Example:

FormlyModule.forChild({
  types: [
    { name: 'checkbox', component: FormlyFieldCheckbox },
+   { name: 'boolean', extends: 'checkbox' },
  ],
}),

Note: use master branch.

@beeman
Copy link
Collaborator

beeman commented May 8, 2020

@aitboudad that looks great!

I've started with the checkbox in this PR: #2232

I'd love to get some feedback. If this is the way to go, I'll create a similar commit for each of the basic types.

@classifieds-dev

This comment has been minimized.

@classifieds-dev

This comment has been minimized.

@aitboudad

This comment has been minimized.

@ceelian
Copy link

ceelian commented Jun 10, 2020

What version of JSONSchema is this PR addressing and what schema versions are currently supported in V5?

@aitboudad
Copy link
Member

@ceelian JSONSchema7

@indiealexh
Copy link

Looking to use json schema format to use a date picker.

Anything I can do to help progress efforts toward the ability to use Date-picker from a json schema
type: string
formate: date-time
?

@Jelledb
Copy link

Jelledb commented Oct 5, 2020

So from the example that I found in the docs (https://stackblitz.com/angular/qkjrkdnqymvb?file=src%2Fapp%2Fobject.type.ts) I get the feeling that there is still a lot of setup and stuff to be done before being able to use formly 'out of the box' with JSON schema. Is it planned to include all these setup components etc in the core library so we don't have to do this ourselves?

For now it's just sad to see that there is so much setup code required.

@kenisteward
Copy link
Collaborator

kenisteward commented Oct 5, 2020 via email

@GertjanJ
Copy link

Hi, first of all, thank you for this awesome package! Not to sound rude but is there any eta on the resolving remote json-schema refs feature? I'll be waiting patiently :)

@kenisteward
Copy link
Collaborator

kenisteward commented Jan 26, 2021

Hi, first of all, thank you for this awesome package! Not to sound rude but is there any eta on the resolving remote json-schema refs feature? I'll be waiting patiently :)

@GertjanJ I had come up with a quick and dirty localized solution that I didn't want to share here yet. Now that' we are officially in production I'll see about adding it.

@aitboudad I may need some guidance on how you want to make use of async/await for remote references. If we leave it in the service it's fine because we can just convert that one function (from the json schema service) but if we move processing to the component it makes for uglier solutions.

@aitboudad
Copy link
Member

@kenisteward just go with the service solution

@aitboudad
Copy link
Member

json-schema will be marked as stable in V6, the current implementation cover 90% of use-cases mores improvements in V6 series I guess :).
I'm going to close this issue and other features should be opened in a serapate issue instead.
To get the new updates make sure to subscribe to our releases.

Selection_055

Happy coding!

@dhairyattpl
Copy link

How to have a custom validator in JSON SCHEMA

@dhairyattpl
Copy link

Dependency custom validator

@aitboudad
Copy link
Member

@dhairyattpl see #1982 (comment)

@HaidarZ
Copy link

HaidarZ commented Mar 3, 2023

@aitboudad @juristr

I intend to leverage the capabilities of ngx-formly extensively for my upcoming project. I have successfully implemented the solution using this technology for one of my clients, and it performed exceptionally well. Drawing upon my positive experience, I aim to take a step further and develop a product for my company.

I am reaching out to express my interest in utilizing json-schema as a fundamental format for defining my data structure, which I believe is a suitable choice as it is on track to becoming an official standard and has already been adopted by major corporations.

Although the library has fulfilled most of the standard's requirements, I have observed that there has been no progress on the related ticket for some time. Furthermore, after thoroughly reviewing all comments associated with this ticket, I am confident that your impressive service can enable us to implement the full standard.

In order to proceed, it would be immensely helpful to have detailed documentation that covers all aspects discussed in the ticket. Specifically, the mapping function, which facilitates custom manipulations of data, would be especially useful.

@aitboudad
Copy link
Member

In order to proceed, it would be immensely helpful to have detailed documentation that covers all aspects discussed in the ticket. Specifically, the mapping function, which facilitates custom manipulations of data, would be especially useful.

@HaidarZ Thanks for you feedback, we're aware of that, the progress is a little slow but its better than nothing. Also we would appreciated any help toward improving the doc and PR welcomed!

@rishabh413
Copy link

My project needs support for contentMediaType = text/html in json schema draft-7. My expectation is that ngx-formly will add an inline validation for string field with "contentMediaType": "text/html" if the string field is not valid HTML.

I understand that this capability is yet to be implemented. Is this the right issue for this request or should I open a new issue?

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

No branches or pull requests