Skip to content

Commit b684694

Browse files
committed
ref: #187 adding formik pendind setLoginInfo
1 parent e6b8f88 commit b684694

6 files changed

Lines changed: 98 additions & 143 deletions

File tree

hooks/14_FormValidation/Readme.md

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ For this we will use lc-form-validation library
66

77
Summary steps:
88

9-
- Install lc-form-validation library.
9+
- Install formik, fonk, fonk-formik library.
1010
- Refactor input component to a common component and include error validation info.
1111
- Let's define the validation for the form.
1212
- Let's hook it.
@@ -19,10 +19,10 @@ Summary steps:
1919
npm install
2020
```
2121

22-
- Let's install the _lc-form-validation-library_.
22+
- Let's install the _formik, @lemoncode/fonk, @lemoncode/fonk-formik _.
2323

2424
```bash
25-
npm install lc-form-validation --save
25+
npm install formik @lemoncode/fonk @lemoncode/fonk-formik --save
2626
```
2727

2828
- To avoid having too much repeated code let's move to common an input component, including it's
@@ -88,22 +88,17 @@ export * from './notification';
8888
_./src/pages/loginPage.validation.ts_
8989

9090
```typescript
91-
import {
92-
createFormValidation,
93-
ValidationConstraints,
94-
Validators
95-
} from "lc-form-validation";
96-
97-
const loginFormValidationConstraints: ValidationConstraints = {
98-
fields: {
99-
login: [{ validator: Validators.required }],
100-
password: [{ validator: Validators.required }]
101-
}
91+
import { ValidationSchema, Validators } from "@lemoncode/fonk";
92+
import { createFormikValidation } from "@lemoncode/fonk-formik";
93+
94+
const validationSchema: ValidationSchema = {
95+
field: {
96+
login: [Validators.required],
97+
password: [Validators.required],
98+
},
10299
};
103100

104-
export const loginFormValidation = createFormValidation(
105-
loginFormValidationConstraints
106-
);
101+
export const loginFormValidation = createFormikValidation(validationSchema);
107102
```
108103

109104
- Let's create now a class to hold the dataFormErrors.

hooks/14_FormValidation/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@
3939
"webpack-dev-server": "^3.11.0"
4040
},
4141
"dependencies": {
42+
"@lemoncode/fonk": "^1.3.0",
43+
"@lemoncode/fonk-formik": "^4.0.1",
4244
"@material-ui/core": "^4.11.0",
4345
"@material-ui/icons": "^4.9.1",
44-
"lc-form-validation": "^2.0.0",
46+
"formik": "^2.1.5",
4547
"react": "^16.13.1",
4648
"react-dom": "^16.13.1",
4749
"react-router-dom": "^5.2.0"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as React from "react";
2+
import { LoginEntity } from "../model/login";
3+
import { TextFieldForm } from "../common";
4+
import { Form } from "formik";
5+
import createStyles from "@material-ui/styles/createStyles";
6+
import makeStyles from "@material-ui/styles/makeStyles";
7+
import Button from "@material-ui/core/Button";
8+
9+
interface PropsForm {
10+
onLogin: () => void;
11+
onUpdateField: (string, any) => void;
12+
loginInfo: LoginEntity;
13+
}
14+
15+
// https://material-ui.com/styles/api/#makestyles-styles-options-hook
16+
const useFormStyles = makeStyles((theme) =>
17+
createStyles({
18+
formContainer: {
19+
display: "flex",
20+
flexDirection: "column",
21+
justifyContent: "center",
22+
},
23+
})
24+
);
25+
26+
export const LoginForm: React.FC<PropsForm> = (props) => {
27+
const classes = useFormStyles();
28+
const { onLogin, onUpdateField, loginInfo } = props;
29+
30+
// TODO: Enhacement move this outside the stateless component discuss why is a good idea
31+
const onTexFieldChange = (fieldID) => (e) => {
32+
onUpdateField(fieldID, e.target.value);
33+
};
34+
35+
return (
36+
<Form>
37+
<div className={classes.formContainer}>
38+
<TextFieldForm
39+
label="Name"
40+
name="login"
41+
value={loginInfo.login}
42+
onChange={onTexFieldChange("login")}
43+
/>
44+
<TextFieldForm
45+
label="Password"
46+
type="password"
47+
name="password"
48+
value={loginInfo.password}
49+
onChange={onTexFieldChange("password")}
50+
/>
51+
<Button variant="contained" color="primary" onClick={onLogin}>
52+
Login
53+
</Button>
54+
</div>
55+
</Form>
56+
);
57+
};
Lines changed: 18 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,15 @@
11
import * as React from "react";
2-
import { Link } from "react-router-dom";
32
import { useHistory } from "react-router-dom";
43
import makeStyles from "@material-ui/styles/makeStyles";
54
import createStyles from "@material-ui/styles/createStyles";
65
import Card from "@material-ui/core/Card";
76
import CardHeader from "@material-ui/core/CardHeader";
87
import CardContent from "@material-ui/core/CardContent";
9-
import TextField from "@material-ui/core/TextField";
10-
import Button from "@material-ui/core/Button";
11-
import { FormHelperText } from "@material-ui/core";
128
import { LoginEntity, createEmptyLogin } from "../model/login";
139
import { isValidLogin } from "../api/login";
14-
import { NotificationComponent } from "../common";
15-
import {
16-
LoginFormErrors,
17-
createDefaultLoginFormErrors,
18-
} from "./loginPage.viewmodel";
1910
import { loginFormValidation } from "./loginPage.validation";
20-
import { TextFieldForm } from "../common";
11+
import { Formik } from "formik";
12+
import { LoginForm } from "./loginFormComponent";
2113

2214
// https://material-ui.com/styles/api/#makestyles-styles-options-hook
2315
const useStyles = makeStyles((theme) =>
@@ -35,117 +27,42 @@ export const LoginPage: React.FC<Props> = (props) => {
3527
const [loginInfo, setLoginInfo] = React.useState<LoginEntity>(
3628
createEmptyLogin()
3729
);
38-
const [loginFormErrors, setLoginFormErrors] = React.useState<LoginFormErrors>(
39-
createDefaultLoginFormErrors()
40-
);
41-
const [showLoginFailedMsg, setShowLoginFailedMsg] = React.useState(false);
4230
const classes = useStyles();
4331
const history = useHistory();
4432

4533
const onLogin = () => {
46-
loginFormValidation.validateForm(loginInfo).then((formValidationResult) => {
47-
if (formValidationResult.succeeded) {
48-
if (isValidLogin(loginInfo)) {
49-
history.push("/pageB");
50-
} else {
51-
setShowLoginFailedMsg(true);
52-
}
53-
} else {
54-
alert("error, review the fields");
55-
const updatedLoginFormErrors = {
56-
...loginFormErrors,
57-
...formValidationResult.fieldErrors,
58-
};
59-
setLoginFormErrors(updatedLoginFormErrors);
60-
}
61-
});
34+
if (isValidLogin(loginInfo)) {
35+
history.push("/pageB");
36+
}
6237
};
6338

6439
const onUpdateLoginField = (name, value) => {
6540
setLoginInfo({
6641
...loginInfo,
6742
[name]: value,
6843
});
69-
70-
loginFormValidation
71-
.validateField(loginInfo, name, value)
72-
.then((fieldValidationResult) => {
73-
setLoginFormErrors({
74-
...loginFormErrors,
75-
[name]: fieldValidationResult,
76-
});
77-
});
7844
};
7945

8046
return (
8147
<>
8248
<Card className={classes.card}>
8349
<CardHeader title="Login" />
8450
<CardContent>
85-
<LoginForm
86-
onLogin={onLogin}
87-
onUpdateField={onUpdateLoginField}
88-
loginInfo={loginInfo}
89-
loginFormErrors={loginFormErrors}
90-
/>
51+
<Formik
52+
onSubmit={onLogin}
53+
initialValues={createEmptyLogin()}
54+
validate={loginFormValidation.validateForm}
55+
>
56+
{() => (
57+
<LoginForm
58+
onLogin={onLogin}
59+
onUpdateField={onUpdateLoginField}
60+
loginInfo={loginInfo}
61+
/>
62+
)}
63+
</Formik>
9164
</CardContent>
9265
</Card>
93-
<NotificationComponent
94-
message="Invalid login or password, please type again"
95-
show={showLoginFailedMsg}
96-
onClose={() => setShowLoginFailedMsg(false)}
97-
/>
9866
</>
9967
);
10068
};
101-
102-
interface PropsForm {
103-
onLogin: () => void;
104-
onUpdateField: (string, any) => void;
105-
loginInfo: LoginEntity;
106-
loginFormErrors: LoginFormErrors;
107-
}
108-
109-
// https://material-ui.com/styles/api/#makestyles-styles-options-hook
110-
const useFormStyles = makeStyles((theme) =>
111-
createStyles({
112-
formContainer: {
113-
display: "flex",
114-
flexDirection: "column",
115-
justifyContent: "center",
116-
},
117-
})
118-
);
119-
120-
const LoginForm: React.FC<PropsForm> = (props) => {
121-
const classes = useFormStyles();
122-
const { onLogin, onUpdateField, loginInfo, loginFormErrors } = props;
123-
124-
// TODO: Enhacement move this outside the stateless component discuss why is a good idea
125-
const onTexFieldChange = (fieldId) => (e) => {
126-
onUpdateField(fieldId, e.target.value);
127-
};
128-
129-
return (
130-
<div className={classes.formContainer}>
131-
<TextFieldForm
132-
label="Name"
133-
name="login"
134-
value={loginInfo.login}
135-
onChange={onUpdateField}
136-
error={loginFormErrors.login.errorMessage}
137-
/>
138-
<TextFieldForm
139-
label="Password"
140-
type="password"
141-
name="password"
142-
value={loginInfo.password}
143-
onChange={onUpdateField}
144-
error={loginFormErrors.password.errorMessage}
145-
/>
146-
<Button variant="contained" color="primary" onClick={onLogin}>
147-
Login
148-
</Button>
149-
</div>
150-
);
151-
};
Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
import {
2-
createFormValidation,
3-
ValidationConstraints,
4-
Validators
5-
} from "lc-form-validation";
1+
import { ValidationSchema, Validators } from "@lemoncode/fonk";
2+
import { createFormikValidation } from "@lemoncode/fonk-formik";
63

7-
const loginFormValidationConstraints: ValidationConstraints = {
8-
fields: {
9-
login: [{ validator: Validators.required }],
10-
password: [{ validator: Validators.required }]
11-
}
4+
const validationSchema: ValidationSchema = {
5+
field: {
6+
login: [Validators.required],
7+
password: [Validators.required],
8+
},
129
};
1310

14-
export const loginFormValidation = createFormValidation(
15-
loginFormValidationConstraints
16-
);
11+
export const loginFormValidation = createFormikValidation(validationSchema);

hooks/14_FormValidation/src/pages/loginPage.viewmodel.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)