Reactでformat付きの数値入力コンポーネントを作る
こういう機能がついた入力フォーム、どのようなサービスでも役立つと思う。 ぐぐってもあんまり情報が見つからなかったので自分でまとめる
- フォーカスインしているときは普通の入力エリア
- フォーカスアウトしたら、三桁区切りでフォーマット
- 指定した範囲内の値しか入力不可
- onChangeイベントで数値データを渡す
この実装で注意しないといけないのが、 -
と .
-1
や 6.0
であれば数値としても妥当であるが、Reactでは(というかJavaScriptでは)
-
と .
が入力された瞬間を考慮しなければならない
で、作ったのが↓こんなの(うろ覚え)
class InputNumber extends Component { constructor(props) { super(props) this.state = { isOnFocus: false, value: '', }; } get value() { if (this.state.isOnFocus) { return this.state.value || '' } if (this.props.value) { return this.props.format(+value); } return '0' } includes = value => this.props.min <= value && value <= this.props.max; handleFocus = () => { this.setState({ isOnFocus: true, value: `${this.props.value}` }); }; handleBlur = () => { this.setState({ isOnFocus: false, }); } handleChange = (e) => { const { value } = e.target; if (this.isIncludes(value)) { this.props.onChange(+value); } // ここがどうにも苦しいロジック if (this.isIncludes(value) || value === '-') { this.setState({ value, }) } } render() { <input type="text" className="form-input" placeHolder={this.props.placeHolder} disabled={this.props.disabled} value={this.value} onFocus={this.handleFocus} onBlur={this.handleBlur} onChange={this.handleChange} /> } } InputNumber.propTypes = { value: PropTypes.number.isRequired, min: PropTypes.number, max: PropTypes.number, placeHolder: PropTypes.string, disabled: PropTypes.bool, onChange: PropTypes.func.isRequired, format: PropTypes.func } InputNumber.defaultProps = { min: -Infinity, max: Infinity, disabled: false, placeHolder: '', format: formatDefault } formatDefault = value => ''; // お好きな数値フォーマッタを実装しよう!
今気づいたけどモバイル端末を考えると htmlのnumber使うようにした方が良いんだろうなぁ