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

imagining the next major version v3 #409

Open
albanm opened this issue Jan 30, 2023 · 13 comments
Open

imagining the next major version v3 #409

albanm opened this issue Jan 30, 2023 · 13 comments

Comments

@albanm
Copy link
Member

albanm commented Jan 30, 2023

What comes next ?

I think a few things converge toward rethinking and rewriting large parts of vjsf.

  • major versions of frameworks and greater maturity of libraries and schema specifications
  • performance issues on large schemas inherent to the way reactivity is implemented
  • accumulated experience from developers and users

Next are a few ideas about how things could look on the next major version. Some of these ideas are already detailed in issues, but I like having a more complete view of the future in a single document.

Target is Q2 or Q3 2023. In the meantime only bug fixes and small pull requests will be included in v2.

Development frameworks and tools

  • Vue 3
  • Vuetify 3
  • Typescript
  • Nuxt 3 for the doc (that will keep serving for development as well)

Do we keep building a dist ? I suspect most people use a toolchain that can load the lib from source code and build it inside their app.

Do we get back to using templates instead of render functions ? I think maybe the limitations we tried to circumvent are not so true anymore or not so important in the new architecture. If we do this we might clarify components import and improve overall maintainability.

Vocabulary / expressivity

  • define a layout vocabulary
  • implement first the simpler explicit layout management where a full layout has to be given as a prop
  • then create a lib (probably @koumoul/schema-layout) that will:
    • serve the layout vocabulary
    • validate that a layout is valid both against the vocabulary and against the schema it is supposed to serve
    • expose a schema2layout function that vjsf will use to implement implicit layout (this function will receive a schema with potential layout related annotations and return a fully explicit layout)
  • use a common data vocabulary in replacement of x-fromUrl and x-fromData ?
  • better distinction between disabled (fields are rendered but not active) and readonly (content is rendered purely for reading, does not even look like a form) ?
  • use standard json pointers for key, fullKey, fromData, reference to schema fragments in layouts, etc (let's have a look at how ajv implements $ref and $data)

Improved composition

The massive use of mixins works for now but we can do better. Explore the composition API of Vue 3.

I think the multi-root components have the potential for making many things simpler (for example an object rendered as a flat section can be rendered in a component without adding intermediate structure).

More generic/meta injection of custom components, slots, props, etc so that many use cases are covered without documenting tens of options.

Decoupling of core and lib components

The following is an initial proposition. It needs more thinking and testing.

The core:

  • manages layout object construction from schema and other layout object manipulations
  • manages model reactivity, root model immutability, full model initialization, etc
  • manages schema validation
  • manages data fetching
  • provides a generic component "vjsf-property"
    • renders the component provided by the lib "vjsf-property-lib" or a custom component or a slot, all with a homogenous signature (value, layout, errorMessages, @input, @change, etc.)
    • maybe also render some standard slots like before and after ?
    • uses the provide/inject pattern for awareness of ifs parent and children
  • renders vjsf-property once for the root object

The components lib:

  • provides a main "vjsf-property-lib" component that has a common props and events signature as simple as possible to work with the core vjsf-property component (value, layout, errorMessages, @input, @change) then uses components from the target UI framework (vuetify by default)
  • a few possibilities for nested rendering:
    • the lib component can in turn use the core vjsf-property to render child properties based on their "layout" prop
    • the core component can fill slots for the lib component

Ideally the core and the components lib would be sufficiently decoupled to allow for creating alternate component libs for other frameworks than vuetify. Maybe this project should even be separated into 'vue-json-schema-form' and 'vuetify-json-schema-form'. This is not a top priority and should not be done if it compromises maintenability.

Reactivity and performance

  • no recursivity of the root component (but the vjsf-property property described in next section would be recursive)
  • optional immutability on the root component (cloning of the root model)
  • allow for mutability of objects and arrays below root component

If we manage to implement a saner reactivity system and by leveraging the separation between the root component and vjsf-property component I think we can solve the annoying issue of external schema/data change and have more predictable behaviors in general.

Better responsive design

Similar logic to the usual responsive breakpoints (xs, sm, etc.), but based on the actual size available to the form (and invidually to each of its children). This should be solved in the core vjsf-property component so that when given to the lib component it has a single value to apply.

Do we keep using a 12 columns grid system like vuetify or do we use more generic percent based values ?

Do we implement responsive layout with flexbox directly in the core vjsf-property component or do we delegate this to the lib component ?

The responsive breakpoint should be usable at the lowest level possible to define the width of each property or at the highest level possible to define a totally different layout (change order, hide an avanced section, use expansion panels instead of tabs, etc.).

Also different layouts might be provided for editable and readOnly mode.

Schema validation

I really want to check if a very strong ajv integration could solve all our schema validation needs.

The core component vjsf-property would apply ajv on all its intermediate models. At an object level either a child already displays an error (we can know that using inject/provide mechanism) or the error is displayed on the current level.

We should look info ajv-errors and ajv-i18n and see if we can get error messages good enough for our users directly from ajv validation.

The validator could also be used to validate the internal vocabularies (cf section "Vocabulary / expressivity").

The validator could also be used detect the current item of a select based on oneOf/anyOf which would allow for a more permissive convention than the strict convention of a property with const value. Also we should have a look at the discriminator keyword for this question.

If we use ajv specifically then we could also use more functionality like Modifying data during validation. Initialization of the model from the schema inside the recursive rendering of vjsf has long been a source of complexity (we render recursively and immediately bubble up some changes that trigger re-renders, it is a circular mess). Using ajv to fill default values before rendering components might solve this issue at least partially.

With strong validation integration the tagline "Create beautiful and low-effort forms that output valid data" would become a hard reality instead of a moving target where we strive to cover more cases as we go.

Support JTD ?

See here for a discussion of JTD vs JSON schema. In my mind the most important case for JTD is the code generation capabilities (https://github.com/jsontypedef/json-typedef-codegen). Not only do you ensure validity at input validation, you can also ensure the safety of the code that manipulates the data afterward.

A strong integration of Ajv and the decoupling of layout vs schema might make supporting both specifications possible without too much hassle. In this case should the project be renamed (vue-json-form) ?

Warning : I am not sure yet that JTD has enough expressivity to support a good implicit layout generation.

Retro-compatibility

The core should manage retro-compatibility of schema annotations and at least some options. It should emit warnings for options that are no longer supported. Technical compatibility is not as much of a priority (props, slots, etc) as long as the functionality can be preserved with reasonable work from developers.

Compilation and tree-shaking

Ok, this one is not obvious but it could be a game-changer to extend legitimate uses of vjsf. In its current state I tend to use vjsf only when schemas are dynamically provided (by some sort of plugin system) or when I know that the application has broad usage of it. But if I have a small form in a standalone page I will not be using vjsf because I am too aware of the cost in source size, init time, etc. The idea to solve this is to introduce a compilation mode that would take a schema and options at build time and do these tasks:

  • validate the schema, the layout annotations, etc
  • prepare the extended layout info based on schema and options
  • compile the ajv validation functions necessary for form validation
  • create a list of imports with the UI components and composables actually needed to render a specific schema
  • create a custom vjsf-my-schema component in a file that wraps all the previous elements and provides an easy interface

This way we can achieve a much lighter integration:

  • close ajv integration without loading ajv on each client or compiling schema at runtime
  • less vjsf code boilerplate
  • include only the necessary ui components in the page bundle

This compilation could also include some other tools like json-schema-to-typescript so that the built component could have typed data bindings.

What I don't think I will do : compile the actual UI code for the schema, vue components will still be generic components, simply they won't be loaded if they are not used.

This approach would probably require a small script based integration at first, then I could work on a closer integration with build systems (a webpack loader ?).

@albanm
Copy link
Member Author

albanm commented Feb 5, 2023

I have been having a debate with myself about this draft these last few days. When I put all ideas together the scope becomes kind of scary, basically I would be building something very similar to jsonforms but even more ambitious. As I have always been wary of excessive layering it got me thinking. I mean stacking abstractions, creating new standards, building large collaborative organizations, etc, it's all good. But personally I am more of the type that gets things done with what is at hand, and do it fast if possible. By creating a monorepo it might be possible to strongly decouple some stuff without creating an organizational nightmare at each new functionality, but still I must strive to keep things simple and not forget that a good deal of power and simplicity comes from assuming some level of coupling.

Therefore I think I will skip on the creation of an external layout schema. Edition would not be very user-friendly and managing coherence with the schema and the data would be complex. I will stick with being very json schema first and using annotations. But I do intend to rethink these annotations : bring some new power and genericity to the syntax, and write a JSON schema vocabulary for them. I will also stick with strong vuejs coupling. I will try to decouple some core components from vuetify implementations, but as a way to better structure the code and facilitate extensibility and not to open the door to compatible implementations with other frameworks (not in this version anyway).

Other ideas like the strong ajv integration, better responsive layout, better reactivity, etc are still a go. JTD support could simply be documented by linking to the schema2td tool I am writing in another repo.

@isedwards
Copy link

@albanm - do you list anywhere the advantages of vjsf over jsonforms? Are there some capabilities in vjsf that don't exist in jsonforms?

@albanm
Copy link
Member Author

albanm commented Feb 19, 2023

No, I don't have the full picture in mind and I don't perfectly know the capabilities of jsonforms so I don't want to be too affirmative on the topic. But sill I would say that vjsf is a less ambitious project in term of scope but has more detailed stuff (nested array validation, external data fetch, vuetify slots, props, etc). Things are not perfect but vjsf aims at providing a schema first approach that doesn't let you get stuck once you need to get into more details of customization of the form.

I would also add that vjsf is currently in a low maintenance mode (sorry for the pending PRs), but it is temporary and the project is definitely not dead at all. Actively used professionally at my company and no plan to switch to another tool anytime soon.

@isedwards
Copy link

@albanm is the plan to release an initial Vuetify 3 version before Vue 2 reaches end of life on on December 31st, 2023?

@albanm
Copy link
Member Author

albanm commented Mar 7, 2023

Yes, for sure.

@RemiC2care
Copy link

Hi @albanm,

We use your vue2 vjsf ( and a pleasure to use ) and we are currently switching to vue3.

Is there a chance to have an update of vjsf in a near future?

Thanks a lot

@albanm
Copy link
Member Author

albanm commented Apr 20, 2023

Hello,

Vjsf 3 won't be ready soon (best-case scenario is somewhere around august or september). But it is more than a port to vue 3, it is a rethink of many things and a complete rewrite. I don't have the time to work on this major version and on a simpler compatibility version of vjsf 2 for vue 3. If someone wants to work on this and bring it to completion I am willing to accept pull requests (or add a link to a fork).

@RemiC2care
Copy link

Hello,

Thank you for you quick answer, keep the good work.
Bye

@ocostello
Copy link

Hi, is there any update to the expected date of a release supporting Vue 3?

@albanm
Copy link
Member Author

albanm commented Aug 29, 2023

I am working on it. Hard to evaluate the necessary time, but end of year is the last deadline with a alpha available probably in a month from now.

Same as before : I am working on a full rewrite with a pretty ambitious target that comes with some level of uncertainty. But I would be ok with linking to a fork with a more minimalist port of vjsf 2 to vue 3 if someone wants to work on it.

@albanm albanm mentioned this issue Sep 18, 2023
@MaciejDybowski
Copy link

@albanm is there a chance for a beta version for 3 to appear this month?

@albanm
Copy link
Member Author

albanm commented Oct 5, 2023

Yes, maybe more an alpha than a beta, but it is coming soon.

The latest documentation contains a recent version of the work in progress https://koumoul-dev.github.io/vuetify-jsonschema-form/master/ . Not usable yet, but it shows that many things are starting to take shape.

Most of the work is done in the new project json-layout.

@albanm
Copy link
Member Author

albanm commented Oct 13, 2023

fyi #420

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

No branches or pull requests

5 participants