@@ -8,9 +8,9 @@ Base Form component for building convenient forms for [React](https://facebook.g
8
8
9
9
## Features Overview
10
10
11
- - Controlled Form, i.e. it works with input values passed in props as JS object.
11
+ - Controlled Form, i.e. it accepts input values as a JSON object.
12
12
- Simple API that handles deeply nested values and collections.
13
- - Flexible and conventient validation that allows to validate inputs as user types.
13
+ - Flexible and convenient validation that allows to validate inputs as user types.
14
14
- Allows to easily turn any existing component into a Form Input component.
15
15
16
16
## Installation
@@ -26,177 +26,69 @@ npm install --save react-form-base
26
26
` react-form-base ` provides a ` Form ` base class which expects to work together
27
27
with ** Input** components. An ** Input** is any component that consumes three
28
28
properties: ` value ` , ` error ` and ` onChange ` . It also has to provide it's
29
- ` value ` as first argument to ` onChange ` function supplied in props. For
30
- existing ready-for-use input bindings take a look on [ react-form-js] ( https://github.com/akuzko/react-form-js )
31
- and [ react-form-material-ui] ( https://github.com/akuzko/react-form-material-ui ) .
29
+ ` value ` as first argument to ` onChange ` function supplied in props.
30
+ * For existing ready-for-use input bindings take a look on:*
31
+ - [ react-form-js] ( https://github.com/akuzko/react-form-js )
32
+ - [ react-form-material-ui] ( https://github.com/akuzko/react-form-material-ui )
32
33
33
34
### Form Usage
34
35
35
36
Most of form use-cases with examples are revealed in [ ** Demo Application** ] ( https://akuzko.github.io/react-form-base/ ) .
36
37
Details on how to run it locally are at the end of README.
37
38
38
- Bellow you can take a glance on main aspects of form usage: general API,
39
- custom on-change handlers, validation and ` $render ` helper function.
39
+ #### Dedicated Forms
40
40
41
- #### Basic example
41
+ Most of forms developers deal with are quite complicated and encapsulate
42
+ vast amount of validation and rendering logic. After some basic setup described
43
+ in the [ Wiki] ( https://github.com/akuzko/react-form-base/wiki ) your form may
44
+ look like following:
42
45
43
46
``` js
44
- import Form from ' react-form-base' ;
45
- import { TextField } from ' your-inputs' ; // read on inputs in the beginning of README
46
-
47
- class MyForm extends Form {
48
- render () {
49
- return (
50
- < div>
51
- < TextField {... this .$ (' firstName' )} / >
52
- < TextField {... this .$ (' lastName' )} / >
53
-
54
- < button onClick= {this .save .bind (this )}> Save< / button>
55
- < / div>
56
- );
57
- }
58
- }
59
- ```
60
-
61
- #### Nested fields example
62
-
63
- ``` js
64
- import Form from ' react-form-base' ;
65
- import { TextField , Select } from ' your-inputs' ; // read on inputs in the beginning of README
66
- import countries from ' utils/countries' ; // it's just a stub
67
-
68
- class MyForm extends Form {
69
- render () {
70
- return (
71
- < div>
72
- < TextField {... this .$ (' email' )} / >
73
-
74
- < Select {... this .$ (' address.country' )} options= {countries} / >
75
- < TextField {... this .$ (' address.city' )} / >
76
- < TextField {... this .$ (' address.streetLine' )} / >
77
-
78
- < button onClick= {this .save .bind (this )}> Save< / button>
79
- < / div>
80
- );
81
- }
82
- }
83
- ```
84
-
85
- #### Custom on-change handler
86
-
87
- ``` js
88
- import Form from ' react-form-base' ;
89
- import { Select } from ' your-inputs' ; // read on inputs in the beginning of README
90
-
91
- class MyForm extends Form {
92
- changeItem (value ) {
93
- this .set ({
94
- item: value,
95
- amount: null
96
- });
97
- }
98
-
99
- render () {
100
- return (
101
- < div>
102
- < Select {... this .$ (' item' )(this .changeItem )} options= {[' Item 1' , ' Item 2' ]} / >
103
- < Select {... this .$ (' amount' )} options= {[' 10' , ' 50' , ' 100' ]} / >
104
-
105
- < button onClick= {this .save .bind (this )}> Save< / button>
106
- < / div>
107
- );
108
- }
109
- }
110
- ```
111
-
112
- #### Validation
113
-
114
- ``` js
115
- import Form from ' react-form-base' ;
116
- import { TextField } from ' your-inputs' ; // read on inputs in the beginning of README
117
-
118
- class MyForm extends Form {
119
- // static validations are common validation rules. it's best to define them
120
- // in your top-level application form that is a base class for other forms.
121
- static validations = {
122
- presence : function (value ) {
123
- if (! value) return ' cannot be blank' ;
124
- },
125
- numericality : function (value , options ) {
126
- const { greaterThan } = options;
127
- const fValue = parseFloat (value);
128
-
129
- if (isNaN (fValue)) return ' should be a number' ;
130
- if (greaterThan != undefined && fValue <= greaterThan) {
131
- return ` should be greater than ${ greaterThan} ` ;
132
- }
133
- }
134
- };
135
-
136
- // per-form input validations
47
+ class UserForm extends Form {
137
48
validations = {
138
- // firstName: 'presence' from static validation rules
139
- firstName: ' presence' ,
140
- // email: 'presence' validation from rules and custom regexp validation
141
- // for this specific form
142
- email: [' presence' , function (value ) {
143
- if (! / ^ [\w\d \. ] + @[\w\d ] + \. [\w\d ] {2,} $ / .test (value)) {
144
- return ' should be an email' ;
145
- }
146
- }],
147
- // validation with options
148
- amount: { presence: true , numericality: { greaterThan: 10 } }
49
+ ' email' : [' presence' , ' email' ],
50
+ ' fullName' : ' presence' ,
51
+ ' address.city' : ' presence' ,
52
+ ' address.line' : { presence: true , format: / ^ [\w\s\d \. ,] + $ / }
149
53
};
150
54
151
- render () {
55
+ $ render ($ ) {
152
56
return (
153
57
< div>
154
- < TextField {... this .$ (' firstName' )} / >
155
- < TextField {... this .$ (' email' )} / >
156
- < TextField {... this .$ (' amount' )} / >
157
-
158
- < button onClick= {this .performValidation .bind (this )}> Validate< / button>
159
- < / div>
160
- );
161
- }
162
- }
163
- ```
58
+ < TextField {... $ (' email' )} label= " Email" / >
59
+ < TextField {... $ (' fullName' )} label= " Full Name" / >
164
60
165
- #### $render($) method
61
+ < Select {... $ (' address.countryId' ) options= {countryOptions} label= " Country" / >
62
+ < TextField {... $ (' address.city' )} label= " City" / >
63
+ < TextField {... $ (' address.line' )} label= " Address" / >
166
64
167
- If you don't have extra logic based on render method (such as implementing
168
- rendering in base form and calling ` super.render(someContent) ` from child
169
- forms), and you want to make things a little bit more DRY, you may declare
170
- your form's rendering using ` $render ` method that accepts input-generation
171
- function as argument. Thus, removing the ` this. ` prefix in inputs:
172
-
173
- ``` js
174
- class MyForm extends Form {
175
- $render ($) {
176
- return (
177
- < div>
178
- < TextField {... $ (' firstName' )} / >
179
- < TextField {... $ (' lastName' )} / >
180
- < TextField {... $ (' email' )} / >
65
+ < button onClick= {this .save .bind (this )}> Submit< / button>
181
66
< / div>
182
67
);
183
68
}
184
69
}
185
70
` ` `
186
71
187
- This form of rendering declaration is also very useful when working with
188
- nested forms, since it has a special ` nested ` method that will generate
189
- onChange handler for nested form for you:
72
+ #### Inline Forms
73
+
74
+ If your form is small enough, you might want to render it inline instead of
75
+ defining separate form component. In this case you may pass renderer function
76
+ as only form's child. This function takes form's ` $` function as argument for
77
+ convenience. Note that you still need to define static ` validation` rules
78
+ for the Form to be able to use validations.
190
79
191
80
` ` ` js
192
- {this .map (' items' , (_item , i ) =>
193
- < ItemForm key= {i} {... $ .nested (` items.${ i} ` )} / >
194
- )}
81
+ < Form {... bindState (this )} validations= {{ email: [' presence' , ' email' ], fullName: ' presence' }}>
82
+ {$ => (
83
+ < div>
84
+ < TextField {... $ (' email' )} label= " Email" / >
85
+ < TextField {... $ (' fullName' )} label= " FullName" / >
86
+ < button onClick= {this .registerUser }> Register< / button>
87
+ < / div>
88
+ )}
89
+ < / Form>
195
90
` ` `
196
91
197
- Of course, since ` $ ` is argument in this method, you may use any name for
198
- this variable that you find suitable.
199
-
200
92
#### API and helper methods
201
93
202
94
- ` $ (name)` , ` input (name)` - returns a set of properties for input with a given
0 commit comments