Как обновить страницу после загрузки - PullRequest
4 голосов
/ 13 августа 2010

У меня есть commandButton, который будет вызывать функцию для загрузки файла (стандартные вещи, такие как InputStream, BufferedOutputStream ...). После успешного завершения загрузки в конце функции я изменяю некоторые значения текущего объекта.и сохранить его в базу данных.Все это работает правильно.Теперь, когда загрузка файла завершена, содержимое страницы не обновляется.Я должен нажать обновить, чтобы увидеть обновленный контент.Пожалуйста помоги.Ниже приведена базовая структура моего кода

document: управляемый компонент
getDrawings(): метод, возвращающий список Drawing (класс сущности)
CheckedOutBy: атрибут Entity Drawing

<p:dataTable id="drawing_table" value="#{document.drawings}" var="item" >                            
    <p:column>
        <f:facet name="header">
              <h:outputText value="CheckedOutBy"/>
        </f:facet>
        <h:outputText value="#{item.checkedOutBy}"/>
        ...
</p:dataTable>
<p:commandButton ajax="false" action="#{document.Download}" value="Download" />

Внутри моего управляемого боба

public void Download(){
    Drawing drawing = getCurrentDrawing();
    //Download drawing
    drawing.setCheckedOutBy("Some Text");
    sBean.merge(drawing);  //Update "Some Text" into CheckedOutBy field
}

Ответы [ 4 ]

4 голосов
/ 13 августа 2010

Вы бы хотели позволить клиенту запускать два запроса.Один для загрузки и другой для обновления новой страницы.Они не могут быть сделаны в одном запросе HTTP.Поскольку загрузка должна выполняться синхронно, и нет никакой возможности подключить завершение загрузки со стороны клиента, нет чистых JSF / JS / Ajax-способов обновить компонент по завершении загрузки.

Ваша лучшая JSF-ставка с помощью PrimeFaces - <p:poll>

<h:outputText id="checkedOutBy" value="#{item.checkedOutBy}"/>
...
<p:poll id="poll" interval="5" update="checkedOutBy" />

или <p:push>

<p:push onpublish="javaScriptFunctionWhichUpdatesCheckedOutBy" />  

Pollingэто легко, но я могу представить, что это добавляет ненужные накладные расходы.Вы не можете запустить его, используя стандартные компоненты JSF / PrimeFaces, когда начинается синхронная загрузка.Но вы можете остановить его, чтобы он мог выполнить самопроверку атрибута rendered.Толчок является технически лучшим решением, но с ним сложнее начать.Однако PrimeFaces объясняет его использование в главе 6 Руководства пользователя.

2 голосов
/ 09 апреля 2013

Ну, я решил пойти с ответом / рекомендацией BalusC выше и решил поделиться своим кодом здесь для людей, которые могут зайти сюда, «позже».К вашему сведению, моя окружающая среда представлена ​​ниже:

TomEE 1.6.0 SNAPSHOT (Tomcat 7.0.39), PrimeFaces 3.5 (PrimeFaces Push), снимок Atmosphere 1.0.13 (1.0.12 - последняя стабильная версия)

Прежде всего, я использую p: fileDownload с p: commandLink.

<p:commandLink value="Download" ajax="false"
               actionListener="#{pf_ordersController.refreshDriverWorksheetsToDownload()}">
    <p:fileDownload value="#{driverWorksheet.file}"/>
</p:commandLink>

Так как у меня есть xhtml выше, и так как p: fileDownload не позволяет oncomplete = "someJavaScript ()" длячтобы выполнить, я решил использовать PrimeFaces Push для отправки сообщения клиенту, чтобы активировать JavaScript, необходимый для разблокировки интерфейса, потому что интерфейс блокировался всякий раз, когда я нажимал на команду commandLink для загрузки файла, и в течение многих месяцев я не знал, какЧтобы решить эту проблему.

Поскольку я уже использую PrimeFaces Push, мне пришлось настроить на стороне клиента следующее:

.js file;содержит метод, который обрабатывает сообщения, отправленные с сервера на клиент

function handlePushedMessage(msg) {
    /* refer to primefaces.js, growl widget,
     * search for: show, renderMessage, e.detail
     * 
     * sample msg below:
     * 
     * {"data":{"summary":"","detail":"displayLoadingImage(false)","severity":"Info","rendered":false}}
     */
    if (msg.detail.indexOf("displayLoadingImage(false)") != -1) {
        displayLoadingImage(false);
    }
    else {
        msg.severity = 'info';
        growl.show([msg]);
    }
}

index.xhtml;содержит компонент p: socket (PrimeFaces Push);Я рекомендую все следующее, если вы реализуете FacesMessage пример PrimeFaces Push

<h:outputScript library="primefaces" name="push/push.js" target="head" />
<p:growl id="pushedNotifications" for="socketForNotifications"
         widgetVar="growl" globalOnly="false"
         life="30000" showDetail="true" showSummary="true" escape="false"/>
<p:socket id="socketForNotifications" onMessage="handlePushedMessage"
          widgetVar="socket"
          channel="/#{pf_usersController.userPushChannelId}" />

Месяцев (или, может быть, год или около того) назад, я счел необходимым добавить следующее кcommandLink, который оборачивает p: fileDownload, который обновит файл / поток на сервере, так что вы можете щелкнуть файл столько раз, сколько вам нужно, и загрузить файл снова и снова без обновления страницы с помощью клавиши F5 / refresh на клавиатуре (или аналогичнойна мобильном устройстве)

actionListener="#{pf_ordersController.refreshDriverWorksheetsToDownload()}"

На этот метод bean ссылаются всякий раз, когда конечный пользователь нажимает на commandLink для загрузки файла, так что это было идеальное место для «передачи» сообщения с сервера на клиент, для запуска JavaScript на клиенте,чтобы разблокировать пользовательский интерфейс.

Ниже приведены методы bean-компонентов в моем приложении, которые выполняют свою работу.:)

pf_ordersController.refreshDriverWorksheetsToDownload ()

public String refreshDriverWorksheetsToDownload() {
    String returnValue = prepareDriverWorksheetPrompt("download", false);
    usersController.pushNotificationToUser("displayLoadingImage(false)");
    return returnValue;
}

usersController.pushNotificationToUser ();я должен был добавить это сегодня вечером.

public void pushNotificationToUser(String notification) {
    applicationScopeBean.pushNotificationToUser(notification, user);
}

applicationScopeBean.pushNotificationToUser ();это уже существовало, без изменений в этом методе.

public void pushNotificationToUser(String msg, Users userPushingMessage) {
    for (SessionInfo session : sessions) {
        if (userPushingMessage != null &&
            session.getUser().getUserName().equals(userPushingMessage.getUserName()) &&
            session.getUser().getLastLoginDt().equals(userPushingMessage.getLastLoginDt())) {
            PushContext pushContext = PushContextFactory.getDefault().getPushContext();
            pushContext.push("/" + session.getPushChannelId(),
                             new FacesMessage(FacesMessage.SEVERITY_INFO, "", msg));
            break;
        }
    }
}
0 голосов
/ 09 апреля 2015

При ответе Balusc мы не можем получить ответ дважды от одного запроса.

Чтобы обновить страницу после загрузки, лучше использовать следующий java-скрипт в ссылке для скачивания (p:commandbutton) тег onclick .

Пример:

<p:commandButton ajax="false" icon="ui-icon-arrowstop-1-s" onclick="setTimeout('location.reload();', 1000);" action="#{managedBean.downloadMethod}" />

это автоматически обновит страницу через 1 секунду, в то же время, т.е. до обновления,Вы получите файл загрузки, основываясь на времени отклика, и увеличите количество секунд в этом сценарии. Секунды должны быть не меньше, чем время отклика при загрузке.

0 голосов
/ 13 августа 2010

Вы можете использовать атрибут update компонента p:commandButton для повторного рендеринга области, которую вы намереваетесь обновить после загрузки, в данном случае - вашего "drawing_table".

<p:commandButton update="drawing_table" action="#{document.Download}" value="Download" />
...