2015-07-21 2 views
0

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

Мы используем такой ресурс, он должен позволить динамически загружать, в зависимости от выбранных элементов

private StreamResource createResource(final IndexedContainer container) { 
     return new StreamResource(new StreamSource() { 
      @Override 
      public InputStream getStream() { 

       for (Object o : container.getItemIds()) { 
        CheckBox checkbox = (CheckBox) container.getItem(o).getItemProperty(C_CHECK_BOX).getValue(); 
        if (checkbox.getValue()) { 
         selectedFiles.add(o); 
        } 
       } 
       // do some magic to get stream of selected files 


      } 
     }, "download.zip"); 
} 

Проблема заключается в том, что только второй и после нажмите на кнопку, дает ожидаемые restults.

Получилось, что FileDownoader получает ресурс с сервера, а затем отправляет текущий статус компонента. Это причина, почему первый клик дает устаревший результат.

У вас есть идеи, как преодолеть это? Можно ли заставить: сначала обновить компонент, а затем загрузить ресурс?

Большое спасибо Pawel

+0

Попробуйте вызвать setImmediate (true); для CheckBoxes при их создании. –

ответ

2

CheckBox в Vaadin не является немедленным по умолчанию, что означает, что он не будет посылать запрос сервер, когда флажок установлен (или не установлен) в браузере. Непосредственные компоненты отправляют очереди на немедленные события также на сервер, но, похоже, что FileDownloader не вызывает событие, которое будет отправлять на сервер немедленные значения флажка.

Единственное, что вам нужно сделать, это установить ваши флажки, чтобы быть немедленным при создании тех:

checkBox.setImmediate(true); 
+0

Я протестировал его, и он работает! Я решил это также с помощью пользовательского переключателя изменения стоимости на флажке, но ваши решения более элегантны. Спасибо – smolarek999

+0

@ smolarek999 Да, добавление ValueChangeListener к нему делает компонент также немедленным в самых последних версиях Vaadin. –

0

FileDownloader не будет отвечать вашим потребностям. Как вы можете прочитать в документации:

Загрузка должна запускаться непосредственно при нажатии пользователем, например. a Button, не проходя через серверный прослушиватель кликов, чтобы избежать запуска предупреждений о безопасности в некоторых браузерах.

Это означает, что вы не можете динамически генерировать файл download.zip, определяемый значениями флажков, потому что для этого требуется поездка на сервер.

У вас есть как минимум 2 варианта. Либо создайте новый FileDownloader и создайте новый Resourcedownload.zip каждый раз, когда пользователь вносит изменения в эти флажки. Или же вы можете добавить простой ClickListener к вам кнопки с этой строки кода:

getUI().getPage().open(resource, "_blank", false); 

Связанные: Vaadin - How to open BrowserWindowOpener from a SINGLE BUTTON

+0

Я не думаю, что здесь проблема. См. Мой ответ. –

+0

Возможно, я ошибаюсь, но я дал наилучшее предположение AFAIU OP. Нам нужно подождать, пока smolarek999 решит это. – kukis

+0

Вы правы :) –

0

Существует также альтернативное решение установить checkBox.setImmediate(true);. Можно отправить текущее состояние всех компонентов, непосредственно перед нажатием, вместо отправки каждого изменения checkbox.

Это решение основано на этом ответе: https://stackoverflow.com/a/30643199/1344546

Вам нужно создать кнопку загрузчик файлов и скрыть его:

Button hiddenButton = new Button();  
hiddenButton.setId(HIDDEN_ID); 
hiddenButton.addStyleName("InvisibleButton"); 
StreamResource zipResource = createResource(container); 
FileDownloader fd = new FileDownloader(zipResource); 
fd.extend(hiddenButton); 

Добавить правило CSS к вашей теме

.InvisibleButton { 
    display: none; 
} 

А потом создайте еще одну кнопку, в которой первое состояние обновления, а затем нажмите скрытую кнопку.

Button zipDownload = new Button("Download as ZIP file"); 
zipDownload.addClickListener(new Button.ClickListener() { 
    @Override 
    public void buttonClick(Button.ClickEvent event) {  
      Page.getCurrent().getJavaScript() 
     .execute(String.format("document.getElementById('%s').click();", HIDDEN_ID)); 
      } 
     }); 
Смежные вопросы