Perl(Amon2)で、Formに自動でエラーメッセージを埋め込みたい。
2015年3月5日
FormValidator::Liteとかでバリデートした結果でエラーがあった場合に、自動でエラーを埋め込むような感じにしたいなーと。
で、とりあえず書いてみたプラグインが下記。
package MyApp::Web::Plugin::HTML::FillInFormError;
use strict;
use warnings;
use utf8;
use Amon2::Util;
use HTML::Filter::Callbacks;
sub init {
my ( $self, $c ) = @_;
Amon2::Util::add_method($c, 'fillin_formerror', \&_fillin_formerror);
}
sub _fillin_formerror {
my ( $c, $error ) = @_;
$c->add_trigger(
'HTML_FILTER' => sub {
my ($c, $html) = @_;
my $f = HTML::Filter::Callbacks->new();
$f->add_callbacks(
'*' => {
start => sub {
my $self = shift;
if ( $self->attr('name') ) {
my $name = $self->attr('name');
if ( exists $error->{ $name } ) {
$self->prepend('<p class="error">'. $error->{ $name } .'</p>');
}
}
},
},
);
$html = $f->process($html);
return $html;
},
);
return;
}
1;
HTML::Filter::Callbacksっていう、タグを置換するようなモジュールがあったんでこれを使って、
nameが一致したinputタグの前にprependでpタグ(エラーメッセージ)を追加。
で、上記のプラグインをロード。
__PACKAGE__->load_plugins(
'+MyApp::Web::Plugin::HTML::FillInFormError',
);
これをエラー発生時に呼び出す。
sub index {
my ( $class, $c ) = @_;
# FormValidator::Liteの結果
my $error = {
age => 'error message!!'
};
$c->fillin_formerror( $error );
$c->render('index.tx');
}
で、上で読み込んでるindex.txは下記のような感じ。
<form> <input type="text" name="age"> </form>
これを実行してみると、
<form> <p class="error">error message!!</p><input type="text" name="age"> </form>
って感じなhtmlが出力されるはずです。
と、ここまで書いてみて、
実際はFillinFormと一緒に使う事になるんですが、このまま使うと生成されたhtmlを2回パーズする事になるんでパフォーマンス的にイケてない気が・・。
ここはまだまだ検討の余地がありそう。。