NumberInput.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import React, { PureComponent } from 'react';
  2. import { Field, Input } from '@grafana/ui';
  3. interface Props {
  4. value?: number;
  5. placeholder?: string;
  6. autoFocus?: boolean;
  7. onChange: (number?: number) => void;
  8. min?: number;
  9. max?: number;
  10. step?: number;
  11. }
  12. interface State {
  13. text: string;
  14. inputCorrected: boolean;
  15. }
  16. /**
  17. * This is an Input field that will call `onChange` for blur and enter
  18. */
  19. export class NumberInput extends PureComponent<Props, State> {
  20. state: State = { text: '', inputCorrected: false };
  21. componentDidMount() {
  22. this.setState({
  23. ...this.state,
  24. text: isNaN(this.props.value!) ? '' : `${this.props.value}`,
  25. });
  26. }
  27. componentDidUpdate(oldProps: Props) {
  28. if (this.props.value !== oldProps.value) {
  29. this.setState({
  30. ...this.state,
  31. text: isNaN(this.props.value!) ? '' : `${this.props.value}`,
  32. });
  33. }
  34. }
  35. onBlur = (e: React.FocusEvent<HTMLInputElement>) => {
  36. let value: number | undefined = undefined;
  37. const txt = e.currentTarget.value;
  38. if (txt && !isNaN(e.currentTarget.valueAsNumber)) {
  39. value = e.currentTarget.valueAsNumber;
  40. }
  41. this.props.onChange(value);
  42. this.setState({ ...this.state, inputCorrected: false });
  43. };
  44. onChange = (e: React.FocusEvent<HTMLInputElement>) => {
  45. let newValue: string | undefined = undefined;
  46. let corrected = false;
  47. const min = this.props.min;
  48. const max = this.props.max;
  49. const currValue = e.currentTarget.valueAsNumber;
  50. if (!Number.isNaN(currValue)) {
  51. if (min != null && currValue < min) {
  52. newValue = min.toString();
  53. corrected = true;
  54. } else if (max != null && currValue > max) {
  55. newValue = max.toString();
  56. corrected = true;
  57. } else {
  58. newValue = e.currentTarget.value;
  59. }
  60. }
  61. this.setState({
  62. ...this.state,
  63. text: newValue ? newValue : '',
  64. inputCorrected: corrected,
  65. });
  66. };
  67. onKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
  68. if (e.key === 'Enter') {
  69. this.onBlur(e as any);
  70. }
  71. };
  72. render() {
  73. const { placeholder } = this.props;
  74. const { text, inputCorrected } = this.state;
  75. return (
  76. <Field invalid={inputCorrected} error={inputCorrected ? 'Cannot go beyond range' : ''}>
  77. <Input
  78. type="number"
  79. min={this.props.min}
  80. max={this.props.max}
  81. step={this.props.step}
  82. autoFocus={this.props.autoFocus}
  83. value={text}
  84. onChange={this.onChange}
  85. onBlur={this.onBlur}
  86. onKeyPress={this.onKeyPress}
  87. placeholder={placeholder}
  88. />
  89. </Field>
  90. );
  91. }
  92. }