Используйте отфильтрованное содержимое dataProvider при вызове FileDownloader в Vaadin - PullRequest
0 голосов
/ 13 мая 2018

Я пытаюсь загрузить CSV-файл после применения фильтров к DataProvider.

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

@AutoView
class FinancialTransactionsView : VerticalLayout(), View {    
    private val grid: Grid<FinancialTransaction>
    private val yearField: ComboBox<Int>

    private val dataProvider = DataProvider.ofCollection(FinancialTransaction.findAll())
    private val fileDownloader: FileDownloader

    init {
        label("Financial Transactions") {
            styleName = ValoTheme.LABEL_H1
        }

        yearField = comboBox("Select Year") {
            setItems(listOf(2016, 2017, 2018))

            addSelectionListener {
                // Filter the data based on the selected year
                if (it.value != it.oldValue) setDataProvider()
            }
        }

        // Create FileDownloader and initialize with all contents in the DataProvider
        fileDownloader = FileDownloader(createCsvResource())

        val downloadButton = button("Download csv") {
            styleName = ValoTheme.BUTTON_PRIMARY

            onLeftClick {
                // The idea here is to assign values from the filtered DataProvider to the FileDownloader
                fileDownloader.fileDownloadResource = createCsvResource()
            }
        }

        fileDownloader.extend(downloadButton)
        fileDownloader.fileDownloadResource = createCsvResource()

        grid = grid(dataProvider = dataProvider) {

            expandRatio = 1f
            setSizeFull()
            addColumnFor(FinancialTransaction::companyId)
            addColumnFor(FinancialTransaction::fiscalYear)
            addColumnFor(FinancialTransaction::fiscalPeriod)
            addColumnFor(FinancialTransaction::currency)
            addColumnFor(FinancialTransaction::finalizedDebitAmountInCurrency)
            addColumnFor(FinancialTransaction::finalizedCreditAmountInCurrency)

            appendHeaderRow().generateFilterComponents(this, FinancialTransaction::class)
        }
    }

    private fun createCsvResource(): StreamResource {
        return StreamResource(StreamResource.StreamSource {

            val csv = dataProvider.items.toList().toCsv()

            try {
                return@StreamSource csv.byteInputStream()
            } catch (e: IOException) {
                e.printStackTrace()
                return@StreamSource null
            }
        }, "financial_transactions.csv")
    }

    private fun setDataProvider() {
        dataProvider.clearFilters()

        if (!yearField.isEmpty)
            dataProvider.setFilterByValue(FinancialTransaction::fiscalYear, yearField.value)
    }
}

toCsv() - это функция расширения List<FinancialTransaction>, которая возвращает строку, содержащую данные CSV.

Что я могу сделать, чтобы получить отфильтрованные результаты в моем файле CSV?

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Спасибо за использование Vaadin-on-Kotlin!

Я только что обновил Руководство по базам данных , которое, мы надеемся, ответит на все ваши вопросы. Если нет, просто дайте мне знать, и я соответствующим образом обновлю руководства.

  1. ListDataProvider.items не будет применять фильтры и всегда будет возвращать все элементы. Вам необходимо использовать функцию расширения getAll(), чтобы подчиняться фильтрам, установленным сеткой. Теперь это объясняется в главе «Экспорт данных из DataProviders» в Руководстве по базам данных.

  2. В вашем коде и grid, и yearField установят фильтр на одного и того же поставщика данных, при этом значения перезаписываются друг на друга. Прочтите главу «Поставщики цепочек данных» в Руководстве по базам данных, чтобы узнать, как И несколько фильтров, установленных несколькими компонентами.

  3. Когда вы используете private val dataProvider = DataProvider.ofCollection(FinancialTransaction.findAll()), это загрузит все транзакции из базы данных в память. Вы можете использовать более эффективный способ памяти: private val dataProvider = FinancialTransaction.dataProvider (учитывая, что FinancialTransaction является Entity)

Пожалуйста, дайте мне знать, если это ответит на ваши вопросы. Спасибо!

0 голосов
/ 13 мая 2018

val csv = dataProvider.items.toList (). ToCsv ()

Я не котлин, но я предполагаю, что dataProvider.items - это сокращениедля dataProvider.getItems () в Java, т.е. этот метод (и вы используете ListDataProvider)

https://vaadin.com/download/release/8.4/8.4.1/docs/api/com/vaadin/data/provider/ListDataProvider.html#getItems--

В Vaadin getItems () возвращает все элементы, передавая все фильтры.

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

dataProvider.fetch(..)

https://vaadin.com/download/release/8.4/8.4.1/docs/api/com/vaadin/data/provider/DataProvider.html#fetch-com.vaadin.data.provider.Query-

Где вы указываете фильтры, которые вы хотите применить в запросе, или

grid.getDataCommunicator.fetchItemsWithRange(..)

https://vaadin.com/download/release/8.4/8.4.1/docs/api/com/vaadin/data/provider/DataCommunicator.html#fetchItemsWithRange-int-int-

Возвращает список элементов с установленными вами фильтрами, что, я думаю, идеально подходит для вас

...