How to generate a html.Table with a for loop?

1.1k views Asked by At

I'm trying to generate a html.Table in my dash app. The table should have 2 columns and max. 5 rows. The first one showing the customer names and the second one their total revenue for the year.

def generate_html_table(max_rows=5):
    return html.Div([
                html.Div(html.Table(id='Customer Top'
                    #header
                    [html.Tr(html.Th())]
                +
                    #body
                    [html.Tr([
                        html.Td(html.A(
                        topCustomers.iloc[i]['Customer'],
                            topCustomers.iloc[i]['Total Including Tax']
                        ))
                    ])
                     for i in range(min(len(topCustomers),max_rows))
                    ]
                ))
    ])

When I run the app I get a TypeError: string indices must be integers

UPDATE:

I fixed the above mentioned error by changing my code to this:

def generate_html_table(max_rows=5):
    return html.Div([
                html.Div(html.Table(
                    [html.Tr(html.Th()),
                    html.Tbody(html.Tr([
                        html.Td(html.A(
                        topCustomers.iloc[i]['Customer'],
                        topCustomers.iloc[i]['Total Including Tax']
                        ))
                    ])                      for i in range(min(len(topCustomers),max_rows))
                              )
                    ]
                ), id='Top Customer')
    ])

But now the dash app won't load the layout. I'm not quite sure what the problem is, but it tells me TypeError: Object of type generator is not JSON serializable

Any idea how to fix that?

1

There are 1 answers

2
coralvanda On

Your return statement is returning a generator, because of the list comprehension you've used. Instead, build the table and put it in a variable, then return that variable. You may need to call list() on it to have it build the whole thing before outputting it.

You could also restructure the loop in a more basic way such as:

for x in 'abc':
   do_stuff()

and within that loop build the table, only returning it after the loop completes.

Edit: I used a dummy dataframe and was able to get the page to load data with this:

def generate_html_table(max_rows=5):
    rows = []
    for i in range(min(len(topCustomers), max_rows)):
        rows.append(html.Tr([
            html.Td(html.A([
                topCustomers.iloc[i]['Customer'],
                topCustomers.iloc[i]['Total Including Tax']
            ], id=str(i))
        ]))

    return html.Div([
        html.Div(html.Table(
            [
                html.Tr(html.Th()),
                html.Tbody(rows),
            ]
        ), id='Top Customer')
    ])