44 * WTFPL License, (c) 2016 Vlad Balin, Volicon.
55 */
66
7+
78import React , { PropTypes } from 'react'
89
910const setValue = ( x , e ) => e . target . value ;
@@ -18,35 +19,51 @@ const setBoolValue = ( x, e ) => Boolean( e.target.checked );
1819 * <input type="text" valueLink={ linkToString } />
1920 */
2021
21- export const Input = ( { invalid = 'invalid' , className = '' , valueLink, checkedLink, ...props } ) => {
22- const type = props . type ,
22+
23+ function validationClasses ( props , value , error ) {
24+ let classNames = props . className ? [ props . className ] : [ ] ;
25+
26+ if ( error ) {
27+ classNames . push ( props . invalidClass || 'invalid' ) ;
28+
29+ if ( value === '' ) {
30+ classNames . push ( props . requiredClass || 'required' ) ;
31+ }
32+ }
33+
34+ return classNames . join ( ' ' ) ;
35+ }
36+
37+ export const Input = ( props ) => {
38+ const { valueLink, checkedLink, ...rest } = props ,
39+ type = props . type ,
2340 link = valueLink || checkedLink ;
2441
2542 switch ( type ) {
2643 case 'checkbox' :
2744 return < input { ...props }
28- className = { className }
2945 checked = { link . value }
3046 onChange = { link . action ( setBoolValue ) } /> ;
3147
3248 case 'radio' :
3349 return < input { ...props }
34- className = { className }
3550 checked = { link . value === props . value }
3651 onChange = { e => { e . target . checked && link . set ( props . value ) } } /> ;
3752
3853 default :
3954 return < input { ...props }
40- className = { valueLink . error ? invalid + ' ' + className : className }
55+ className = { validationClasses ( rest , valueLink . value , valueLink . error ) }
4156 value = { valueLink . value }
4257 onChange = { valueLink . action ( setValue ) } /> ;
4358 }
4459} ;
4560
4661export const isRequired = x => x != null && x !== '' ;
62+ isRequired . error = 'Required' ;
4763
4864const emailPattern = / ^ [ - a - z 0 - 9 ~ ! $ % ^ & * _ = + } { \' ? ] + ( \. [ - a - z 0 - 9 ~ ! $ % ^ & * _ = + } { \' ? ] + ) * @ ( [ a - z 0 - 9 _ ] [ - a - z 0 - 9 _ ] * ( \. [ - a - z 0 - 9 _ ] + ) * \. ( a e r o | a r p a | b i z | c o m | c o o p | e d u | g o v | i n f o | i n t | m i l | m u s e u m | n a m e | n e t | o r g | p r o | t r a v e l | m o b i | [ a - z ] [ a - z ] ) | ( [ 0 - 9 ] { 1 , 3 } \. [ 0 - 9 ] { 1 , 3 } \. [ 0 - 9 ] { 1 , 3 } \. [ 0 - 9 ] { 1 , 3 } ) ) ( : [ 0 - 9 ] { 1 , 5 } ) ? $ / i;
4965export const isEmail = x => x . match ( emailPattern ) ;
66+ isEmail . error = 'Should be valid email' ;
5067
5168// This number component rejects invalid input and modify link only with valid number values.
5269// Implementing numeric input rejection might be tricky.
@@ -65,7 +82,7 @@ export const NumberInput = React.createClass( {
6582 setValue ( x ) {
6683 // We're not using native state in order to avoid race condition.
6784 this . value = String ( x ) ;
68- this . error = isNaN ( Number ( x ) ) ;
85+ this . error = this . value === '' || isNaN ( Number ( x ) ) ;
6986 this . forceUpdate ( ) ;
7087 } ,
7188
@@ -92,15 +109,15 @@ export const NumberInput = React.createClass( {
92109 } ,
93110
94111 render ( ) {
95- const { type , invalid = 'invalid' , className = '' , valueLink, ...props } = this . props ,
112+ const { valueLink, ...props } = this . props ,
96113 error = valueLink . error || this . error ;
97114
98- return < input type = "text"
99- className = { error ? className + ' ' + invalid : className }
115+ return < input { ...props }
116+ type = "text"
117+ className = { validationClasses ( props , this . value , error ) }
100118 value = { this . value }
101119 onKeyPress = { this . onKeyPress }
102120 onChange = { this . onChange }
103- { ...props }
104121 /> ;
105122 } ,
106123
@@ -142,9 +159,9 @@ export const NumberInput = React.createClass( {
142159 *
143160 * <TextArea valueLink={ linkToText } />
144161 */
145- export const TextArea = ( { invalid = 'invalid' , className = '' , valueLink, ...props } ) => (
162+ export const TextArea = ( { valueLink, ...props } ) => (
146163 < textarea { ...props }
147- className = { valueLink . error ? invalid + ' ' + className : className }
164+ className = { validationClasses ( props , valueLink . value , valueLink . error ) }
148165 value = { valueLink . value }
149166 onChange = { valueLink . action ( setValue ) } />
150167) ;
0 commit comments