src/components/Form/Number/Number.jsx
import React from 'react'
import ValidationElement from '../ValidationElement'
import Generic from '../Generic'
export default class Number extends ValidationElement {
constructor(props) {
super(props)
this.state = {
uid: `${this.props.name}-${super.guid()}`,
max: props.max,
min: props.min,
}
this.handleError = this.handleError.bind(this)
}
componentWillReceiveProps(next) {
if (!next.receiveProps) {
return
}
const oldmax = this.state.max
const oldmin = this.state.min
this.setState({ max: next.max, min: next.min, value: next.value }, () => {
if (oldmax !== next.max || oldmin !== next.min) {
this.handleValidation(
{
fake: true,
target: {
name: this.props.name,
},
},
null
)
}
})
}
/**
* Prevent non-numerical values from being entered
*/
sanitizedInput = (value) => {
if (!value.match(/^(\s*|\d+)$/)) {
return value.replace(/\D/g, '')
}
return value
}
/**
* Handle the change event.
*/
handleChange(event) {
event.persist()
super.handleChange(event)
if (this.props.onUpdate) {
this.props.onUpdate({
name: this.props.name,
value: this.sanitizedInput(event.target.value),
})
}
}
handleError(value, arr) {
const errors = arr.concat(
this.constructor.errors.map(err => (
{
code: !this.props.prefix
? err.code
: `${this.props.prefix}.${err.code}`,
valid: err.func(value, this.props),
uid: this.state.uid,
}
))
)
// Take the original and concatenate our new error values to it
return this.props.onError(value, errors)
}
render() {
return (
<Generic
name={this.props.name}
label={this.props.label}
placeholder={this.props.placeholder}
type="text"
className={this.props.className}
disabled={this.props.disabled}
minlength={this.props.minlength}
maxlength={this.props.maxlength}
pattern={this.props.pattern}
readonly={this.props.readonly}
required={this.props.required}
value={this.props.value}
onChange={this.handleChange}
onFocus={this.props.onFocus}
onBlur={this.props.onBlur}
onKeyDown={this.props.onKeyDown}
onCopy={this.props.onCopy}
onCut={this.props.onCut}
onPaste={this.props.onPaste}
clipboard={this.props.clipboard}
tabBack={this.props.tabBack}
tabNext={this.props.tabNext}
ref="number"
onError={this.handleError}
/>
)
}
}
Number.defaultProps = {
name: 'number',
disabled: false,
value: '',
max: '',
min: '',
prefix: '',
pattern: '^(\\s*|\\d+)$',
errorCode: null,
onError: (value, arr) => arr,
}
Number.errors = [
{
code: 'min',
func: (value, props) => {
if (!value.length) {
return null
}
if (props.min) {
return parseInt(value) >= parseInt(props.min)
}
return true
}
},
{
code: 'max',
func: (value, props) => {
if (!value.length) {
return null
}
if (props.max) {
return parseInt(value) <= parseInt(props.max)
}
return true
},
},
]