simplrjs / react-forms Goto Github PK
View Code? Open in Web Editor NEWDeclarative forms for React
License: GNU Affero General Public License v3.0
Declarative forms for React
License: GNU Affero General Public License v3.0
I was implementing proper Field
behavior when rendered/removed from FieldsArray
(mounting/unmounting, to be precise) and noticed that Field
cannot be rendered outside of Form
.
But if I'm correct, it's as easy as adding formId
prop and updating FormId
getter to take that into account, not just context.FormId
.
This is what BaseContainer
does, inherently BaseFormButton
does and Form
itself does. Maybe setting formId
would enable some scenarios that we didn't yet encounter?
With the newest update, the validation is being initialized like so:
import { SubscriberContainer } from "simplr-validation/subscribers";
SubscriberContainer.Initialize();
It is a small thing and functionally works well, but it is the first thing that someone wanting to use validation will see and I think it's a bit tricky.
What I propose to do is:
a. Create an initialization method and expose it via main import, like so:
import { InitializeValidation } from "simplr-validation";
InitializeValidation();
Naming is subject to discussion, but the idea of having a function to call in the main import seems to be the best here. Any more ideas on naming or different approach at all?
In some cases, there might arise necessity to have transitional value:
a value that is not suitable for FormStore
yet, but is not invalid either.
Value:
123
Transitional value:
123.
Dot at the end is intentional, because the user might be typing 123.4
and value
that is suitable for FormStore is 123
, but while the user is typing the end value that one wants, there is a transitional value 123.
in between.
We should explore mechanism update for modifiers to have ability to return both values: correct one and a transitional one.
As the library is not yet released, breaking changes are acceptable.
From early usage outside of package development, I noticed that FieldOnChangeCallback
and FormOnSubmitCallback
have differences in their parameters.
FieldOnChangeCallback
has:
event
newValue
fieldId
store
And FormOnSubmitCallback
has:
event
store
While defining and using both callbacks in the same class like so:
onSubmit: FormOnSubmitCallback = (event, store) => {
// <...>
};
onChange: FieldOnChangeCallback<any> = (event, newValue, fieldId, formId) => {
// <...>
};
It seems that usage should differ, but in essence, it should not differ that much.
E.g. formId
is available in FieldOnChangeCallback
, but not in FormOnSubmitCallback
. Why so?
Also, store
is being passed into FormOnSubmitCallback
, but getting FormStore
in FieldOnChangeCallback
requires importing FSHContainer
and getting FormStore
with a dance like so:
const store = FSHContainer.FormStoresHandler.GetStore(formId);
Not pretty and could scare an inexperienced user.
Therefore, I suggest updating FieldOnChangeCallback
from:
export type FieldOnChangeCallback<TElement> = (
event: React.FormEvent<TElement>,
newValue: FieldValue,
fieldId: string,
formId: string
) => void;
To:
export type FieldOnChangeCallback<TElement> = (
event: React.FormEvent<TElement>,
newValue: FieldValue,
fieldId: string,
store: FormStore
) => void;
Changing the last parameter from formId
to store
.
Also, figuring out which form's store instance you have is a bit tricky at the moment, because FormId
property is protected
. As TypeScript does not allow us to have different visibility property getter and setter and we cannot make a protected setter and public getter, the solution here is a public GetFormId()
method on a FormStore
.
Another observation is that public methods like GetFieldId
, GetFieldsGroupid
and similar ones should be moved out into helpers, because they are cluttering public API.
Right now constructing error message is a bit limited, because fieldId
and fieldName
are not available during message construction, unless variable closure is used.
Therefore, error
prop in validators could take in a template function:
(fieldName, fieldId): string;
At the moment, only non-controlled fields are implemented. Controlled value should be handled also.
At the moment, usage of validators is not as smooth as I'd like it to be.
We should add default validator messages.
simplr-validation
is already an awesome library. One thing that I struggled while starting using it is showing the errors, which is kind of a main thing for the library.
I think we should create ErrorsContainer
or sth for an easy errors rendering.
We discussed a bit in Slack with @MartynasZilinskas, so we'll have something soon.
The concept of modifiers is powerful, but with great power comes great responsibility:
If the modifier is suitable for chaining, it is a bit more complex.
This is why we could have a notion of chainable: boolean
on the modifier.
/cc @GiedriusGrabauskas @MartynasZilinskas
Not sure about this one just yet. Let's discuss a bit more.
Submit component is rendered out of the form before form is mounted. If Submit component is unmounted before Form is mounted error is raised.
Error reproduction: https://codesandbox.io/s/yjq0mm6m11
Click Toggle submit
, then Toggle form
and you'll get the error.
I think for clarity, we should rename restProps
in all GetHTMLProps
methods to htmlProps
. It conveis the message more clearly.
Non default DOM components:
If form contains a set of Fields with a prop initialValue
and without a prop value
and a single Hidden
component with all required props defaultValue
, initialValue
and value
, Hidden field causes form Pristine
value change to false. You can supply same values for defaultValue
, initialValue
and value
- the outcome is still the same.
If you have a set of FieldsArray
s rendered and you remove one, form stays pristine.
Handle pasted value extraction including the sign (+, -, no sign) and sign entering on value change.
TransitionalValue enables adding signs and only the extraction regex has to be updated to accept the sign.
<Text name="Number" initialValue={"23.45"}>
<StringToDecimalModifier precision={2} delimiter="," />
</Text>
The resulting value is NaN
.
We still haven't figured out the proper way of modifier mechanism.
Thus Number field doesn't work as intended. For now, it will be left without modifier which restricts any not numeric or special characters (like minus or comma) usage in the field.
Input from users would be really helpful.
FieldGroup with a prop destroyOnUnmount={false}
throws an unexpected error:
Issue reproduction: https://codesandbox.io/s/6xmzoo05xr
Press Toggle
button two times (perform unmount and mount) to get the error.
There are types for FormProps.onChange
, but it is not used anywhere yet.
I guess there could be two roads here:
First one makes no sense to me as it would comprehend imperative API, which I don't really want to foster. Anyone can subscribe themselves to the store.
Second one adds responsibility for field developers to handle this and proxy the onChange of field into the form one. I guess this TODO
describes just that:
https://github.com/SimplrJS/simplr-forms/blob/dev/packages/simplr-forms-dom/src/components/text.tsx#L41
Also, at the moment, FormProps
has a property onChange
, but I think it's better to call it onFieldChange
to explicitly note that this is NOT a change happening on the form itself, but rather a proxied callback from a field.
Using versions in package.json
:
"@simplr/react-forms": "^4.3.3"
"@simplr/react-forms-dom": "^4.3.3"
Error:
[17:33:55] ERROR TS: D:/Projects/Admin/node_modules/@simplr/react-forms-dom/components/radio-group.d.ts(23,22): error TS2417: Class static side 'typeof RadioGroup' incorrectly extends base class static side 'typeof BaseDomField'.
Types of property 'childContextTypes' are incompatible.
Type 'ValidationMap<RadioGroupChildContext>' is not assignable to type 'ValidationMap<FieldChildContext>'.
Types of property 'FieldId' are incompatible.
Type 'Validator<RadioGroupChildContext> | undefined' is not assignable to type 'Validator<FieldChildContext> | undefined'.
Type 'Validator<RadioGroupChildContext>' is not assignable to type 'Validator<FieldChildContext> | undefined'.
Type 'Validator<RadioGroupChildContext>' is not assignable to type 'Validator<FieldChildContext>'.
Types of parameters 'object' and 'object' are incompatible.
Type 'FieldChildContext' is not assignable to type 'RadioGroupChildContext'.
Property 'RadioGroupOnChangeHandler' is missing in type 'FieldChildContext'.
[17:33:55] ERROR TS: D:/Projects/Admin/node_modules/@simplr/react-forms-dom/components/radio.d.ts(18,22): error TS2417: Class static side 'typeof Radio' incorrectly extends base class static side 'typeof BaseContainer'.
Types of property 'contextTypes' are incompatible.
Type 'ValidationMap<RadioParentContext>' is not assignable to type 'ValidationMap<BaseContainerParentContext>'.
Types of property 'FormId' are incompatible.
Type 'Validator<RadioParentContext> | undefined' is not assignable to type 'Validator<BaseContainerParentContext> | undefined'.
Type 'Validator<RadioParentContext>' is not assignable to type 'Validator<BaseContainerParentContext> | undefined'.
Type 'Validator<RadioParentContext>' is not assignable to type 'Validator<BaseContainerParentContext>'.
Types of parameters 'object' and 'object' are incompatible.
Type 'BaseContainerParentContext' is not assignable to type 'RadioParentContext'.
Type 'BaseContainerParentContext' is not assignable to type 'RadioGroupChildContext'.
Property 'RadioGroupOnChangeHandler' is missing in type 'BaseContainerParentContext'.
At the moment simplr-forms
are a bit untidy, because the library does not conform to all QuatroDev TSLint rules.
We need to setup tslint with full set of rules.
@MartynasZilinskas, maybe you could do this?
It seems impossible to see the placeholder for the <Number />
input element.
Whenever initialValue
/defaultValue
props are passed 0
, null
, undefined
or even ""
values the value="0"
HTML attribute is always rendered.
The only solution for displaying the placeholder is passing value=""
prop, but obviously the prop doesn't use the built-in onChange handling then and becomes non-editable.
<Number
name="somename"
placeholder={"Test placeholder"}
/>
As mentioned in #75, public API should not expose some methods that are not going to be used that often.
They should be moved into helpers.
Multiple sources of updates can occur while submit is in progress:
We should decide whether a general disabling mechanism should be in place or at least Reset and Clear buttons should be disabled.
formStore.ToObject()
Throw if the delimiter length is greater than 1, because only single character delimiters make sense.
Number validators
Implementation of NPM package Validator:
Other:
For a dev build of forms, there should be a type check after each value normalization.
If value type changes, an error should be thrown to use modifier for that.
On form being submitted, validation should be ran.
@MartynasZilinskas, you did the validation, is it implemented?
I found TODO
reminding me about this:
https://github.com/SimplrJS/simplr-forms/blob/dev/packages/simplr-forms-dom/src/components/form.tsx#L30
Modifiers Parse
methods should be executed in an order in which they are put in children
and Format
methods should be executed in reverse order to keep sanity.
Input from users would be really helpful.
Submit
component is rendered out of form before form is mounted. If form is mounted this error is raised.
Error reproduction: https://codesandbox.io/s/6wm6x6w2rn.
Press Toggle button (form mount is performed) to get the error.
When the precision in zero, the delimiter should not be allowed at all.
Quite a common scenario that people are almost used to is validation on blur, i.e. when the field looses focus. We should be able to implement this quite easily, shouldn't we?
FieldTemplate
is an easy way to wrap your field into a wanted structure.
Very convenient way of using the forms would be to have a builder constructing a form for a given object.
It would not be a declarative way of doing things, but I imagine it being more of a code-generation tool, than automagical builder, even though it would be used by many, I assume, it would have quite a few challenges by itself.
Just an idea for now, so no commitment.
In order to get FormStore
outside of form events (onChange, onSubmit, etc.), developer has to pass a custom formId
into Form
and use the same id to get FormStore
later on:
componentDidMount() {
const store = FSHContainer.FormStoresHandler.GetStore("form");
}
<Form formId="form">
{/* Fields go here */}
</Form>
To get the form store in a more convenient manner, it would be great to have onLoad
event on Form
where an instance of FormStore
would be passed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.