Custom rendering (python)

import htmltools as html

from reactable.data import cars_93
from reactable import Reactable, Column, embed_css

embed_css()

data = cars_93[20:25, ["manufacturer", "model", "type", "price"]]

Cells

from reactable.models import CellInfo

def fmt_cell_red(ci: CellInfo):
    return html.div(ci.value.upper(), style="color: red")


Reactable(
    data,
    columns={"manufacturer": Column(cell=fmt_cell_red)},
)

Headers

from reactable.models import  HeaderCellInfo 

def fmt_header(ci: HeaderCellInfo):
    return html.div(f"name: {ci.name}", html.br(), f"value: {ci.value}")


Reactable(
    data,
    columns={"manufacturer": Column(header=fmt_header, name="Manufacturer")},
)

Footers

from reactable.models import ColInfo

def fmt_footer(ci: ColInfo):
    ttl = sum(ci.values)
    return f"${ttl:.2f}"


Reactable(
    data,
    searchable=True,
    columns={"price": Column(footer=fmt_footer)},
)

Note that a sum of $79.10 appears at the bottom right of the table. Importantly, if you filter the rows by typing into the search box, the sum won’t update. This is because Python footers are rendered only once, when generating the initial table.

Expandable row details

from reactable.models import RowInfo


# TODO: explain use of to_widget
def fmt_details(ci: RowInfo):
    return html.div(
        f"Details for row: {ci.row_index}",
        Reactable(data[ci.row_index, :]).to_widget(),
    )


Reactable(
    data[["model"]],
    details=fmt_details,
)

Why use javascript? Dynamic filtering

from reactable.models import JS

js_footer = JS(
    """
function(column, state) {
  let total = 0
  state.sortedData.forEach(function(row) {
    total += row[column.id]
  })
  return '<b>$' + total.toFixed(2) + '</b>'
}"""
)

Reactable(
    data,
    searchable=True,
    columns={
        "price": Column(
            html=True,
            footer=js_footer,
        ),
    },
)