Skip to content

Instantly share code, notes, and snippets.

@flakey-bit
Last active January 6, 2019 04:03
Show Gist options
  • Save flakey-bit/aac62ea658a4426423d887760ca98a22 to your computer and use it in GitHub Desktop.
Save flakey-bit/aac62ea658a4426423d887760ca98a22 to your computer and use it in GitHub Desktop.
React numeric input field w/ draft functionality
import * as React from 'react';
import TextField from 'react-md/lib/TextFields';
interface Props {
id: string;
label: React.ReactNode;
clearOnFocus: boolean;
step: number;
min?: number;
max?: number;
value: number;
onChange: (newValue: number) => void;
}
interface State {
localFieldValue: string;
focused: boolean;
}
export class NumericField extends React.Component<Props, State> {
constructor(props: Readonly<Props>) {
super(props);
this.state = {
localFieldValue: props.value.toFixed(0),
focused: false
};
}
public render() {
let renderValue: string;
if (this.state.focused) {
renderValue = this.state.localFieldValue;
} else {
renderValue = this.props.value.toFixed(0);
}
return <TextField id={this.props.id} label={this.props.label} step={this.props.step} min={this.props.min} max={this.props.max} value={renderValue} type="number" onChange={this.onChange} onFocus={this.onFocus} onBlur={this.onBlur} fullWidth={false} />
}
private onChange = (value: string) => {
this.setState({localFieldValue: value});
};
private onFocus = () => {
this.setState({focused: true, localFieldValue: this.props.clearOnFocus ? "" : this.props.value.toFixed(0)});
}
private onBlur = () => {
let newValue = parseInt(this.state.localFieldValue);
// Revert to previous value on blur if invalid
if (isNaN(newValue) || !this.valueIsValid(newValue)) {
newValue = this.props.value;
}
this.setState({localFieldValue: "", focused: false}, () => {
this.props.onChange(newValue);
});
};
private valueIsValid(value: number) {
return (this.props.min === undefined || value >= this.props.min) && (this.props.max === undefined || value <= this.props.max) && value % this.props.step === 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment