ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Apache Tapestryコミュの[T5] カスタム入力フォームの作成方法について

  • mixiチェック
  • このエントリーをはてなブックマークに追加
TapestryによるWebシステム(のプロトタイプ)を作ろうとしている者です。
皆さんのお知恵を拝借させていただきたく、トピックをたてさせていただきました。
なお、Tapestryは「5.0.5」を使用しています。

さっそく質問させていただきます。
Tapestryに用意されている入力フォームを組み合わせ、独自の入力フォームコンポーネントを作成したいのですが、どうにも行き詰まってしまいました。

例えば、「氏名」の項目を「姓」と「名」に分けて入力させることを想定します。
氏名の入力はあちこちで使う可能性があるので、毎回「TextField」コンポーネントを2つ書くのではなく、「TextField」2つからなる「姓名コンポーネント」を作たいと考えました。

このような要求はよくあることだと思いますが、Tapestry(5.0.5)的には、どのように実装するのがセオリーなのでしょうか?

2つの「TextField」を含むテンプレートとそれに対応するJavaコードを書き、ここ数日試行錯誤しているのですが、テンプレート上のパラメータの管理、外の世界とのパラメータの管理、そしてコンポーネントIDの管理等をどのようなコードで実現すればいいのか、なかなか正解にたどり着けずにいます。

テンプレートは以下のようなものを書いてみました。
<span xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<t:label for="lastname"/>
<input t:type="textfield" t:id="lastname" value="lastname"/>
<t:label for="firstname"/>
<input t:type="textfield" t:id="firstname" value="firstname"/>
</span>

これに対するJavaコードはどんな感じになるのでしょうか。
そもそもテンプレートも、これだとIDが固定になってしまうので、あまり嬉しくありません(「姓名コンポーネント」は「氏名」と「ふりがな」のように、同じフォームの中に複数回使う事も考えています)。

ヒントだけでもいただければ、とても嬉しいです。
よろしくお願いします。

コメント(10)

こんな簡単な言葉で大変申し訳ありませんが、丁寧なご説明、本当にありがとうございました。
お示しいただいたコードを拝見して、目から鱗が落ちる気持ちでした。

なるほど、「inherit:」はこういうときに使えるんですね。参考になりました。
IDの件も理解しました。勝手に数字をつけてくれるなあ、とは思っていたのですが、そういう仕様だったのですね。
今回はCSSやJavaScriptの問題はないのですが、明示的にIDを指定できるのは嬉しいです。

さっそく試してみます。
また、分からないところがあったら質問させていただきます。
その節は、またよろしくお願いします。
コメントありがとうございました。

本日さっそく試してみました。
「姓」「名」のラベルは固定で構わないのと、各テキストフィールドのIDも半固定で構わないので、以下のような形になりました。

これで、独自入力フォームの作り方の理解が進みました。
ただ、まだちょっと問題が残っているので、別掲で相談させてください。

いずれにしても、貴重なアドバイスをありがとうございました。


NameFields.html:
--------------------------------------------------
<span xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
 <t:label for="lastname"/>
 <input t:type="textfield" t:id="lastname" value="inherit:lastname" clientid="prop:lastclientid"/>
 <t:label for="firstname"/>
 <input t:type="textfield" t:id="firstname" value="inherit:firstname" clientid="prop:firstclientid"/>
</span>
--------------------------------------------------

NameFields.java:
--------------------------------------------------
import org.apache.tapestry.corelib.base.AbstractField;
import org.apache.tapestry.services.FormSupport;

public class NameFields extends AbstractField {
 private final String SUFFIX_LASTNAME = "-lastname";
 private final String SUFFIX_FIRSTNAME = "-firstname";

 @Override
 protected void processSubmission(FormSupport formSupport, String elementName) {
  // Do nothing.
 }

 public String getLastClientId() {
  return getClientId() + SUFFIX_LASTNAME;
 }

 public String getFirstClientId() {
  return getClientId() + SUFFIX_FIRSTNAME;
 }
}
--------------------------------------------------

使用例:
--------------------------------------------------
<t:form>
 <t:label for="name"/>
 <t:namefields t:id="name" lastname="prop:user.lastname" firstname="prop:user.firstname"/>

 <t:label for="kana"/>
 <t:namefields t:id="kana" lastname="prop:user.lastkana" firstname="prop:user.firstkana"/>

 <t:submit/>
</t:form>
--------------------------------------------------
前のコメントの通り、一応目的は達せられたのですが、まだちょっと不満があります。
先のコードを実行すると、以下のような入力フォームになります:

 名前   姓_____ 名_____
 ふりがな 姓_____ 名_____

ここでこれらの項目が必須入力だった場合、サブミットすると、以下のようなエラーメッセージが表示されます(エラーメッセージおよびラベルは日本語化してあります)。

エラー:
--------------------------------------------------
・姓は必須項目です。
・名は必須項目です。
・姓は必須項目です。
・名は必須項目です。
--------------------------------------------------

これを、できれば以下のようなメッセージにしたいと思っています。

期待するエラー:
--------------------------------------------------
・名前は必須項目です。
・ふりがなは必須項目です。
--------------------------------------------------

「AbstractTextField」のソースを眺めて、先のコードで「Do nothing」と書いたあたりでエラーメッセージの埋め込み処理をしてやればいいような気がするのですが、認識はあっていますか?それとももっと簡単な方法がありますか?

そもそも「AbstractField」を継承しているところも自信がないのですが。
この継承は、「姓名コンポーネント」にIDを与えたかったために行いました。

アドバイスいただければ幸いです。
よろしくお願いします。
Form側で処理する訳ですね。
これだと、JavaScriptでの検査は行われないように見えますが、あってますか?
JavaScriptの生成部分を探すべきなんでしょうか。

> 私はAbstractFieldはフォームの1フィールドに対応するものだと認識しています。
そうなんですよね。それが気になっていました。
「ComponentResources」を使えば良かったのですね。

> (というかFieldインターフェースを実装していないと)
> Labelのforパラメータに渡せなくなるので、
これも、できればLabelにしておいて、エラーの際にはBEFによるハイライトの対象になって欲しいんですけど、もしかしてそもそもBEFは使わないというのが正解ですか?


いろいろとご親切にありがとうございます。

ちなみに、Tapestryの情報はどんなところで収集されていらっしゃるんですか?
日本語のリソースはほとんど皆無なので、個人的にはココは非常にありがたい場所なんですが。(^^;
情報をいただくばかりで申し訳ありません。
> 返事が遅くなってすみません。

とんでもないです。
あんまりレスポンスがいいと、自分の宿題をやっていただいているような罪悪感にさいなまれてしまいますので。(^^;

> ・Fieldインターフェースを実装したコンポーネントを作る。
> ・そのコンポーネントはhiddenフィールドとして作る。
> ・姓、名の各フィールドにonchangeイベントハンドラを設定して、
>  変更されたら姓名を連結してhiddenフィールドに格納。
> ・hiddenフィールドにvalidatorを設定する。

できるかどうかは置いておいて、これがやりたい事に近いのだと思います。
時間ができたらトライしてみます。

もっとも、くだんの「姓名コンポーネント」は結局「姓」と「名」の二つのフィールドに分けてしまいました。
最近は、IoCの思想からも伺えるように、Tapestryはシンプルな機能を積み重ねて行くのが基本スタイルなのかな、などと感じています。

> 公式のドキュメントとソースコードです。MLも購読してますが、流量が多くて追いきれません。。。

やっぱりドキュメントとソースは基本ですね。
しかし、慣れていないので、どちらも解読に時間がかかります。(^^;
MLについては同感です。

> ドキュメントは http://kuramo.ch/tapestry5/tapestry-core/ja/ で日本語訳をやってます。

ええ!このサイトの管理をされているんですか?
このドキュメントにはめちゃめちゃ助けていただきました。
これがなかったら一歩も進めなかったです。唯一存在する日本語の資料といっても過言ではないでしょう。
大変でしょうが、ご活躍に期待させていただきます。

ありがとうございました。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Apache Tapestry 更新情報

Apache Tapestryのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング