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 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
val htmlData = dataFrameOf(
"kotlinLogo" to columnOf(
IMG("https://kotlin.github.io/dataframe/images/kotlin-logo.svg"),
),
).toStandaloneHtml()
Embed pages
Values of the org.jetbrains.kotlinx.dataframe.datatypes.IFRAME class are rendered as an <iframe> tag
val htmlData = dataFrameOf(
"documentationPages" to columnOf(
IFRAME(
src = "https://kotlin.github.io/dataframe/tohtml.html",
width = 850,
height = 500,
),
),
).toStandaloneHtml()
Render clickable links
Values of java.net.URL are rendered as <a> tag
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()
Render any HTML inside a cell
Wrap cell values in custom HTML using RenderedContent.media
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()
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()
Sample data
This dataframe is used in the following examples
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),
)
Reusable rendering logic
Generic approach to custom cell rendering. Useful if you want to apply the same rendering to different dataframes.
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())
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
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)
}
Custom style and scripts
Let's add a hover effect and click listener for table cells. See init.js and table.css for reference.
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)
Depending on your environment, there can be different ways to use the result of toHtml functions.