複数フィールドバリデーションは、ラベルをバリデータが持った方が良い
最近、複数フィールドバリデーションを、実案件でモリモリ使っています。
具体的には、複数フィールドに分かれた「年」「月」「日」に対して
- 全部入力されなかったらスルー
- どれか入力したら、他が一つでも入力されていないエラー
- 全部入力されたら、存在する日付かどうかを確認する
という感じです。
そんな事をやっていると、タイトルの件に気付きました。
例えば、こんなバリデーションです。
生年月日 <input type="text" id="year" m:label="年" m:value="#{xxxDto.year}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday"/> </input> <input type="text" id="month" m:label="月" m:value="#{xxxDto.month}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday"/> </input> <input type="text" id="day" m:label="日" m:value="#{xxxDto.day}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday"/> </input>
こうやって、複数フィールドをグループ化して、バリデーションを行います。
内部実装はキモいので省略します(笑)
# 要望が高ければ、後日、S2JSFにもコントリビュートします。
さて、ここで、いずれかの項目が入力されておらず、バリデーションエラーが発生した時、
どのようなエラーメッセージを出せば良いでしょうか。
こんな案が考えられます。
- 年、月、日 : すべて入力してください。
- 生年月日 : すべて入力してください。
どちらでも構わないか、前者が若干好ましい、ぐらいでしょう。
同様に、日付が存在しなかった場合は、どうでしょうか。
- 年、月、日 : 正しい日付を入力してください。
- 生年月日 : 正しい日付を入力してください。
これは後者の方が好ましいでしょう。
しかし、各フィールドは「年」「月」「日」であって、生年月日ではありません。
では、こんな風にHTMLを記述すれば良いのでしょうか。
<input type="text" id="year" m:label="生年月日" m:value="#{xxxDto.year}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday"/> </input> <input type="text" id="month" m:label="生年月日" m:value="#{xxxDto.month}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday"/> </input> <input type="text" id="day" m:label="生年月日" m:value="#{xxxDto.day}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday"/> </input>
今度は、それぞれの「年」「月」「日」が分からなくなりました。
しかも、xxxDto.yearがIntegerなどだと、NumberConverterが自動設定され、
数字以外が入力された場合には、以下のようなエラーメッセージが表示されます。
生年月日 : 形式が正しくありません。
これでは、どのフィールドの形式が間違っているか、分かりません。
そんな事を考えていると、結論はこうなりました。
<input type="text" id="year" m:label="年" m:value="#{xxxDto.year}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday" m:label="生年月日"/> </input> <input type="text" id="month" m:label="月" m:value="#{xxxDto.month}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday" m:label="生年月日"/> </input> <input type="text" id="day" m:label="日" m:value="#{xxxDto.day}"> <span m:inject="s:validator" m:binding="#{multiFieldDateValidator}" m:groupId="birtyday" m:label="生年月日"/> </input>
これなら、各フィールドの変換エラーにも、
全体のバリデーションエラーにも上手く対応できます。
でも、ホントはこう書きたいんですよね。
<input type="text" id="year" m:label="年" m:value="#{xxxDto.year}" /> <input type="text" id="month" m:label="月" m:value="#{xxxDto.month}" /> <input type="text" id="day" m:label="日" m:value="#{xxxDto.day}" /> <span m:inject="s:validator" m:binding="#{groupDateValidator}" m:targetId="year,month,day" m:label="生年月日" />
JSFでは無理な書き方ですが、随分とスッキリします。