Make NumberInput more tolerant to errors

This commit is contained in:
Lukas Martinelli 2016-12-30 16:18:53 +01:00
parent 89d497c73f
commit 1d7768e37c
2 changed files with 55 additions and 22 deletions

View file

@ -31,7 +31,7 @@ export default class PropertyGroup extends React.Component {
onPropertyChange(property, newValue) { onPropertyChange(property, newValue) {
const group = getGroupName(this.props.layer.type, property) const group = getGroupName(this.props.layer.type, property)
this.props.onChange(group , property ,newValue) this.props.onChange(group , property, newValue)
} }
render() { render() {
@ -40,7 +40,7 @@ export default class PropertyGroup extends React.Component {
const paint = this.props.layer.paint || {} const paint = this.props.layer.paint || {}
const layout = this.props.layer.layout || {} const layout = this.props.layer.layout || {}
const fieldValue = paint[fieldName] || layout[fieldName] const fieldValue = fieldName in paint ? paint[fieldName] : layout[fieldName]
return <ZoomSpecField return <ZoomSpecField
onChange={this.onPropertyChange.bind(this)} onChange={this.onPropertyChange.bind(this)}

View file

@ -11,38 +11,71 @@ class NumberInput extends React.Component {
onChange: React.PropTypes.func, onChange: React.PropTypes.func,
} }
onChange(e) { constructor(props) {
const value = parseFloat(e.target.value) super(props)
/*TODO: we can do range validation already here? this.state = {
if(this.props.min && value < this.props.min) return value: props.value
if(this.props.max && value > this.props.max) return }
*/ }
if(isNaN(value)) { componentWillReceiveProps(nextProps) {
this.props.onChange(this.props.default) this.setState({ value: nextProps.value })
} else { }
changeValue(newValue) {
const value = parseFloat(newValue)
const hasChanged = this.state.value !== value
if(this.isValid(value) && hasChanged) {
this.props.onChange(value) this.props.onChange(value)
} else {
this.setState({ value: newValue })
}
}
isValid(v) {
const value = parseFloat(v)
if(isNaN(value)) {
return false
}
if(!isNaN(this.props.min) && value < this.props.min) {
return false
}
if(!isNaN(this.props.max) && value > this.props.max) {
return false
}
return true
}
resetValue() {
// Reset explicitly to default value if value has been cleared
if(this.state.value === "") {
return this.changeValue(this.props.default)
}
// If set value is invalid fall back to the last valid value from props or at last resort the default value
if(!this.isValid(this.state.value)) {
if(this.isValid(this.props.value)) {
this.changeValue(this.props.value)
} else {
this.changeValue(this.props.default)
}
} }
} }
render() { render() {
let stepSize = null
if(this.props.max && this.props.min) {
stepSize = (this.props.max - this.props.min) / 10
}
return <input return <input
style={{ style={{
...input.input, ...input.input,
...this.props.style ...this.props.style
}} }}
type={"number"}
min={this.props.min}
max={this.props.max}
step={stepSize}
placeholder={this.props.default} placeholder={this.props.default}
value={this.props.value} value={this.state.value}
onChange={this.onChange.bind(this)} onChange={e => this.changeValue(e.target.value)}
onBlur={this.resetValue.bind(this)}
/> />
} }
} }