The requirement in this case is as follows:
- A dialog is opened by clicking on a Change Password button.
- The dialog contains two input components (Password and Repeat Password) and several buttons (Cancel, Reset and Submit).
The repeat password input component has no validation.
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.
However, if I refresh the browser window and click on the Change Password button a second time the new password field is 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:
- ChangePasswordBean#getRenderNewPasswordComponent() (returns false)
- ChangePasswordBean#renderNewPasswordComponent() (sets it to true)
- ChangePasswordBean#getRenderNewPasswordComponent() (returns true)
- ChangePasswordBean#getRenderNewPasswordComponent() (returns true)
- ChangePasswordBean#getRenderNewPasswordComponent() (returns true)
- ChangePasswordBean#getRenderNewPasswordComponent() (returns true)
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?