Files
2026-02-08 11:20:43 -10:00

290 lines
7.6 KiB
Markdown
Vendored

[//]: # (title: toHtml)
<!---IMPORT org.jetbrains.kotlinx.dataframe.samples.api.Render-->
## HTML rendering
`DataFrame` instances can be rendered to HTML.
Rendering of hierarchical tables in HTML is supported by JS and CSS definitions
that can be found in project resources.
Dataframes can also be formatted before being converted to HTML.
See [](format.md) for how to do this.
Besides that, DataFrame provides multiple APIs to customize HTML output.
### Display images
Values of the `org.jetbrains.kotlinx.dataframe.datatypes.IMG` class are rendered as an `<img>` tag
<!---FUN displayImg-->
```kotlin
val htmlData = dataFrameOf(
"kotlinLogo" to columnOf(
IMG("https://kotlin.github.io/dataframe/images/kotlin-logo.svg"),
),
).toStandaloneHtml()
```
<!---END-->
### Embed pages
Values of the `org.jetbrains.kotlinx.dataframe.datatypes.IFRAME` class are rendered as an `<iframe>` tag
<!---FUN displayIFrame-->
```kotlin
val htmlData = dataFrameOf(
"documentationPages" to columnOf(
IFRAME(
src = "https://kotlin.github.io/dataframe/tohtml.html",
width = 850,
height = 500,
),
),
).toStandaloneHtml()
```
<!---END-->
### Render clickable links
Values of `java.net.URL` are rendered as `<a>` tag
<!---FUN displayURL-->
```kotlin
val htmlData = dataFrameOf(
"documentationPages" to columnOf(
URI("https://kotlin.github.io/dataframe/format.html").toURL(),
URI("https://kotlin.github.io/dataframe/tohtml.html").toURL(),
URI("https://kotlin.github.io/dataframe/jupyterrendering.html").toURL(),
),
).toStandaloneHtml()
```
<!---END-->
### Render any HTML inside a cell
Wrap cell values in custom HTML using `RenderedContent.media`
<!---FUN displayMediaContent-->
<tabs>
<tab title="Properties">
```kotlin
val htmlData = dataFrameOf(
"documentationPages" to columnOf(
"https://kotlin.github.io/dataframe/format.html",
"https://kotlin.github.io/dataframe/tohtml.html",
"https://kotlin.github.io/dataframe/jupyterrendering.html",
),
)
.convert { documentationPages }.with {
val uri = URI(it)
RenderedContent.media("""<a href='$uri'>${uri.path}</a>""")
}
.toStandaloneHtml()
```
</tab>
<tab title="Strings">
```kotlin
val htmlData = dataFrameOf(
"documentationPages" to columnOf(
"https://kotlin.github.io/dataframe/format.html",
"https://kotlin.github.io/dataframe/tohtml.html",
"https://kotlin.github.io/dataframe/jupyterrendering.html",
),
)
.convert { "documentationPages"<String>() }.with {
val uri = URI(it)
RenderedContent.media("""<a href='$uri'>${uri.path}</a>""")
}
.toStandaloneHtml()
```
</tab></tabs>
<!---END-->
### Sample data
This dataframe is used in the following examples
<!---FUN df-->
```kotlin
val df = dataFrameOf(
"name" to columnOf(
"firstName" to columnOf("Alice", "Bob", "Charlie", "Charlie", "Bob", "Alice", "Charlie"),
"lastName" to columnOf("Cooper", "Dylan", "Daniels", "Chaplin", "Marley", "Wolf", "Byrd"),
),
"age" to columnOf(15, 45, 20, 40, 30, 20, 30),
"city" to columnOf("London", "Dubai", "Moscow", "Milan", "Tokyo", null, "Moscow"),
"weight" to columnOf(54, 87, null, null, 68, 55, 90),
"isHappy" to columnOf(true, true, false, true, true, false, true),
)
```
<!---END-->
### Reusable rendering logic
Generic approach to custom cell rendering. Useful if you want to apply the same rendering to different dataframes.
<!---FUN cellRenderer-->
```kotlin
class CustomArrayCellRenderer : ChainedCellRenderer(DefaultCellRenderer) {
override fun maybeContent(value: Any?, configuration: DisplayConfiguration): RenderedContent? {
if (value is Boolean) {
return RenderedContent.text(if (value) "" else "")
}
// return null to delegate work to parent renderer: DefaultCellRenderer
return null
}
override fun maybeTooltip(value: Any?, configuration: DisplayConfiguration): String? {
// return null to delegate work to parent renderer: DefaultCellRenderer
return null
}
}
val htmlData = df.toStandaloneHtml(cellRenderer = CustomArrayCellRenderer())
```
<!---END-->
### Custom HTML outside the table
The result of `toHtml` can be composed with other HTML, CSS, or JS definitions.
Let's build an alternative to displaying all rows in one table: custom pagination across multiple files
<!---FUN appendCustomHtml-->
```kotlin
val pages = df.duplicateRows(10).chunked(20)
val files = pages.indices.map { i -> File("page$i.html") }
val navLinks = files.mapIndexed { i, file ->
"""<a href="${file.name}">Page ${i + 1}</a>"""
}.joinToString(" | ")
pages.forEachIndexed { i, page ->
val output = files[i]
page.toStandaloneHtml().plus(DataFrameHtmlData(body = navLinks))
// uncomment
// .writeHtml(output)
}
```
<!---END-->
### Custom style and scripts
Let's add a hover effect and click listener for table cells.
See [init.js](https://github.com/Kotlin/dataframe/blob/704200cb86e7bdc07b800a7cfef48de408bd5fe8/core/src/main/resources/init.js) and [table.css](https://github.com/Kotlin/dataframe/blob/ead4f8666df5cf24e5bf45d245cda3200e150e93/core/src/main/resources/table.css) for reference.
<!---FUN interactiveJs-->
```kotlin
val selectCellInteraction = DataFrameHtmlData(
style =
"""
td:hover {
background-color: rgba(0, 123, 255, 0.15);
cursor: pointer;
}
""".trimIndent(),
script =
"""
(function() {
let cells = document.querySelectorAll('td');
cells.forEach(function(cell) {
cell.addEventListener('click', function(e) {
let content = cell.textContent;
alert(content);
});
});
})();
""".trimIndent(),
)
// keep in mind JS script initialization order.
val htmlData = df.toStandaloneHtml().plus(selectCellInteraction)
```
<!---END-->
Depending on your environment, there can be different ways to use the result of `toHtml` functions.
## IntelliJ IDEA
### Working with the result
The following function produces HTML that includes JS and CSS definitions.
It can be displayed in the browser and has parameters for customization.
<!---FUN useRenderingResult-->
```kotlin
val configuration = DisplayConfiguration(rowsLimit = null)
df.toStandaloneHtml(configuration).openInBrowser()
df.toStandaloneHtml(configuration).writeHtml(File("/path/to/file"))
df.toStandaloneHtml(configuration).writeHtml(Path("/path/to/file"))
```
<!---END-->
### Composing multiple tables
`toHtml` and `toStandaloneHtml` return composable `DataFrameHtmlData`,
which you can use to include additional scripts, elements,
or styles at the end of the page or just to merge multiple tables into one HTML snippet.
<!---FUN composeTables-->
<tabs>
<tab title="Properties">
```kotlin
val df1 = df.reorderColumnsByName()
val df2 = df.sortBy { age }
val df3 = df.sortByDesc { age }
listOf(df1, df2, df3).fold(DataFrameHtmlData.tableDefinitions()) { acc, df -> acc + df.toHtml() }
```
</tab>
<tab title="Strings">
```kotlin
val df1 = df.reorderColumnsByName()
val df2 = df.sortBy("age")
val df3 = df.sortByDesc("age")
listOf(df1, df2, df3).fold(DataFrameHtmlData.tableDefinitions()) { acc, df ->
acc + df.toHtml()
}
```
</tab></tabs>
<!---END-->
## Jupyter Notebooks
### Configuring display for individual output
`toHtml` is useful if you want to configure how a single cell is displayed.
To configure the display for the entire notebook, please refer to the [](jupyterRendering.md) section.
<!---FUN configureCellOutput-->
```kotlin
df.toHtml(DisplayConfiguration(cellContentLimit = -1))
```
<!---END-->