Skip to content

Commit 8e00c98

Browse files
Create 2017-04-27.md (#29)
* Create 2017-04-27.md
1 parent 145dd8b commit 8e00c98

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed

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

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
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/MartiogalaLT) (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+
I hope now you're just exited as I am!
138+
139+
This is how you easily organize and reuse your normalization logic.
140+
141+
### Amazing! What about `Modifiers`?
142+
143+
`Modifiers` are another convenient feature. You use them just as you used `Normalizers`: declare inside the field.
144+
145+
But what they do is a bit different: `Modifiers` format and parse value of the field.
146+
147+
To be more specific:
148+
* When value comes from `FormStore` to the field, it is formatted.
149+
* When it changes, before going to `FormStore`, it is parsed.
150+
151+
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.
152+
153+
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:
154+
155+
Example of `Modifier` usage:
156+
```tsx
157+
<Form onSubmit={this.onSubmit}>
158+
<label>
159+
Full name:
160+
<Text name="FullName">
161+
<NumericModifier />
162+
</Text>
163+
</label>
164+
<Submit>Submit</Submit>
165+
</Form>
166+
```
167+
168+
And you can also use both `Modifiers` and `Normalizers` in the same `Field`:
169+
```tsx
170+
<Form onSubmit={this.onSubmit}>
171+
<label>
172+
Full name:
173+
<Text name="FullName">
174+
<NumericModifier />
175+
<UpperCaseNormalizer />
176+
</Text>
177+
</label>
178+
<Submit>Submit</Submit>
179+
</Form>
180+
```
181+
Even if this case does not make much sense (numeric->upper-case), I'm sure someone will find a proper usage.
182+
183+
### What's next?
184+
185+
That's it for today. Tomorrow we'll look at `Reset` and `Clear` buttons, how they work and what are they used for. During that, we'll learn how `initialValue` and `defaultValue` can be used in a meaningful way.
186+
187+
------------
188+
189+
The feedback and questions are more than welcome!
190+
191+
------------
192+
193+
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)