こちら続き
レイアウトがうまくいかなかったため、
試行錯誤した結果をメモします。

エラーメッセージをまとめて一つのマークアップにではなく、
入力項目ごとに出力したくなり、
ComponentFeedbackMessageFilter使用することでうまくいきました。

目次


実装後のスクリーンショット

以下のように表示されます。
エラー時の<wbr>スクリーンショット


ComponentFeedbackMessageFilterについて

12 Wicket forms in detail 6.x記載がありますが、 IFeedbackMessageFilter実装クラスです。
実装クラスは3つあり、それぞれメッセージの出力単位が異なります。

  • ComponentFeedbackMessageFilter
    コンポーネントごと

  • ContainerFeedbackMessageFilter
    コンテナーごと

  • ErrorLevelFeedbackMessageFilter
    エラーレベルごと

何故か、ComponentFeedbackMessageFilter使用した ComponentFeedbackPanelあり、
他2つのFilter使ったPanelないのですが、
これはよく使うからっていうことだと理解しました。


HTML

HTML以下の通り、修正しました。
input項目ごとに、<div wicket:id="nameFeedback"></div>
いった形で、FeedbackPanelの挿入ポイントを追加しました。

<form role="form" wicket:id="mailForm">
    <div class="form-group has-feedback" wicket:id="sendMessageFeedback"></div>
    <div class="form-group has-feedback">
        <input wicket:id="name" type="text" class="form-control" id="inputName" placeholder="Name" required>
        <div wicket:id="nameFeedback"></div>
    </div>
    <div class="form-group has-feedback">
        <input wicket:id="eMail" type="text" class="form-control" id="inputEmail" placeholder="Email" required>
        <div wicket:id="eMailFeedback"></div>
    </div>
    <div class="form-group has-feedback">
        <input wicket:id="subject" type="text" class="form-control" id="inputSubject" placeholder="Subject" required>
        <div wicket:id="subjectFeedback"></div>
    </div>
    <div class="form-group has-feedback">
        <textarea wicket:id="message" name="message" class="form-control" rows="3" placeholder="Message" required></textarea>
        <div wicket:id="messageFeedback"></div>
    </div>
    <div class="form-group">
        <button type="submit" wicket:id="sendMessage" class="btn btn-theme btn-lg btn-block">Send message</button>
    </div>
</form>


FORM

    // newMailForm
    private Form newMailForm() {

        Form form = new Form("mailForm") {

            private static final long serialVersionUID = 5538299138211283825L;

            public void onInitialize() {
                super.onInitialize();
                // name
                TextField name = new RequiredTextField("name", Model.of(""));
                name.setLabel(Model.of(getString("nameLabelText")));
                name.add(StringValidator.maximumLength(150));
                add(name);

                FeedbackPanel nameFeedback = new AppFeedbackPanel("nameFeedback", name);
                add(nameFeedback);

                // eMail
                TextField eMail = new RequiredTextField("eMail", Model.of(""));
                eMail.setLabel(Model.of(getString("eMailLabelText")));
                eMail.add(StringValidator.maximumLength(150));
                eMail.add(EmailAddressValidator.getInstance());
                add(eMail);

                FeedbackPanel eMailFeedback = new AppFeedbackPanel("eMailFeedback", eMail);
                add(eMailFeedback);

                // subject
                TextField subject = new RequiredTextField("subject", Model.of(""));
                subject.setLabel(Model.of(getString("subjectLabelText")));
                subject.add(StringValidator.maximumLength(150));
                add(subject);

                FeedbackPanel subjectFeedback = new AppFeedbackPanel("subjectFeedback", subject);
                add(subjectFeedback);

                // message
                TextArea<String> message = new TextArea<>("message", Model.of(""));
                message.setLabel(Model.of(getString("messageLabelText")));
                message.setRequired(true);
                message.add(StringValidator.maximumLength(10000));
                add(message);

                FeedbackPanel messageFeedback = new AppFeedbackPanel("messageFeedback", message);
                add(messageFeedback);

                AjaxButton sendMessage = new AjaxButton("sendMessage", Model.of(getString("messageButtonLabelText"))) {
                    private static final long serialVersionUID = -8204140666393922700L;

                    @Override
                    protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        // --------------------------------------------------
                        // メール送信要求の登録処理.....
                        // getDefaultModelObjectAsString()で値を取得して、
                        // INSERT文なりを実行する。
                        // form.get("name").getDefaultModelObjectAsString();
                        // form.get("eMail").getDefaultModelObjectAsString();
                        // form.get("subject").getDefaultModelObjectAsString();
                        // form.get("message").getDefaultModelObjectAsString();
                        // ----------------------------------

                        // Formに対してのオペレーション
                        // super.onSubmit(target, form); 空メソッドなので、呼ばなくてOK
                        success(getString("messageMailSendSucceed"));
                        target.add(form);
                    }

                    @Override
                    protected void onError(AjaxRequestTarget target, Form<?> form) {
                        // super.onError(target, form); 空メソッドなので、呼ばなくてOK
                        error(getString("messageMailSendError"));
                        target.add(form);
                    }
                };
                add(sendMessage);
                setDefaultButton(sendMessage);

                FeedbackPanel sendMessageFeedback = new AppFeedbackPanel("sendMessageFeedback", sendMessage);
                add(sendMessageFeedback);

                add(new AjaxFormValidatingBehavior("blur", Duration.ONE_SECOND));
            }
        };
        return form;
    }

説明

  • inputフィールドのコンポーネント元に、AppFeedbackPanel生成して、Form add します。
    コンポーネントがそれぞれフィルターとして機能します。

                FeedbackPanel nameFeedback = new AppFeedbackPanel("nameFeedback", name);
                add(nameFeedback);

  • AjaxRequestTarget#add()引数にForm設定します。
    これで、Form配下のコンポーネント(FeedbackPanel) にエラーメッセージが伝播します。
    便利です。

  • add(new AjaxFormValidatingBehavior("blur", Duration.ONE_SECOND)); で、
    onblur1秒後、(フォーカスを失って1秒後) に、Validation実行するようにしています。
    これも便利です。

  • form.get("name").getDefaultModelObjectAsString()で、Value取得が冗長なので、
    CompoundPropertyModel使用する形で記述したほうが良いかもしれません。


AppFeedbackPanel

FeedbackPanel継承したクラスを作成しました。
作成理由は、デフォルトだと、<ul ><li >タグを使う形の実装になっていて、
タグを変えたかったからです。

import org.apache.wicket.Component;
import org.apache.wicket.feedback.ComponentFeedbackMessageFilter;
import org.apache.wicket.feedback.ErrorLevelFeedbackMessageFilter;
import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.feedback.IFeedbackMessageFilter;
import org.apache.wicket.markup.html.panel.FeedbackPanel;

/**
 * AppFeedbackPanel
 *
 * @author Kem
 */
public class AppFeedbackPanel extends FeedbackPanel {

    private static final long serialVersionUID = 8451969894945021514L;

    /**
     * Constructor
     *
     * @param id
     */
    public AppFeedbackPanel(String id) {
        super(id);
        setOutputMarkupId(true);
    }

    /**
     * Constructor
     *
     * @param id
     * @param filter
     */
    public AppFeedbackPanel(final String id, IFeedbackMessageFilter filter) {
        super(id, filter);
        setOutputMarkupId(true);
    }

    /**
     * Constructor
     *
     * @param id
     * @param compornent
     */
    public AppFeedbackPanel(String id, Component compornent) {
        this(id, new ComponentFeedbackMessageFilter(compornent));
    }

    /**
     * Constructor
     *
     * @param id
     * @param errorLevel
     */
    public AppFeedbackPanel(String id, int errorLevel) {
        this(id, new ErrorLevelFeedbackMessageFilter(errorLevel));
    }

    /**
     * getCSSClass
     *
     * @param message
     * @return
     */
    @Override
    protected String getCSSClass(final FeedbackMessage message) {
        String cssClass;
        switch (message.getLevel()) {
            case FeedbackMessage.UNDEFINED:
                cssClass = getString(FeedbackMessage.UNDEFINED_CSS_CLASS_KEY);
                break;
            case FeedbackMessage.DEBUG:
                // FeedbackMessage.INFO 以下は、"alert alert-info"
                cssClass = "alert alert-info";
                break;
            case FeedbackMessage.INFO:
                cssClass = "alert alert-info";
                break;
            case FeedbackMessage.SUCCESS:
                cssClass = "alert alert-success";
                break;
            case FeedbackMessage.WARNING:
                cssClass = "alert alert-warning";
                break;
            case FeedbackMessage.ERROR:
                cssClass = "alert alert-danger";
                break;
            case FeedbackMessage.FATAL:
                // FeedbackMessage.ERROR 以上は、"alert alert-danger"
                cssClass = "alert alert-danger";
                break;
            default:
                cssClass = "feedbackPanel" + message.getLevelAsString();
        }
        return cssClass;
    }
}

HTMLは以下の通りです。feedbackululなのは、
継承元のFeedbackPanel実装都合となります。

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:panel>
  <div wicket:id="feedbackul">
    <div wicket:id="messages">
      <span wicket:id="message">A message</span>
    </div>
  </div>
</wicket:panel>
</body>
</html>

参考

以下参考に、FORMFeedbackPanel作成しました。

以上です。

コメント