JSFに標準でついているバリデーションを使っているのですが、小数の扱いに困ったので
カスタムバリデータ―を作成することにしました。
小数点以下何桁まで許可するのかをパラメータで渡す必要があったのですが、
バリデータの作成は結構資料があるんだけど、カスタムタグの方法があんまりない…
有っても、JSF1の頃の資料とかで結構古い感じだったので、備忘録としてメモ
■カスタムバリデータの作成
すごく簡単。
アノテーションをつけて、Validatorクラスを継承するだけ。
例)半角英数字バリデーション
※実際の半角チェック部分は省略
アノテーション@FacesValidatorを付けることで、JSF1のときに必要だった
faces-config.xmlへの設定が不要になっています。便利。
()内に別名を指定することも可能。
この状態で、以下のようにタグを指定することで使用できます。
■カスタムバリデータをタグ化
さらに上記バリデータをタグ化してみます。
タグ化するためには、PartialStateHolderのimplementsが必要になります。
多分
多分…多分です…本当は要らないのかもしれないけど、参考にしたLengthValidatorなんかが
継承していたので、とりあえずつけています。
PartialStateHolderを追加することで、いろいろとメソッドの追加が必要になります。
さっきの半角英数字バリデーションに、テスト用に引数onlyNumberを追加したのがこちら。
restoreState、saveStateはそれぞれ引数の値の設定・復元を行います。
それ以降のisTransient等は…よくわかりません。
で、上記のように変更したら、次にカスタムタグの定義を行います。
このあたりは、通常のカスタムタグを作成する場合と似たような形のようです。
今回はWEB-IF/custom.taglib.xmlに作成しました。
この定義内で、カスタムタグ内で使用する引数の設定を行います。
attributeのところですね。
requiredを指定すると、必須のパラメータにできます。
これ以外の定義はまだちゃんと調べていません・・・
ここまで定義したら、あとはxmlnsの宣言のところで、
上記で作成したnamespaceを追加することで、カスタムバリデータタグが使えるようになります。
たとえば、こんな感じに指定したら…
こんな感じで使えます。
JSF1のころ?だと、カスタムタグ化するために、タグ用のクラスを生成したりしないと
いけなかったようですが、ずいぶん楽になったように思います。
これで、相互チェックにも対応してくれていれば言うことないんですけど…
そこはまだみたいですねえ
カスタムバリデータ―を作成することにしました。
小数点以下何桁まで許可するのかをパラメータで渡す必要があったのですが、
バリデータの作成は結構資料があるんだけど、カスタムタグの方法があんまりない…
有っても、JSF1の頃の資料とかで結構古い感じだったので、備忘録としてメモ
■カスタムバリデータの作成
すごく簡単。
アノテーションをつけて、Validatorクラスを継承するだけ。
例)半角英数字バリデーション
※実際の半角チェック部分は省略
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import com.sun.faces.util.MessageUtils;
/**
* 半角英数字バリデーション
*/
@FacesValidator("alphanumValid")
public class AlphanumValidator implements Validator {
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (context == null) throw new NullPointerException();
if (component == null) throw new NullPointerException();
if (value == null) return;
String text = value.toString();
if (!CheckUtils.checkAlphanum(text)) { //ここで半角チェックを行う
//メッセージ取得
FacesMessage fm = MessageUtils.getExceptionMessage("messgae.NOT_MATCHED");
throw new ValidatorException(fm);
}
}
}
アノテーション@FacesValidatorを付けることで、JSF1のときに必要だった
faces-config.xmlへの設定が不要になっています。便利。
()内に別名を指定することも可能。
この状態で、以下のようにタグを指定することで使用できます。
<h:inputText type="text" id="alphaValue" label="半角英数字" value="#{testForm.alphaValue}">
<f:validator validatorId="alphanumValid" />
</h:inputText>
■カスタムバリデータをタグ化
さらに上記バリデータをタグ化してみます。
タグ化するためには、PartialStateHolderのimplementsが必要になります。
多分
多分…多分です…本当は要らないのかもしれないけど、参考にしたLengthValidatorなんかが
継承していたので、とりあえずつけています。
PartialStateHolderを追加することで、いろいろとメソッドの追加が必要になります。
さっきの半角英数字バリデーションに、テスト用に引数onlyNumberを追加したのがこちら。
import javax.faces.application.FacesMessage;
import javax.faces.component.PartialStateHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import com.sun.faces.util.MessageUtils;
/**
* 半角英数字バリデーション
*/
@FacesValidator("alphanumValid")
public class AlphanumValidator implements Validator, PartialStateHolder {
private Boolean onlyNumber;
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (context == null) throw new NullPointerException();
if (component == null) throw new NullPointerException();
if (value == null) return;
if (onlyNumber == null) onlyNumber = false;
String text = value.toString();
if (!CheckUtils.checkAlphanum(text, onlyNumber)) {
//メッセージ取得
FacesMessage fm = MessageUtils.getExceptionMessage("messgae.NOT_MATCHED");
throw new ValidatorException(fm);
}
}
@Override
public Object saveState(FacesContext context) {
if (context == null) throw new NullPointerException();
Object values[] = new Object[3];
values[0] = this.onlyNumber;
return values;
}
@Override
public void restoreState(FacesContext context, Object state) {
if (context == null) throw new NullPointerException();
if (state != null) {
Object values[] = (Object[]) state;
this.onlyNumber = (Boolean) values[0];
}
}
private boolean transientValue = false;
private boolean initialState;
@Override
public boolean isTransient() {
return transientValue;
}
@Override
public void setTransient(boolean transientValue) {
this.transientValue = transientValue;
}
@Override
public void markInitialState() {
this.initialState = true;
}
@Override
public boolean initialStateMarked() {
return this.initialState;
}
@Override
public void clearInitialState() {
this.initialState = false;
}
}
restoreState、saveStateはそれぞれ引数の値の設定・復元を行います。
それ以降のisTransient等は…よくわかりません。
で、上記のように変更したら、次にカスタムタグの定義を行います。
このあたりは、通常のカスタムタグを作成する場合と似たような形のようです。
今回はWEB-IF/custom.taglib.xmlに作成しました。
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0">
<!-- validator tag -->
<namespace>http://hogehoge/custom-taglib</namespace>
<tag>
<tag-name>ValideAlphanum</tag-name>
<validator>
<validator-id>alphanumValid</validator-id>
</validator>
<attribute>
<name>onlyNumber</name>
<required>true</required>
</attribute>
</tag>
</facelet-taglib>
この定義内で、カスタムタグ内で使用する引数の設定を行います。
attributeのところですね。
requiredを指定すると、必須のパラメータにできます。
これ以外の定義はまだちゃんと調べていません・・・
ここまで定義したら、あとはxmlnsの宣言のところで、
上記で作成したnamespaceを追加することで、カスタムバリデータタグが使えるようになります。
たとえば、こんな感じに指定したら…
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:cf="http://hogehoge/custom-taglib">
こんな感じで使えます。
<h:inputText type="text" id="alphaValue" label="半角英数字" value="#{testForm.alphaValue}">
<f:ValideAlphanum onlyNumber="false" />
</h:inputText>
JSF1のころ?だと、カスタムタグ化するために、タグ用のクラスを生成したりしないと
いけなかったようですが、ずいぶん楽になったように思います。
これで、相互チェックにも対応してくれていれば言うことないんですけど…
そこはまだみたいですねえ