0

The requirement in this case is as follows:

  1. A dialog is opened by clicking on a Change Password button.

Change Password button

  1. The dialog contains two input components (Password and Repeat Password) and several buttons (Cancel, Reset and Submit).

New password field gets properly rendered

  1. The repeat password input component has no validation.

  2. The password input component is validated only when the dialog is open.

To satisfy #4 I decided to render the password only when dialog was open; otherwise not rendered.

<p:commandButton
    id="changePasswordButton"
    value="Change Password"
    actionListener="#{changePasswordBean.renderNewPasswordComponent()}"
    update="newPassword"
    oncomplete="PF('changePasswordDialog').show();"/>
<p:dialog id="changePasswordDialogId" widgetVar="changePasswordDialog">
    <p:password
        id="newPassword"
        value="#{changePasswordBean.newPassword}"
        rendered="#{changePasswordBean.getRenderNewPasswordComponent()}"
        match="repeatPassword">
        <f:validator validatorId="foo.bar.PasswordValidator"/>
    </p:password>
    <p:password id="repeatPassword"/>

    <p:commandButton
        value="Submit"
        immediate="false"
        validateClient="true"
        process="@this newPassword repeatPassword"
        actionListener="#{changePasswordBean.hideNewPasswordComponent()}"
        update="newPassword repeatPassword"
        oncomplete="if(!args.validationFailed) { PF('changePasswordDialog').hide(); }"/>

    <p:commandButton type="reset" value="Reset"/>

    <p:commandButton
        value="Cancel"
        immediate="true"
        validateClient="false"
        actionListener="#{changePasswordBean.hideNewPasswordComponent()}"
        update="newPassword repeatPassword"
        oncomplete="PF('changePasswordDialog').hide();"/>
</p:dialog>

Backing Bean:

@ViewScoped
public class ChangePasswordBean {

    private String newPassword;

    private boolean renderNewPasswordComponent = false;

    public boolean getRenderNewPasswordComponent() {
        return renderNewPasswordComponent;
    }

    public void renderNewPasswordComponent() {
        renderNewPasswordComponent = true;
    }

    public void hideNewPasswordComponent() {
        renderNewPasswordComponent = false;
    }
}

Unfortunately it does not work. The new password field does not get rendered properly when the dialog opens.

New password field does not get rendered properly

However, if I refresh the browser window and click on the Change Password button a second time the new password field is properly rendered.

New password field gets properly rendered

If I click the Cancel or Submit button the dialog closes. Afterward, if I click the Change Password button another time, the new password field is again rendered properly. This goes on back and forth ad infinitum and is the desired behavior.

However, if I click the Cancel or Submit button (which closes the dialog), refresh the browser window and click the Change Password button the new password field is not properly rendered.

So it seems like the Change Password button, Submit button and Cancel button are not updating the new password input component. After reading Execution order of events when pressing PrimeFaces p:commandButton it looked like I had everything set correctly. The actionListener executes before update, which executes before oncomplete. Setting break points on ChangePasswordBean#renderNewPasswordComponent() and ChangePasswordBean#hideNewPasswordComponent() shows that the action listeners are being executed. Setting a break point on ChangePasswordBean#getRenderNewPasswordComponent() shows that the password component is checking whether or not it should be rendered. But this method is being executed both before and after the actionListener is fired.

Here's the sequence of actionListener method invocations upon clicking Change Password button:

  1. ChangePasswordBean#getRenderNewPasswordComponent() (returns false)

enter image description here

  1. ChangePasswordBean#renderNewPasswordComponent() (sets it to true)

enter image description here

  1. ChangePasswordBean#getRenderNewPasswordComponent() (returns true)

enter image description here

  1. ChangePasswordBean#getRenderNewPasswordComponent() (returns true)

enter image description here

  1. ChangePasswordBean#getRenderNewPasswordComponent() (returns true)

enter image description here

  1. ChangePasswordBean#getRenderNewPasswordComponent() (returns true)

enter image description here

Not sure why the password component checks whether or not it should be rendered (#1) before the actionListener sets the rendered to true (#2). But it looks like the password component checks again whether it should be rendered four times after the actionListener is executed (e.g. in #3, #4, #5, & #6). Does this look like the proper execution order?

If the execution order is correct then perhaps update is not happening at the right time in the sequence, or not at all. How would I check on the server side if update is executing?

Or perhaps there is something all together different that I'm overlooking or misunderstanding?

Community
  • 1
  • 1
Patrick Garner
  • 3,201
  • 6
  • 39
  • 58
  • O/T: your 'getter' for a boolean is 'wrong' http://stackoverflow.com/questions/7437803/resolving-boolean-properties-in-el-not-working and http://stackoverflow.com/questions/2945061/java-how-to-name-boolean-properties – Kukeltje Nov 05 '15 at 21:31
  • @Kukeltje the first link you sent was very helpful. The password component is nested so I changed update to the ID of its parent and it now renders properly. However, now validation is not happening on the password field at all. Need to figure that out now. – Patrick Garner Nov 05 '15 at 21:48
  • 1
    Keep this at hand... https://jsf.zeef.com/bauke.scholtz Read as many Stackoverflow links as possible! – Kukeltje Nov 05 '15 at 21:51

0 Answers0