H: commandButton несколько действий: загрузить файл и отобразить таблицу ajax
В настоящее время у меня есть две командные кнопки и один список. На основе выбора списка, сгенерированный результат может отображаться в файле, который можно загрузить, или отображается как таблица HTML. Код getFile()
основан на Учебном пособии по обработке BalusC PDF, а getTable()
устанавливает resultTable
.
<h:form>
<fieldset>
<h:selectManyListbox id="listbox" value="#{form.items}">
<f:selectItems value="#{form.allItems}">
</h:selectManyListbox>
</fieldset>
<h:commandButton value="Get File" action="#{form.getFile}">
<h:commandButton value="Get Table" action="#{form.getTable}">
<f:ajax render="result_table" execute="listbox" />
</h:commandButton>
<h:panelGrid id="result_table">
<table>
<thead></thead>
<tbody>
<ui:repeat var="table" value="#{form.resultTable}">
</ui:repeat>
</tbody>
</table>
</h:panelGrid>
Обе кнопки работают до сих пор. Однако я хочу объединить оба действия в одну кнопку. Когда я тестирую это с помощью кнопки, которая запускает оба действия, ничего не происходит (нет сохранения файла в виде диалога или таблицы). Это потому, что одно действие является ajax или потому что другое действие завершается с помощью facesContext.responseComplete();
?
<h:commandButton value="Get Both" action="#{form.getBoth}">
<f:ajax render="result_table" execute="listbox" />
</h:commandButton>
getBoth() {
getTable();
getFile();
}
Кроме того, я хотел бы установить флажок, если он установлен, сохранить, как открывается диалоговое окно, и отображается таблица. Если он не установлен, отображается только таблица.
Ответы
Ответ 1
К сожалению, это невозможно с HTTP. Вы можете отправить только один ответ за каждый запрос. Вы не можете объединить ответ, содержащий файл PDF, и ответ ajax в один ответ. Поскольку это ограничение HTTP, JSF не может сделать для вас многого. Кроме того, загрузка файла с использованием Ajax невозможна вообще, поскольку JavaScript не может заставить браузер вызывать диалог "Сохранить как" и не иметь доступа к локальной файловой системе на диске из-за ограничений безопасности.
Обходным путем было бы запустить два HTTP-запроса одним нажатием кнопки, где второй запрос возвращает Content-Disposition: attachment
, чтобы отклик другого запроса оставался нетронутым. Вы можете добиться этого, добавив onclick
к командной кнопке.
<h:commandButton onclick="window.location='/context/pdfservlet/filename.pdf'">
и создайте сервлет PDF, который примерно похож на этот пример FileServlet. Как вы видите, невозможно вызвать действие JSF этим. Вы должны реорганизовать метод загрузки PDF в класс HttpServlet
, который выполняет задание в методе doGet()
. Для любой необходимой связи между управляемым JSF bean и сервлетом вы можете использовать область сеанса или передать желаемую информацию (только идентификатор файла PDF?) По пути или параметру запроса.
Ответ 2
Я перехожу на аналогичный случай, в моем случае я получаю решение с помощью ajax richfaces tag lib и surround commandbuton с тегом формы ajax.
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j">
<a4j:form id="formDownloads">
<rich:panel>
<h:commandButton value="Exportar para PDF" status= "block" ... />
</rich:panel>
</a4j:form>