numericInputComponent.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import * as React from "react";
  2. interface INumericInputComponentProps {
  3. label: string;
  4. value: number;
  5. step?: number;
  6. onChange: (value: number) => void;
  7. precision?: number;
  8. }
  9. export class NumericInputComponent extends React.Component<INumericInputComponentProps, { value: string }> {
  10. static defaultProps = {
  11. step: 1,
  12. };
  13. private _localChange = false;
  14. constructor(props: INumericInputComponentProps) {
  15. super(props);
  16. this.state = { value: this.props.value.toFixed(this.props.precision !== undefined ? this.props.precision : 3) }
  17. }
  18. shouldComponentUpdate(nextProps: INumericInputComponentProps, nextState: { value: string }) {
  19. if (this._localChange) {
  20. return true;
  21. }
  22. if (nextProps.value.toString() !== nextState.value) {
  23. nextState.value = nextProps.value.toFixed(this.props.precision !== undefined ? this.props.precision : 3);
  24. return true;
  25. }
  26. return false;
  27. }
  28. updateValue(evt: any) {
  29. let value = evt.target.value;
  30. if (/[^0-9\.\-]/g.test(value)) {
  31. return;
  32. }
  33. let valueAsNumber = parseFloat(value);
  34. this._localChange = true;
  35. this.setState({ value: value });
  36. if (isNaN(valueAsNumber)) {
  37. return;
  38. }
  39. this.props.onChange(valueAsNumber);
  40. }
  41. onBlur() {
  42. this._localChange = false;
  43. let valueAsNumber = parseFloat(this.state.value);
  44. if (isNaN(valueAsNumber)) {
  45. this.props.onChange(this.props.value);
  46. return;
  47. }
  48. this.props.onChange(valueAsNumber);
  49. }
  50. render() {
  51. return (
  52. <div className="numeric">
  53. {
  54. this.props.label &&
  55. <div className="numeric-label" title={this.props.label}>
  56. {`${this.props.label}: `}
  57. </div>
  58. }
  59. <input type="number" step={this.props.step} className="numeric-input" value={this.state.value} onChange={evt => this.updateValue(evt)} onBlur={() => this.onBlur()}/>
  60. </div>
  61. )
  62. }
  63. }