-
Notifications
You must be signed in to change notification settings - Fork 20
/
App.jsx
157 lines (132 loc) · 5.6 KB
/
App.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// @ts-check
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import { FormWithConstraints, FormInput, FieldFeedbacks, Async, FieldFeedback } from 'react-form-with-constraints-bootstrap4';
import { DisplayFields } from 'react-form-with-constraints-tools';
import './index.html';
import './App.scss';
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function checkUsernameAvailability(value) {
console.log('checkUsernameAvailability');
await sleep(1000);
return !['john', 'paul', 'george', 'ringo'].includes(value.toLowerCase());
}
class Form extends React.Component {
constructor(props) {
super(props);
this.state = this.getInitialState();
this.handleChange = this.handleChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleReset = this.handleReset.bind(this);
}
getInitialState() {
return {
username: '',
password: '',
passwordConfirm: '',
submitButtonDisabled: false
};
}
async handleChange(e) {
const target = e.currentTarget;
this.setState({
[target.name]: target.value
});
await this.form.validateFields(target);
this.setState({submitButtonDisabled: !this.form.isValid()});
}
async handlePasswordChange(e) {
const target = e.currentTarget;
this.setState({
[target.name]: target.value
});
await this.form.validateFields(target, 'passwordConfirm');
this.setState({submitButtonDisabled: !this.form.isValid()});
}
async handleSubmit(e) {
e.preventDefault();
await this.form.validateForm();
const formIsValid = this.form.isValid();
this.setState({submitButtonDisabled: !formIsValid});
if (formIsValid) {
alert(`Valid form\n\nthis.state =\n${JSON.stringify(this.state, null, 2)}`);
}
}
handleReset() {
this.setState(this.getInitialState());
this.form.reset();
}
render() {
return (
<FormWithConstraints ref={formWithConstraints => this.form = formWithConstraints}
onSubmit={this.handleSubmit} noValidate>
<div className="form-group">
<label htmlFor="username">Username <small>(already taken: john, paul, george, ringo)</small></label>
<FormInput id="username" name="username"
value={this.state.username} onChange={this.handleChange}
required minLength={3}
className="form-control" />
<FieldFeedbacks for="username">
<FieldFeedback when="tooShort">Too short</FieldFeedback>
<FieldFeedback when="*" />
<Async
promise={checkUsernameAvailability}
pending="..."
then={available => available ?
<FieldFeedback key="1" info style={{color: '#28a745'}}>Username available</FieldFeedback> :
<FieldFeedback key="2">Username already taken, choose another</FieldFeedback>
}
/>
<FieldFeedback when="valid">Looks good!</FieldFeedback>
</FieldFeedbacks>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<FormInput type="password" id="password" name="password"
innerRef={password => this.password = password}
value={this.state.password} onChange={this.handlePasswordChange}
required pattern=".{5,}"
className="form-control" />
<FieldFeedbacks for="password">
<FieldFeedback when="valueMissing" />
<FieldFeedback when="patternMismatch">Should be at least 5 characters long</FieldFeedback>
<FieldFeedback when={value => !/\d/.test(value)} warning>Should contain numbers</FieldFeedback>
<FieldFeedback when={value => !/[a-z]/.test(value)} warning>Should contain small letters</FieldFeedback>
<FieldFeedback when={value => !/[A-Z]/.test(value)} warning>Should contain capital letters</FieldFeedback>
<FieldFeedback when={value => !/\W/.test(value)} warning>Should contain special characters</FieldFeedback>
<FieldFeedback when="valid">Looks good!</FieldFeedback>
</FieldFeedbacks>
</div>
<div className="form-group">
<label htmlFor="password-confirm">Confirm Password</label>
<FormInput type="password" id="password-confirm" name="passwordConfirm"
value={this.state.passwordConfirm} onChange={this.handleChange}
required className="form-control" />
<FieldFeedbacks for="passwordConfirm">
<FieldFeedback when="*" />
<FieldFeedback when={value => value !== this.password.value}>Not the same password</FieldFeedback>
<FieldFeedback when="valid">Looks good!</FieldFeedback>
</FieldFeedbacks>
</div>
<button disabled={this.state.submitButtonDisabled} className="btn btn-primary">Submit</button>{' '}
<button type="button" onClick={this.handleReset} className="btn btn-secondary">Reset</button>
<DisplayFields />
</FormWithConstraints>
);
}
}
const App = () => (
<div className="container">
<p>
Inspired by <a href="http://moduscreate.com/reactjs-form-validation-approaches/">Modus Create - ReactJS Form Validation Approaches</a>
<br />
Fixed version: <a href="https://codepen.io/tkrotoff/pen/MEeNvO">https://codepen.io/tkrotoff/pen/MEeNvO</a>
</p>
<Form />
</div>
);
ReactDOM.render(<App />, document.getElementById('app'));