Good looking Table for a Streamlit application... is anyone still using aggrid?

Hi, I am a long time fan of Streamlit.
Recently I have been building my company’s main internal data application using Streamlit, highlighting the benefits of using Python and being able to ship faster.
Still, when I am presenting the application to other stakeholders - like board members - the application is just “not good looking”, especially the tables.

Having a good looking table like “Aggrid” would solve 99% of the “ugliness” of streamlit data_editor / dataframe, but aggrid is simply buggy and not maintained.

Has anyone dealt with such scenario? How did you make the tables “beautiful”?

Note that I know the purpose of Streamlit, which is to make data applications easier to build, but it would make my life 100% better if I could shift the focus of my data application to the actual analysis, and not the “poor” design of dataframes.

Thanks a lot, João

Can you post a sample table that is good-looking?

I tried showing the datatables in streamlit, does this looks good?

1 Like

Hi Ferdy, thanks for the reply!
Yes it does, how did you do it?

I am thinking on using something like tailwind css to create some table component. The data editor seems a little raw in general.
this is a very beautiful example. Having something like this on streamlit would be incredible.

First we need an html template that can take a url that contains a csv.

table_template.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Beautiful Table with CSV Data</title>

        <!-- Include DataTables CSS and JS -->
        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.css">
        <script type="text/javascript" charset="utf8" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
        <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.js"></script>
    </head>
    <body>

        <!-- Table container -->
        <div style="width: 80%; margin: 20px 0 0 0; float: left;">
            <table id="beautifulTable" class="display">
                <thead>
                    <!-- Headers will be loaded dynamically from CSV -->
                </thead>
                <tbody>
                    <!-- Data will be loaded dynamically from CSV -->
                </tbody>
            </table>

        </div>

        <!-- Custom CSS for centering -->
        <style>
            .center { text-align: center; }
            th.dt-center, td.dt-center { text-align: center; }
        </style>

        <!-- Initialize DataTable -->
        <script>
            $(document).ready(function() {
                // Load data from CSV
                $.ajax({
                    type: "GET",
                    url: "{{ data_source_url }}",
                    dataType: "text",
                    success: function(data) {
                        processData(data);
                    }
                });

                function processData(allText) {
                    var allTextLines = allText.split(/\r\n|\n/);
                    var headers = allTextLines[0].split(',');
                    var lines = [];

                    // Generate table headers
                    var headerHTML = '<tr>';
                    for (var i = 0; i < headers.length; i++) {
                        headerHTML += '<th class="center">' + headers[i] + '</th>';
                    }
                    headerHTML += '</tr>';
                    $('#beautifulTable thead').html(headerHTML);

                    for (var i = 1; i < allTextLines.length; i++) {
                        var data = allTextLines[i].split(',');
                        if (data.length == headers.length) {
                            var tarr = [];
                            for (var j = 0; j < headers.length; j++) {
                                tarr.push(data[j]);
                            }
                            lines.push(tarr);
                        }
                    }

                    // Populate DataTable
                    $('#beautifulTable').DataTable({
                        data: lines,
                        columns: headers.map(function(header) {
                            return { title: header, className: "center" };
                        }),
                        "lengthMenu": [10, 20, 50, 100],
                        "autoWidth": true // Enable auto column width adjustment
                    });
                }
            });
        </script>
    </body>
</html>

app.py

import streamlit as st
from jinja2 import Environment, FileSystemLoader


st.set_page_config(layout='wide')


def render_html_template(url, table_template, width=1200, height=600, scrolling=True):
    # Load Jinja environment
    env = Environment(loader=FileSystemLoader('.'))
    template = env.get_template(table_template)

    # Render the template with the provided URL
    rendered_html = template.render(data_source_url=url)

    # Render the HTML content
    st.components.v1.html(rendered_html, width=width, height=height, scrolling=scrolling)


def main():
    template = 'table_template.html'

    st.title('Miles per Gallon Dataset')
    url = 'https://raw.githubusercontent.com/mwaskom/seaborn-data/master/mpg.csv'
    render_html_template(url, template, width=1300, height=600, scrolling=True)


if __name__ == '__main__':
    main()

Input your url here. Be careful on table size.

url = 'https://raw.githubusercontent.com/mwaskom/seaborn-data/master/mpg.csv'

You can customize the table by modifying the html template.

Output

Very nice table, can I use a similar method to display pandas’ dataframe?