電話番号形式で入力する際のフォームを実装

ReactNativeで入力フォームを使う時って、TextInputを使いますよね。ただこのTextInputさんは、汎用的につくられているので電話番号の入力フォームとしては少し使いづらい印象があります。
そこで割と簡単に電話番号形式入力フォームがコンポーネントとしてあらかじめ定義されていると嬉しいなと思い、実際につくってみました。
機能としては、まだまだで入力に対して電話番号をハイフン区切りにして表示してくれるだけですが、なんとなくそれっぽくなるように作りました。
ぜひ、コピペして使ってみてください。
TelephoneInputを実装
ポイントは、insertDelimiterメソッドですね。入力に対してつねに所定の位置にハイフンが挿入されるように作っています。あとはそれぞれ電話番号の桁数やスタイル、キーボードの種類などをpropsに定義しています。
TelephoneInput.js
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, TextInput } from 'react-native';
TELEPOHNE_LENGTH = 13; // 番号の桁数
DELIMITER_INDEX = [3, 7]; // ハイフンを入れる位置
export class TelephoneInput extends Component {
constructor(props) {
super(props);
}
insertDelimiter(text) {
let text_without_delimiter = text.replace(/-/g, '');
let index = 0;
let result = text_without_delimiter;
DELIMITER_INDEX.forEach(function(value, index) {
if (text_without_delimiter.length >= value) {
const insertIndex = value + index;
result = `${result.slice(0, insertIndex)}-${result.slice(
insertIndex,
insertIndex + result.length
)}`;
index++;
}
});
return result;
}
render() {
return (
<TextInput
autoFocus={true}
keyboardType={'phone-pad'}
value={this.props.value}
placeholder="000-0000-0000"
maxLength={TELEPOHNE_LENGTH}
style={this.props.style}
onChangeText={text => {
this.props.updateAction(this.insertDelimiter(text));
}}
/>
);
}
}
実際に使って見る
上での説明は最小限度にとどめましたが、コンポーネントを定義するところで得られるメリットは上の実装を意識せずにつかえることです。
実際に使ってみて、それを確かめてみましょう。
App.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { TelephoneInput } from './../components/TelephoneInput';
type Props = {};
export default class App extends React.Component<Props> {
constructor(props) {
super(props);
this.state = { telephoneNumber: null };
}
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Input Your Telephone Number</Text>
<TelephoneInput
value={this.state.telephoneNumber}
style={{
fontSize: 35,
fontWeight: 'bold',
padding: 30
}}
updateAction={number => {this.setState({ telephoneNumber: number });}}
/>
<Button
raised
title="Submit"
onPress={() => {
const number = this.state.telephoneNumber;
if (number) {
alert(`下記の番号が入力されています。\n${number}`);
} else {
alert('番号を入力してください。');
}
}}
/>
</View>
);
}
}
TelephoneInputコンポーネントを定義したことで、ハイフンを挿入するといったロジックがかかれなくなったので、 コンポーネントを利用する側からはコードがスッキリ見えるようになりました。他の画面で電話番号を入力するフォームを作る必要ができたときもこのコンポーネントをつかえますね。
<TelephoneInput
value={this.state.telephoneNumber}
style={{
fontSize: 35,
fontWeight: 'bold',
padding: 30
}}
updateAction={number => {this.setState({ telephoneNumber: number });}}
/>
また、updateActionで(名前があまりよくないかもしれない)ステートも更新できるようにしているので、コンポーネントの呼び出し側でも入力された値がわかるようになっています。

親コンポーネントでボタンを押すと電話番号の値を表示するように今回はコードを書いていますが、見事に親コンポーネントで値がとれています。
これができるば入力された電話番号をサーバーに送信して保存ということもできてフォームとしても使えますね。
まとめ
- defaultPropsでデフォルトの値を決める。
- TextInputの各propsに対応する。
- 電話番号の桁数やデリミタを入れる位置を外側から設定できるようにする。
- バリデーションをかけられるようにする。
では