Skip to content

Commit ccb0c2d

Browse files
Merge branch 'master' into dev
2 parents da2b41c + 1041c76 commit ccb0c2d

File tree

5 files changed

+337
-6
lines changed

5 files changed

+337
-6
lines changed

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# simplr-forms
2-
The only forms for React you will ever need
2+
Declarative forms for React.
3+
4+
Includes declarative modifiers, normalizers and validators.
35

46
At the moment library is work-in-progress. We will try to document some of the notes here, in GitHub.
57
Feel free to comment on [PRs](https://github.com/SimplrJS/simplr-forms/pulls?utf8=%E2%9C%93&q=is%3Apr%20) and open [issues](https://github.com/SimplrJS/simplr-forms/issues).
@@ -10,11 +12,15 @@ Initial development is happening in the [dev](https://github.com/SimplrJS/simplr
1012

1113
Development right now is being done by [SimplrJS](https://github.com/SimplrJS) team inside [QuatroDev](http://quatrodev.com):
1214
* [Dovydas](https://twitter.com/dovydasnav) (QuatroDev) [[GH](https://github.com/DovydasNavickas)]
13-
* [Martynas](https://twitter.com/MartiogalaLT) (QuatroDev) [[GH](https://github.com/MartynasZilinskas)]
15+
* [Martynas](https://twitter.com/MartinZilinskas) (QuatroDev) [[GH](https://github.com/MartynasZilinskas)]
1416
* [Giedrius](https://twitter.com/Giedrucis) (QuatroDev) [[GH](https://github.com/GiedriusGrabauskas)]
1517
* Deividas (QuatroDev) [[GH](https://github.com/DeividasBakanas)]
1618

1719
### Notes
1820

19-
* [2017-04-08 Initial notes](https://github.com/SimplrJS/simplr-forms/blob/master/docs/2017-04/2017-04-08.md)
20-
* [2017-04-14 Progress update](https://github.com/SimplrJS/simplr-forms/blob/master/docs/2017-04/2017-04-14.md)
21+
Notes can be found in this repo and in Medium:
22+
23+
* [Part 1: Why are we doing this?](https://medium.com/@DovydasNavickas/part-1-simplr-forms-declarative-forms-for-react-why-are-we-doing-this-293b9a9c45bd)
24+
* [Part 2: Core, validation, testing.](https://medium.com/@DovydasNavickas/part-2-simplr-forms-declarative-forms-for-react-core-validation-testing-fd9494304305)
25+
* [Part 3: First e2e flow, FormStore.ToObject()](https://medium.com/@DovydasNavickas/part-3-simplr-forms-declarative-forms-for-react-first-e2e-flow-formstore-toobject-ed81d930e14c)
26+
* [Part 4: Normalizers and Modifiers](https://medium.com/@DovydasNavickas/part-4-simplr-forms-declarative-forms-for-react-normalizers-and-modifiers-6cefbd0269c4)

docs/2017-04/2017-04-08.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
### Attendees
44

55
* [Dovydas](https://twitter.com/dovydasnav) (QuatroDev)
6-
* [Martynas](https://twitter.com/MartiogalaLT) (QuatroDev)
6+
* [Martynas](https://twitter.com/MartinZilinskas) (QuatroDev)
77

88
### Why do we need yet another forms library?
99

docs/2017-04/2017-04-14.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
### Attendees
44

55
* [Dovydas](https://twitter.com/dovydasnav) (QuatroDev)
6-
* [Martynas](https://twitter.com/MartiogalaLT) (QuatroDev)
6+
* [Martynas](https://twitter.com/MartinZilinskas) (QuatroDev)
77
* [Giedrius](https://twitter.com/giedrucis) (QuatroDev)
88
* [Aurimas](https://twitter.com/waikys) (QuatroDev)
99

docs/2017-04/2017-04-26.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
## April 26 ([discuss](https://github.com/SimplrJS/simplr-forms/pull/26))
2+
3+
### Attendees
4+
5+
* [Dovydas](https://twitter.com/dovydasnav) (QuatroDev)
6+
* [Martynas](https://twitter.com/MartinZilinskas) (QuatroDev)
7+
8+
### State of mind
9+
10+
:tada: :clap: :tada: :clap: :tada: :clap: :tada: :clap: :tada: :clap: :tada: :clap:
11+
12+
### Sooooo... What happened?
13+
14+
After quite a bit of work, a first e2e workflow now forks. Non-test, but a working browser example!
15+
16+
### So... How does it look?
17+
18+
Technical. No styles, no nothing, just two text fields and a form. And you can submit the form (this one is big for the library :smile:).
19+
20+
### And if we spoke code?
21+
22+
Right. So the exciting part is that everything works as planned:
23+
24+
A declarative and intuitive way to build forms.
25+
26+
The whole react application including the form looks like this:
27+
```ts
28+
import * as React from "react";
29+
import * as ReactDOM from "react-dom";
30+
import "tslib";
31+
import { FormStore } from "simplr-forms-core/stores";
32+
import { Form, Text, Submit } from "simplr-forms-dom";
33+
34+
export class MyForm extends React.Component<{}, { formId: string }> {
35+
protected onSubmit: any = (event: React.FormEvent<HTMLFormElement>, store: FormStore) => {
36+
console.log("Submitting...");
37+
console.log(store.ToObject());
38+
};
39+
40+
render() {
41+
return <Form onSubmit={this.onSubmit}>
42+
<label>
43+
Full name:
44+
<Text name="FullName" />
45+
</label>
46+
<label>
47+
Email:
48+
<Text name="Email" />
49+
</label>
50+
<Submit>Submit</Submit>
51+
</Form>;
52+
}
53+
}
54+
55+
ReactDOM.render(<MyForm />, document.getElementById("react-root"));
56+
```
57+
58+
When rendered, it's a plain form:
59+
60+
![image](https://cloud.githubusercontent.com/assets/7989797/25414223/08425d84-2a39-11e7-869a-be440991c688.png)
61+
62+
And even html rendered is as plain as it can be:
63+
64+
![image](https://cloud.githubusercontent.com/assets/7989797/25414636/420efba6-2a3b-11e7-886a-31542e057432.png)
65+
66+
It's not "like" a `plain HTML form`. It IS a plain HTML form.
67+
68+
But when filled and submitted, it prints this into console:
69+
70+
![image](https://cloud.githubusercontent.com/assets/7989797/25414252/36c56c78-2a39-11e7-8831-cbcfdc4fcc2b.png)
71+
72+
Can you see it already? :smile:
73+
74+
Declarative form with an intuitive, almost default `onSubmit`, where getting an object of the whole form boils down to this:
75+
```ts
76+
store.ToObject()
77+
```
78+
79+
The only difference from the "default" `onSubmit` is that you get `FormStore` as a second parameter into the handler. And that is only for your convenience. You can take it in a few different ways, if you want.
80+
81+
And what `FormStore` gives you is simplicity. The `ToObject()` method takes care of knowing how to transform data in the store into a plain object. You don't have to take care of any refs, values, nothing. Name your fields with.. Well, `name`. And you're good to go!
82+
83+
Easy? Super easy!
84+
85+
### That's amazing? But... Where's everything else?
86+
87+
This simple example shows what works e2e at this very moment, but even here, quite a lot of things are handled behind the scenes:
88+
* Form is registered with `FormStoresHandler` and `FormStore` is initiated.
89+
* `formId` is not given, therefore it is generated automatically for you.
90+
* Both `text` fields are registered with the same store with the same generated `formId` and you didn't have to do anything!
91+
* `Submit` button used here is from `simplr-forms-dom`, but no custom logic is being used in this example. It's basically your default `<button type="submit">Submit</button>` and it could be one. Because effectively this one is, as you can see in the HTML shown above :+1: No custom click handlers, nothing. Plain button of type `submit`.
92+
* Everything behind the scenes updates data in the `FormStore` for you and you can already listen to actions coming from `FormStore` and do what you need accordingly.
93+
94+
Also, I'm pretty sure `Modifiers` and `Normalizers` would work already, but did not test that yet.
95+
`Validators` with `simplr-validation` package also do what they are supposed to do (kudos to [Martynas](https://twitter.com/MartiogalaLT) for that one).
96+
97+
Oh, riiight. Since the last post almost two weeks ago, [Martynas](https://twitter.com/MartiogalaLT) has already finished an initial version of `simplr-validation` and we will test it out soon and make the forms ready for it.
98+
99+
### So the validation is tightly coupled with forms and not externalized...
100+
101+
No! Well, yes, but no! :smile:
102+
103+
It is coupled only by a public API that `simplr-forms-core` exposes and that's it.
104+
105+
You already can create your own validation library and just use the same public API and you're good to go!
106+
107+
Why am I so sure? Because, `simplr-validation` does just that.
108+
109+
### Awesome. What's next?
110+
111+
Until we can ship a solid alpha, we need to have:
112+
* Most commonly used HTML components covered in `simplr-forms-dom`.
113+
* Modifiers and Normalizers working.
114+
* Validation working with `simplr-forms-dom`.
115+
116+
Until we can ship a solid beta, we need to have:
117+
* All HTML components covered in `simplr-forms-dom`.
118+
* Reliably working `FieldsGroup`.
119+
120+
As soon as we have something solid, we will ask a few people to test it out. And for the mean time, yay for a first e2e flow!
121+
122+
------------
123+
124+
The feedback and questions are more than welcome!
125+
126+
------------
127+
128+
Please feel free to discuss these notes in the [corresponding pull request](https://github.com/SimplrJS/simplr-forms/pull/26).

docs/2017-04/2017-04-27.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
## April 27 ([discuss](https://github.com/SimplrJS/simplr-forms/pull/29))
2+
3+
### Attendees
4+
5+
* [Dovydas](https://twitter.com/dovydasnav) (QuatroDev)
6+
* [Martynas](https://twitter.com/MartinZilinskas) (QuatroDev)
7+
8+
### What's new?
9+
10+
`Modifiers` and `Normalizers` work properly with fields!
11+
12+
### Soooo... What are those?
13+
14+
Let's start with `Normalizers`. If you ever needed to make sure your input is all lower-case, upper-case or alphanumeric, think how would you approach that scenario.
15+
16+
Now look at this. I introduce to you: `Normalizers`.
17+
18+
Imagine you need a form for a promo code. It has a few limitations: it's upper-case and alphanumeric characters only.
19+
20+
You could let user enter whatever input and then take what's needed, stripping all spaces and symbols away.
21+
22+
But that is not user friendly, because user cannot see what's happening behind the scenes and their imput is being modifier without any visual feedback.
23+
24+
You could also take `onChange` event and enforce required rules there, setting the value to the filtered one after each key stroke.
25+
But the logic gets messy and it's an imperative approach to solve this problem.
26+
27+
What if you could take this familiar form application (yep, that's the whole application, if you didn't read [the last post](https://github.com/SimplrJS/simplr-forms/blob/master/docs/2017-04/2017-04-26.md)):
28+
```tsx
29+
import * as React from "react";
30+
import * as ReactDOM from "react-dom";
31+
import "tslib";
32+
import { FormStore } from "simplr-forms-core/stores";
33+
import { Form, Text, Submit } from "simplr-forms-dom";
34+
35+
export class Main extends React.Component<{}, { formId: string }> {
36+
protected onSubmit: any = (event: React.FormEvent<HTMLFormElement>, store: FormStore) => {
37+
console.log("Submitting...");
38+
console.log(store.ToObject());
39+
};
40+
41+
render() {
42+
return <Form onSubmit={this.onSubmit}>
43+
<label>
44+
Promo code:
45+
<Text name="PromoCode" />
46+
</label>
47+
<Submit>Submit</Submit>
48+
</Form>;
49+
}
50+
}
51+
52+
ReactDOM.render(<Main />, document.getElementById("react-root"));
53+
```
54+
55+
And declare required rules well... In a declarative fashion?
56+
57+
E.g. for upper-case, you import an `UpperCaseNormalizer` like this:
58+
```ts
59+
import { UpperCaseNormalizer } from "simplr-forms-core/normalizers";
60+
```
61+
And declare the rule right inside the field like this:
62+
```tsx
63+
<Form>
64+
<label>
65+
Promo code:
66+
<Text name="PromoCode">
67+
<UpperCaseNormalizer />
68+
</Text>
69+
</label>
70+
<Submit>Submit</Submit>
71+
</Form>
72+
```
73+
74+
Convenient, right? Now you think that the `UpperCaseNormalizer` is some complex peace of code, right?
75+
76+
Well, decide for yourself, because the whole `UpperCaseNormalizer` looks like this:
77+
```ts
78+
import { BaseNormalizer } from "simplr-forms-core/normalizers";
79+
import { FieldValue } from "simplr-forms-core/contracts";
80+
import { ValueOfType } from "simplr-forms-core/utils";
81+
82+
export class UpperCaseNormalizer extends BaseNormalizer<{}, {}> {
83+
Normalize(value: FieldValue): FieldValue {
84+
if (ValueOfType<string>(value, UpperCaseNormalizer.name, "string")) {
85+
return value.toUpperCase();
86+
}
87+
}
88+
}
89+
```
90+
91+
Library imports are organized and easily reachable.
92+
93+
And what is `ValueOfType` thingy there?
94+
95+
That's just a convenient helper function that checks if `typeof value === "string"` and throws an error with a proper message if it's not. Take it or leave it. The library is not opinionated about that.
96+
97+
There's more.
98+
99+
We only have our value normalized to upper-case now. What about alphanumeric part?
100+
101+
Well, you can compose `Normalizers` and even decide the order of them as you wish, all still declaratively, like this:
102+
```tsx
103+
<Form>
104+
<label>
105+
Promo code:
106+
<Text name="PromoCode">
107+
<UpperCaseNormalizer />
108+
<AlphanumericNormalizer />
109+
</Text>
110+
</label>
111+
<Submit>Submit</Submit>
112+
</Form>
113+
```
114+
115+
Now value will be upper-cased and all non-alphanumeric symbols filtered out. If you think that upper-casing should go after alphanumeric filter, you just change the order, still declaratively:
116+
```tsx
117+
<Form>
118+
<label>
119+
Promo code:
120+
<Text name="PromoCode">
121+
<AlphanumericNormalizer />
122+
<UpperCaseNormalizer />
123+
</Text>
124+
</label>
125+
<Submit>Submit</Submit>
126+
</Form>
127+
```
128+
129+
Want something more?
130+
131+
`Normalizers` are regular react components, therefore, they can take props. E.g.:
132+
```tsx
133+
<AlphanumericNormalizer allowSpaces={true} />
134+
```
135+
Now you can unleash the power of declarative rule listing and composition and use props for an easy control of `Normalizers` behaviour.
136+
137+
When user is typing `discount123`, this is how it looks in the field (also, in the store):
138+
139+
![image](https://cloud.githubusercontent.com/assets/7989797/25463183/2646d638-2afd-11e7-95e3-a4812d573435.png)
140+
141+
`Normalizers` enforced all declared rules.
142+
143+
This is how you easily organize and reuse your normalization logic.
144+
145+
### Amazing! What about `Modifiers`?
146+
147+
`Modifiers` are another convenient feature. You use them just as you used `Normalizers`: declare inside the field.
148+
149+
But what they do is a bit different: `Modifiers` format and parse value of the field.
150+
151+
To be more specific:
152+
* When value comes from `FormStore` to the field, it is formatted.
153+
* When it changes, before going to `FormStore`, it is parsed.
154+
155+
This enables you to have a `numeric` value in the store and a `string` one in the field. Or storing `Date` in the store and formatting it for user in a human-readable format.
156+
157+
And `Normalizers` get an already parsed value, so you don't have to care about converting it to the right type in the `Normalizers` and it's the only thing you do in `Modifier`. [Separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns) :+1:
158+
159+
Example of `Modifier` usage:
160+
```tsx
161+
<Form onSubmit={this.onSubmit}>
162+
<label>
163+
Full name:
164+
<Text name="FullName">
165+
<NumericModifier />
166+
</Text>
167+
</label>
168+
<Submit>Submit</Submit>
169+
</Form>
170+
```
171+
172+
And you can also use both `Modifiers` and `Normalizers` in the same `Field`:
173+
```tsx
174+
<Form onSubmit={this.onSubmit}>
175+
<label>
176+
Full name:
177+
<Text name="FullName">
178+
<NumericModifier />
179+
<UpperCaseNormalizer />
180+
</Text>
181+
</label>
182+
<Submit>Submit</Submit>
183+
</Form>
184+
```
185+
Even if this case does not make much sense (numeric->upper-case), I'm sure someone will find a proper usage.
186+
187+
### What's next?
188+
189+
We’ll look at `Reset` and `Clear` buttons, how they work and what are they used for. We'll learn how `initialValue` and `defaultValue` can be used in a meaningful way.
190+
191+
------------
192+
193+
The feedback and questions are more than welcome!
194+
195+
------------
196+
197+
Please feel free to discuss these notes in the [corresponding pull request](https://github.com/SimplrJS/simplr-forms/pull/29).

0 commit comments

Comments
 (0)