react.jsとmaterial-uiを使うと、入力フィールドとそのバリデーションは次のようなコードになります。今回はメールアドレスを入力するケースです。
※ ES6の記法で書いています。
handleValidation(e) {
let email = this.refs.email;
let value = email.getValue();
if (!value) {
email.setErrorText('メールアドレスを入力してください');
return;
}
let re = /^.+@.+$/i;
if (!re.test(email)) {
email.setErrorText('入力された値はメールアドレスではありません');
return;
}
}
render() {
return <TextField ref='email' floatingLabelText='email'
onChange={this.handleValidation.bind(this)} />;
}
のように記述します。html5のタグが使えるのに、メリットを全然活かせていません。TextFieldにセットしたプロパティはすべて、inputタグにセットされるので、type='email'をセットします。ここでは一緒に、required=trueをセットして、入力を必須にセットしています。
render() {
return <TextField ref='email' floatingLabelText='email'
type='email' required={true}
onChange={this.handleValidation.bind(this)} />;
}
これで、inputタグのtypeはemailになりました。しかし、html5のinputタグのバリデーションはフォームをサブミットするときに実行されて表示されます。さらにonChangeで自前でemailのバリデーションを行うのもの二度手間です。もっとスッキリとしたいです。
inputタグは値が入力されると、即座にバリデーションされてvalidationMessageにバリデーションメッセージがセットされます。これを使えば、バリデーションのロジックを自分のコードから減らせて、表示方法もコントロールできます。
material-uiに限った話で言えば、input要素はdiv要素の中にラップされているので、reactのコンポーネントからDOM要素を抜き出す、と言う余分な処理が入りますが、やり方自体はreact.jsに限らず汎用的に使えるはずです。
それでは、バリデーションメッセージを処理するようにhandleValidationを書き換えます。
handleValidation() {
let email = this.resf.email;
let elem = React.findDOMNode(email).getElementsByTagName('input')[0];
if (!elem.validity.valid) {
email.setErrorText(elem.vaidationMessage);
} else {
email.setErrorText('');
}
}
これで、入力値のバリデーションがhtml5の機能で隠蔽されました。また、ブラウザの機能でかっこわるいバリデーションエラーを見せるのではなく、Material UIの統一的なエラーメッセージの表示方法でエラーを見せられるようになります。