Выражение EL внутри p: commandButton onclick не обновляет / повторно визуализирует по запросу ajax? - PullRequest
3 голосов
/ 11 января 2012

Атрибут onclick моего commandButton содержит некоторый зависимый от EL Javascript внутри. Чтобы быть более конкретным, вот этот кусок кода:

<p:commandButton
    onclick="javascript: if('#{userBean.user.friendList.size() gt 0}' == 'true') deleteFriendsConfirmDialog.show(); else friendsAlreadyDeletedErrorDialog.show();"
    value="Delete all friends?" />

deleteFriendsConfirmDialog очищает список друзей и обновляет @form. Список друзей, commandButton и диалоговые окна находятся в этой форме.

Итак, я нажимаю кнопку, появляется диалоговое окно подтверждения (поскольку длина списка друзей - gt 0), я подтверждаю, и список очищается, представление обновляется. Однако, когда я нажимаю кнопку Delete all friends? еще раз, снова появляется диалоговое окно подтверждения. Поскольку длина списка теперь равна 0, я ожидаю, что появится диалоговое окно с сообщением об ошибке.

Это, я думаю, потому, что Javascript, написанный внутри onclick, не обновляется (хотя кнопка в форме).

Редактировать: Изменение #{userBean.user.friendList.size() gt 0} на #{not empty userBean.user.friendList} также не работает.

Как получилось? Что здесь не так?

Любая помощь приветствуется. :)

1 Ответ

5 голосов
/ 11 января 2012

Действительно. PrimeFaces (и стандартный JSF) не переоценивает EL в атрибутах on* для каждого запроса. Это происходит только на основе просмотра. Однако RichFaces делает это в <a4j:xxx> компонентах.

Вам нужно решить проблему по-другому. Я предлагаю вместо этого использовать visible атрибут <p:dialog>.

<h:form>
    ...
    <p:commandButton value="Delete all friends?" update=":deleteDialogs" />
</h:form>
...
<h:panelGroup id="deleteDialogs">
    <p:dialog id="deleteFriendsConfirmDialog" visible="#{facesContext.postback and not empty userBean.user.friendList}">
        ...
    </p:dialog>
    <p:dialog id="friendsAlreadyDeletedErrorDialog" visible="#{facesContext.postback and empty userBean.user.friendList}">
        ...
    </p:dialog>
</h:panelGroup>

Альтернативой является использование RequestContext PrimeFaces в методе действия bean-компонента, который позволяет программно выполнять код JavaScript в методе действия bean-компонента (хотя это слишком сильно связывает контроллер с представлением, IMO).

<p:commandButton value="Delete all friends?" action="#{userBean.deleteAllFriends}" />

с

RequestContext context = RequestContext.getCurrentInstance();

if (!user.getFriendList().isEmpty()) {
    context.execute("deleteFriendsConfirmDialog.show()");
} else {
    context.execute("friendsAlreadyDeletedErrorDialog.show()");
}

Не связанный с конкретной проблемой, ваш исходный onclick, хотя он не работает в вашем конкретном случае, показывает некоторые плохие практики. Псевдопротокол javascript: является излишним. Это уже по умолчанию. Убери это. Также лишним является тест против == 'true'. Убери это. Просто позвольте EL печатать true или false напрямую. Ниже приведен правильный синтаксис (опять же, это не решает вашу проблему, только для вашей информации)

<p:commandButton
    onclick="if (#{not empty userBean.user.friendList}) deleteFriendsConfirmDialog.show(); else friendsAlreadyDeletedErrorDialog.show();"
    value="Delete all friends?" />

Это бы сработало, если бы вы использовали RichFaces <a4j:commandButton>.

<a4j:commandButton
    oncomplete="if (#{not empty userBean.user.friendList}) deleteFriendsConfirmDialog.show(); else friendsAlreadyDeletedErrorDialog.show();"
    value="Delete all friends?" />
...