Как визуализировать компонент ввода внутри диалога при открытии диалога и отменить рендеринг при закрытии диалога

Требование в этом случае следующее:

  1. Диалоговое окно открывается при нажатии на кнопку «Изменить пароль».

Кнопка смены пароля

  1. Диалоговое окно содержит два компонента ввода (Пароль и Повторите пароль) и несколько кнопок (Отмена, Сброс и Отправить).

Поле нового пароля отображается правильно

  1. Компонент повторного ввода пароля не имеет проверки.

  2. Компонент ввода пароля проверяется только тогда, когда диалоговое окно открыто.

Чтобы выполнить пункт 4, я решил отображать пароль только при открытом диалоговом окне; иначе не визуализируется.

<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>

Поддерживающий компонент:

@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;
    }
}

К сожалению, это не работает. Поле нового пароля не отображается должным образом при открытии диалогового окна.

Поле нового пароля отображается неправильно

Однако, если я обновлю окно браузера и нажму кнопку «Изменить пароль» во второй раз, поле нового пароля отобразится правильно.

Поле нового пароля отображается правильно

Если я нажму кнопку «Отмена» или «Отправить», диалоговое окно закроется. После этого, если я нажму кнопку «Изменить пароль» еще раз, поле нового пароля снова отобразится правильно. Это продолжается взад и вперед до бесконечности и является желаемым поведением.

Однако, если я нажимаю кнопку «Отмена» или «Отправить» (которая закрывает диалоговое окно), обновляю окно браузера и нажимаю кнопку «Изменить пароль», поле нового пароля отображается неправильно.

Таким образом, кажется, что кнопка «Изменить пароль», кнопка «Отправить» и кнопка «Отмена» не обновляют компонент ввода нового пароля. После прочтения порядка выполнения событий при нажатии PrimeFaces p:commandButton показалось, что у меня все настроено правильно. ActionListener выполняется перед обновлением, которое выполняется до завершения. Установка точек останова на ChangePasswordBean#renderNewPasswordComponent() и ChangePasswordBean#hideNewPasswordComponent() показывает, что прослушиватели действий выполняются. Установка точки останова на ChangePasswordBean#getRenderNewPasswordComponent() показывает, что компонент пароля проверяет, должен ли он отображаться. Но этот метод выполняется как до, так и после запуска actionListener.

Вот последовательность вызовов метода actionListener при нажатии кнопки «Изменить пароль»:

  1. ChangePasswordBean#getRenderNewPasswordComponent() (возвращает false)

введите здесь описание изображения

  1. ChangePasswordBean#renderNewPasswordComponent() (устанавливает значение true)

введите здесь описание изображения

  1. ChangePasswordBean#getRenderNewPasswordComponent() (возвращает true)

введите здесь описание изображения

  1. ChangePasswordBean#getRenderNewPasswordComponent() (возвращает true)

введите здесь описание изображения

  1. ChangePasswordBean#getRenderNewPasswordComponent() (возвращает true)

введите здесь описание изображения

  1. ChangePasswordBean#getRenderNewPasswordComponent() (возвращает true)

введите здесь описание изображения

Не уверен, почему компонент пароля проверяет, должен ли он отображаться (№ 1) до того, как actionListener установит для рендеринга значение true (№ 2). Но похоже, что компонент пароля снова проверяет, должен ли он отображаться четыре раза после выполнения actionListener (например, в № 3, № 4, № 5 и № 6). Похоже ли это на правильный порядок выполнения?

Если порядок выполнения правильный, то, возможно, обновление происходит не в нужное время в последовательности или вообще не происходит. Как мне проверить на стороне сервера, выполняется ли обновление?

Или, возможно, есть что-то совершенно другое, что я упускаю из виду или неправильно понимаю?


person Patrick Garner    schedule 05.11.2015    source источник
comment
O/T: ваш «геттер» для логического значения «неправильный» stackoverflow.com/questions/7437803/ и stackoverflow.com/questions/2945061/   -  person Kukeltje    schedule 06.11.2015
comment
@Kukeltje первая ссылка, которую вы отправили, была очень полезной. Компонент пароля является вложенным, поэтому я изменил обновление на идентификатор его родителя, и теперь он отображается правильно. Однако теперь проверка поля пароля вообще не происходит. Нужно разобраться в этом сейчас.   -  person Patrick Garner    schedule 06.11.2015
comment
Держите это под рукой... jsf.zeef.com/bauke.scholtz Читать как можно больше Stackoverflow ссылки по возможности!   -  person Kukeltje    schedule 06.11.2015