10

次のBalusC キックオフの例を取り上げて、送信ボタンと追加の h:messages を追加し、f:ajaxからを削除することで少し変更しました(最初のままにすると、何らかの理由h:inputSecret'sで原因が削除され、すぐに「値が必要です」というエラーが表示されます) 2番目-しかし、ユーザーはそれを入力する機会がありません... ??? <-別の将来の質問?:) )f:ajaxh:inputSecreth:inputSecret

わかりました、長い話を短くするために:

パスワードフィールドの個々の h:message ではなく、グローバル h:messages の両方のパスワードフィールド (パスワードが等しくない) に関する検証エラーを表示する方法を見つけようとしています。各フィールドの に ="true" が表示され<h:messageます...

しかし、現在、検証メッセージ(私の例外によってスローされた)とrequired="true"が同じ場所に表示されています

コードは次のとおりです。

<h:outputLabel for="password" value="Password:" />
<h:inputSecret id="password" value="#{bean.password}" required="true">
    <f:validator validatorId="confirmPasswordValidator" />
    <f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />
</h:inputSecret>
<h:message id="m_password" for="password" />

<h:outputLabel for="confirm" value="Password (again):" />
<h:inputSecret id="confirm" binding="#{confirmPassword}" required="true">
</h:inputSecret>
<h:message id="m_confirm" for="confirm" />

そして、そのコードh:commandButtonの下に追加:h:messages

<h:commandButton value="doSomething" action="#{myBean.myAction}">
    <f:ajax execute="password confirm" render="m_password m_confirm"></f:ajax>
</h:commandButton>
<h:messages globalOnly="true" styleClass="validation_value_required"/>
@FacesValidator("confirmPasswordValidator")
public class ConfirmPasswordValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String password = (String) value;
        String confirm = (String) component.getAttributes().get("confirm");

        if (password == null || confirm == null) {
            return; // Just ignore and let required="true" do its job.
        }

        if (!password.equals(confirm)) {
            throw new ValidatorException(new FacesMessage("Passwords are not equal."));
        }
    }

}

また

よろしくお願いします。

解決策 (BalusC のおかげ)

かわった

<f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />

<f:attribute name="confirm" value="#{confirmPassword}" />

String confirm = (String) component.getAttributes().get("confirm");

の中へ

UIInput confirmPasswordComponent = (UIInput) component.getAttributes().get("confirm");
String confirm = (String) confirmPasswordComponent.getSubmittedValue();

throw new ValidatorException(new FacesMessage("Passwords are not equal."));

の中へ

context.addMessage(null, new FacesMessage("Passwords are not equal."));
context.validationFailed();
((UIInput) component).setValid(false);
confirmPasswordComponent.setValid(false);
return;
4

1 に答える 1

8

特定のValidatorコンポーネントの が をスローするValidatorExceptionと、そのは が呼び出されFacesMessageたコンポーネントに自動的に関連付けられます。Validator

FacesMessage最終的に になるように、nullクライアント IDに を手動で追加する必要があります<h:messages globalOnly="true">。また、JSF がモデル値を更新したり、アクションを呼び出したりしないように、手動でvalidationFailed()on に設定する必要があります。FacesContext必要に応じて (推奨されますが)、適切なリスナー/ツリー ビジター (強調表示など) がこれを考慮に入れるように、手動でコンポーネントを無効としてマークする必要もあります。

if (!password.equals(confirm)) {
    context.addMessage(null, new FacesMessage("Passwords are not equal."));
    context.validationFailed();
    ((UIInput) component).setValid(false);
    confirmPasswordComponent.setValid(false); // You'd need to pass it as component instead of as its submitted value in f:attribute.
}

ところで、OmniFacesプロジェクトには、<o:validateEqual>これを簡単にするコンポーネントがあります。ショーケースの例も参照してください。

于 2012-04-04T12:01:28.283 に答える