-
Notifications
You must be signed in to change notification settings - Fork 35
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
Dynamic forms #43
Comments
Forgive me if this is a bad question, but what would passing validators as props look like? |
@lewisf It should be the same way as it is right now but list of validators is passed via props. module Validator = {
let email = ...
let password = ...
};
render: _ =>
<FormContainer
...
validators=[
Validator.email,
Validator.password,
]
/> |
graphql_ppx uses GraphQL directives to pass pure functions for converting raw GraphQL data into more friendly Reason code. https://github.com/mhallin/graphql_ppx/blob/master/README.md#custom-field-decoders For me it looks similar and could be possible solution to passing validators. |
@baransu it's an option 👍 |
I’ll be working a little bit on dynamic forms in the next week so I’ll try to share my feedback with some code samples :) |
Another option is not dealing w/ custom DSL and use record and attributes: module NewArticleForm = [%form {
title: string,
body: string,
[@nest] authors: {
name: string,
url: option(string),
}
}]; But in this case nested array item can't be defined inline :( Prolly, we don't even need module NewArticleForm = [%form {
title: string,
body: string,
authors: array(Author.t),
}]; |
Scratch that, it won’t be possible to parse nested records. |
I've been playing with complex dynamic forms over the last few days that here is what I came up with. My schema is rather complex. It was initially the same schema as in #34: type state = {
name: string,
parts: list(part)
}
and part = {
image: string,
title: string,
subtitle: string,
buttons: list(button),
}
and button =
| UrlButton(url)
| PluginButton(plugin)
and url = {
id: string,
caption: string,
url: string,
}
and plugin = {
caption: string,
pluginId: string,
instanceId: string,
}; It's complex. I decided there is no way I can handle in the two-level nested record with reasonable API. So I changed the schema a little bit to have a better structure for my form. I ended up with this: type state = {
name: string,
parts: list(part),
buttons: list(button),
}
and part = {
image: string,
title: string,
subtitle: string,
buttons: list(string),
}
and button =
| UrlButton(url)
| PluginButton(plugin)
and url = {
id: string,
caption: string,
url: string,
}
and plugin = {
caption: string,
pluginId: string,
instanceId: string,
}; Right now it's better. Next step was to come up with a suitable type field =
| Name
| ButtonUrl(string)
| ButtonCaption(string)
| ButtonPlugin(string)
| ButtonContent(string)
| Part
| PartImage(string)
| PartTitle(string)
| PartSubtitle(string)
| PartButtons(string); Thanks to current Now it's a time to write code that updates correct elements in a list. But there comes a realization. We have to define our validators upfront. That's why I had to make some changes to
The current implementation works for my use case and I believe that with proper ppx we can reduce boilerplate a lot. Here is part of the application to present our solution to this problem: https://gist.github.com/baransu/4ff1086014693fe27c562d435c1ee461 |
@alexfedoseev do you think there is anything we can move into dynamic forms direction? |
@baransu Sorry for the delay, the current state of things is: I have a draft of types for lexer and tokenizer and it's pretty much it. My current situation is the following: I have a 2 main projects I'm working on right now—the client one and the personal one. The latter, the main consumer of this library, is in the pre-release mode and I need 1-2 months to clean things up for MVP. Besides the time concern, TBH I don't feel comfortable pushing such a big change without a solid test suite right before release so I would postpone this for some time. I'm really sorry for dragging this for so long but I have to finish some more prioritized work at the moment. |
@alexfedoseev No problem. I have a fork that I'm maintaining for my company project and it works really well. Just today I've changed dynamic validators thing and I'm testing how it works on few forms. I'll post my observations and changes in this issue for the future. I hope your personal project will be great! Let's get back to the topic once you have time again 🙂 |
Sounds good, thanks for understanding! |
Since I write my description of the changes I've made a few things changed and I would really like to describe how our fork looks right now.
We made one significant change to that. We replace that with concept of optionaly regenerating validators after some change. let genValidators: Form.state => list(Form.validator) and it can be passed as a optional argument to change function: type state = {
firstName: string,
lastName: string
};
type field = | FirstName | LastName
let updateFirstName = (firstName, state) => {...state, firstName};
let initialState = {firstName: "", lastName: ""};
let genValidators = _state => [
/* firstName and lastName validators */
];
let initialValidators = genValidators(initialState);
let change = firstName =>
form.change(
~field=FirstName,
/* it should probably be named regenerateValidators or something like this */
~validators=genValidators,
updateFirstName(firstName)
); It easly allow us to regenerate validators when form shape changes - for example by adding new element to list or removing one. It's also useful if items in your list change shape for example which is sometimes a case. You can check current state of the fork here: https://github.com/baransu/re-formality I really count on the feedback as I would really like to introduce those changes to the upstream repository so other can benefit too 🙂 And I think it's a starting point to think about ppx to reduce boilerplate as a this issue stands 🙂 |
@baransu In my initial sketch, I thought about making validators kinda static b/c validators list itself doesn't change over time, form state does. So you can provide all of them at the very beginning and never think about them afterwards. The main problem here is to represent array of entities in the current state. So internal structure needs to be changed to support these |
That makes a lot of sense but to be honest I have no idea how to handle those arrays with static set of validators. What do you think about my solution in particular? I’m trying to think about drawbacks. It works for our usecase but I would be happy to improve it to work for other people cases too |
I published RC ( |
After poking around dynamic forms implementation I don't see a sane way how to implement it w/o code generation.
I haven't figured out neither public api or exact internal implementation, just a rough prototype of config dsl:
I think from this I can get all data I need to generate proper
field
,state
and some more internal types and lets to make dynamic forms possible but before going into implementation of this dsl I need to figure out internal implementation first. Also, it will require validators to be passed via props which is not a big deal I guess (comparing to the bloated and confusing config w/o dsl).Not jumping into implementation yet and appreciate any feedback on it.
The text was updated successfully, but these errors were encountered: