在 Vaadin 中调用 FileDownloader 时使用过滤后的 dataProvider 内容
Use filtered dataProvider contents when FileDownloader is called in Vaadin
我尝试在对 DataProvider 应用过滤器后下载一个 csv 文件。
出于某种原因,过滤后的结果显示在网格中,但下载的 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>
其中 returns 一个包含 csv 数据的字符串。
如何才能在我的 csv 文件中获得过滤后的结果?
val csv = dataProvider.items.toList().toCsv()
我不是 Kotlin 专家,但我假设 dataProvider.items 是 Java 中的 shorthand 到 dataProvider.getItems(),即这个方法(并且您使用 ListDataProvider)
在 Vaadin getItems() returns 中通过所有过滤器的所有项目。
因此,您应该执行以下任一操作
dataProvider.fetch(..)
在您提供要在查询中应用的过滤器的位置,或
grid.getDataCommunicator.fetchItemsWithRange(..)
哪个 returns 项目列表应用了您设置的过滤器,我认为最适合您
感谢您使用 Vaadin-on-Kotlin!
我刚刚更新了 Databases Guide,希望它能回答您的所有问题。如果没有,请告诉我,我会相应地更新指南。
ListDataProvider.items
不会应用任何过滤器,并且始终 return 所有项目。
您需要使用 getAll()
扩展函数才能遵守 Grid 设置的过滤器。
现在在数据库指南的从 DataProviders 导出数据一章中对此进行了解释。
在您的代码中,grid
和 yearField
都会将过滤器设置为相同的数据提供者,
从而覆盖彼此设置的值。请阅读数据库指南中的链接数据提供程序一章,了解如何对多个组件设置的多个过滤器进行 AND 运算。
当您使用 private val dataProvider = DataProvider.ofCollection(FinancialTransaction.findAll())
时,这将从内存中的数据库加载所有事务。您可以使用更节省内存的方式:private val dataProvider = FinancialTransaction.dataProvider
(假定 FinancialTransaction
是一个 Entity
)
如果这回答了您的问题,请告诉我。谢谢!
我尝试在对 DataProvider 应用过滤器后下载一个 csv 文件。
出于某种原因,过滤后的结果显示在网格中,但下载的 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>
其中 returns 一个包含 csv 数据的字符串。
如何才能在我的 csv 文件中获得过滤后的结果?
val csv = dataProvider.items.toList().toCsv()
我不是 Kotlin 专家,但我假设 dataProvider.items 是 Java 中的 shorthand 到 dataProvider.getItems(),即这个方法(并且您使用 ListDataProvider)
在 Vaadin getItems() returns 中通过所有过滤器的所有项目。
因此,您应该执行以下任一操作
dataProvider.fetch(..)
在您提供要在查询中应用的过滤器的位置,或
grid.getDataCommunicator.fetchItemsWithRange(..)
哪个 returns 项目列表应用了您设置的过滤器,我认为最适合您
感谢您使用 Vaadin-on-Kotlin!
我刚刚更新了 Databases Guide,希望它能回答您的所有问题。如果没有,请告诉我,我会相应地更新指南。
ListDataProvider.items
不会应用任何过滤器,并且始终 return 所有项目。 您需要使用getAll()
扩展函数才能遵守 Grid 设置的过滤器。 现在在数据库指南的从 DataProviders 导出数据一章中对此进行了解释。在您的代码中,
grid
和yearField
都会将过滤器设置为相同的数据提供者, 从而覆盖彼此设置的值。请阅读数据库指南中的链接数据提供程序一章,了解如何对多个组件设置的多个过滤器进行 AND 运算。当您使用
private val dataProvider = DataProvider.ofCollection(FinancialTransaction.findAll())
时,这将从内存中的数据库加载所有事务。您可以使用更节省内存的方式:private val dataProvider = FinancialTransaction.dataProvider
(假定FinancialTransaction
是一个Entity
)
如果这回答了您的问题,请告诉我。谢谢!