4

I used to validate two passwords, checking if they're the same, this way :

Password: <h:message id="m_password" for="password" /><br/>
<h:inputSecret id="password" value="#{userC.user.password}" maxlength="15" size="15" required="true">
    <f:validator validatorId="confirmPasswordValidator" />
    <f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />
</h:inputSecret>
<br/>

Password (yes, again): <h:message id="m_confirm_password" for="confirm_password" /><br/>
<h:inputSecret id="confirm_password" binding="#{confirmPassword}" maxlength="15" size="15" required="true">
    <f:ajax event="blur" render="m_password m_confirm_password" />
</h:inputSecret>
<br/>

And in validator :

@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(FacesMessage.SEVERITY_ERROR, null, "passwords don't match"));
        }
    }

}

But I would like to do this verification when the second field of the password lose focus, that's why I'm using the <f:ajax..> field, but it seems there's something missing here. What could it be ?

update

<h:form id="change_password_form">
    Password: <h:message id="m_password" for="password" /><br/>
    <h:inputSecret id="password" value="#{userC.user.password}" maxlength="15" size="15" required="true">
        <f:validator validatorId="confirmPasswordValidator" />
        <f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />
    </h:inputSecret>
    <br/>

    Password (yes, again): <h:message id="m_confirm_password" for="confirm_password" /><br/>
    <h:inputSecret id="confirm_password" binding="#{confirmPassword}" maxlength="15" size="15" required="true">
        <f:ajax event="blur" execute="@this password" render="m_password m_confirm_password" />
    </h:inputSecret>
    <br/>

    <h:commandButton id="change_passord" action="#{userC.changePassword}" value="Change Password" />
    <h:messages globalOnly="true" escape="false" />

</h:form>

update 2 With BalusC suggestion everything went fine, as I had forget to define my template:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

<ui:composition template="/resources/jsf/include/default.xhtml">
    <ui:define name="content">
        <h:form id="change_password_form">
            Password: <h:message id="m_password" for="password" /><br/>
            <h:inputSecret id="password" value="#{userC.user.password}" maxlength="15" size="15" required="true">
                <f:validator validatorId="confirmPasswordValidator" />
                <f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />
            </h:inputSecret>
            <br/>

            Password(yes, again): <h:message id="m_confirm_password" for="confirm_password" /><br/>
            <h:inputSecret id="confirm_password" binding="#{confirmPassword}" maxlength="15" size="15" required="true">
                <f:ajax event="blur" execute="@this password" render="m_password m_confirm_password" />
            </h:inputSecret>
            <br/>

            <h:commandButton id="change_passord" action="#{userC.changePassword}" value="Change password" />
            <h:messages globalOnly="true" escape="false" />

        </h:form>
    </ui:define>
</ui:composition>
</html>
Valter Silva
  • 16,446
  • 52
  • 137
  • 218

1 Answers1

4

The <f:ajax> submits by default only the current component (as in, execute="@this"). If you intend to submit another component along it as well, then you'd need to explicitly specifiy its client ID:

<f:ajax ... execute="@this password" />

This way the validators associated with the password component will be fired as well.

See also:


Update: as per the comments, make sure that you've a <h:head> in the template, otherwise JSF won't be able to auto-include the necessary jsf.js JavaScript file containing the code responsible for <f:ajax> magic.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Bauke, I tried your suggestion but is not working.. I trid `` in the first password and `` in the seconds and nothing so far. – Valter Silva Apr 09 '13 at 01:09
  • The `` is already inside `confirm_password` field like as in your question, right? The `@this` refer the current component, which is thus `confirm_password`. So, basically you're with `execute="@this confirm_password"` doing the same like as `execute="confirm_password confirm_password"` while you really need `execute="password confirm_password"`. The example provided in my answer does exactly the same. – BalusC Apr 09 '13 at 01:12
  • Is this what I'm saying, I put as you said in the second password ``, still not working. I have to do something else in my bean ? Or just the validator should be enough for it ? – Valter Silva Apr 09 '13 at 01:17
  • Sorry, I don't see any problem. I've even copypasted your code along with the change in the above answer into an empty `` in my playground environment (Mojarra 2.1.20 + Tomcat 7.0.37) to ensure that I didn't miss anything obvious. It works fine. Sure that you're running the code you think you're running? No missing faces messages according server logs? Placed a breakpoint on `UIInput#validate()` to see if it's doing its job properly? – BalusC Apr 09 '13 at 01:27
  • The `UIInput#validate()` is called only when I press the `commandButton`. Not when when the seconds input lose focus. – Valter Silva Apr 09 '13 at 01:34
  • Ah okay, `` thus didn't send a HTTP request at all? Did you check the HTTP traffic monitor in browser's developer toolset? (press F12 in Chrome/IE/Firebug) Are you seeing an error in JS console like "Mojarra is undefined" or so? That can happen if you don't have a JSF ``, but a plain HTML `` and thus making JSF unable to auto-include the necessary JavaScript file `jsf.js` containing the logic for JSF ajax magic. Make sure that you've a `` in the template. – BalusC Apr 09 '13 at 01:35
  • `Unsafe JavaScript attempt to access frame with URL chrome-extension://hdokiejnpimakedhajhdlcegeplioahd/overlay.html?&change=1 from frame with URL http://localhost:7070/hi/pages/user/change-password.xhtml. The frame requesting access has a protocol of 'http', the frame being accessed has a protocol of 'chrome-extension'. Protocols must match` – Valter Silva Apr 09 '13 at 01:38
  • `Uncaught ReferenceError: mojarra is not defined` – Valter Silva Apr 09 '13 at 01:39
  • When losing focus in the first and seconds password field respectively. – Valter Silva Apr 09 '13 at 01:39
  • The 1st error suggests that you're showing this form inside an ` – BalusC Apr 09 '13 at 01:41
  • 2
    (and I am going to watch a movie now, can only comment back in a hour or so ;) ) – BalusC Apr 09 '13 at 01:44
  • Bauke, really sorry bro, was my mistake, I forgot to define, my `template`, after that everything went fine! haha sorry bro, really! – Valter Silva Apr 09 '13 at 01:44
  • Good movie buddy, thank you very much for you help, as always a great friend =] – Valter Silva Apr 09 '13 at 01:45