Editable DataTable entry class

I’m having trouble with my graph that gets updated by an editable DataTable. I keep getting an error that i can’t multiply strings by numbers, but I’m not sure how to control the type of an entry in the table. Even if I type a number like 2, it treats is at a string, ‘2’ Here is my code:

html.Div([
    dcc.Graph(id='graph-1'),
    html.H5('Drill Bits', style={'textAlign':'center'}),
    dash_table.DataTable(
        id='table-1',
        columns = [{'name':i,'id':i} for i in ['col1','col2']],
        data=[],
        editable=True,
        row_deletable=True,
        # style_as_list_view=True,
        style_cell={
            'textAlign': 'center'
            }
    ),
    html.Button('Add Row', id='add-row-button', n_clicks=0),
    dcc.Store(id='store-1',storage_type='session')
],
style = {'padding': 10}
)

@app.callback(
>     Output('table-1', 'data'),
>     [Input('add-row-button', 'n_clicks')],
>     [State('store-1', 'data')])
> def add_row(n_clicks, rows):
>     if n_clicks > 0:
>         if not rows:
>             rows = [{c: 0 for c in ['col1','col2']}]
>         else:
>             rows.append({c: 0 for c in ['col1','col2]})
>         return rows
>     else:
>         if rows:
>             return rows
>         raise PreventUpdate
>     
> 
> @app.callback(
>     Output('graph-1', 'figure'),
>     [Input('table-1', 'data')])
> def graph(rows):
>     print([row.get('col1',None) for row in rows])
>     # x = [max(row['col2'] for row in row)]
>     x=[0]
>     y = [0]
>     for row in rows:
>         x.append(row.get('col1',None))
>         y.append(row.get('col2',None)*row.get('col1',None)*24)
>     return dict(
>         data= [
>             go.Scatter(
>                 x=x,
>                 y=y
>             )
>         ]
>     )

I’m assuming that you’re having issues with the multiplication in:
y.append(row.get(‘col2’,None)*row.get(‘col1’,None)*24).

I had something similar and I had to do the following:
row[‘Conf minus Freddie’] = round(float(row[‘WFC Conf Int Rate’]) - float(row[‘Freddie Mac’]),3)

This made sure that each ‘item’ was a float and that I could round the answer to 3 decimal places.

1 Like

Yes that’s the part I have trouble with. It looks like maybe I can specify type in columns too? https://dash.plot.ly/datatable/reference

We’re talking about the for loop ‘for row in rows’, correct?

I’ve named my columns (look for examples with name and id when you define the columns).

I’m not trying to append data in my version of the for loop. I have some editable fields in my data table and someone has changed a value in one of those fields. I’m re-calculating the data in the columns whose value could be affected. The entire for loop is as follows:
for row in rows:
row[‘Conf minus Freddie’] = round(float(row[‘WFC Conf Int Rate’]) - float(row[‘Freddie Mac’]),3)
row[‘Jumbo minus Freddie’] = round(float(row[‘WFC Jumbo Int Rate’]) - float(row[‘Freddie Mac’]),3)
return rows

Yes we are. It seems the default entry class is string. I think instead of converting the default to float with float(), you can specify the class of each column when you initialize the table. That way if someone enters a string it doesn’t error out.

1 Like

I checked and I have ‘type’ : ‘numeric’ and one of my format options is precision = 3. Example:
{‘name’: [‘Interest Rate Type’,‘Freddie Mac’],
‘id’ : ‘Freddie Mac’,
‘type’ : ‘numeric’,
‘format’ : Format(
precision=3,
scheme=Scheme.fixed,
symbol=Symbol.yes,
symbol_suffix= ‘%’),
},

I still needed the round and float commands when doing the recalculation in the for loop.

I think that the type and the format information are just for the presentation within the data table.

Got any ideas?

PBK, is this when you initialize the datatable? I was able to initialize it like this:

 dash_table.DataTable(
        id='ex-table',
        columns = [{'name':i,'id':i,'type':'text'} if i in ['col1','col2'] else {'name':i,'id':i,'type':'numeric'} for i in ['col1','col2','col3']],
        data=[],
        editable=True,
        row_deletable=True,
        # style_as_list_view=True,
        style_header={
            # 'backgroundColor': '#fff',
            'font-family': 'system-ui',
            # 'color': 'black'
        },
        style_cell={
            'textAlign': 'center',
            'font-family': 'system-ui',
            # 'backgroundColor': '#fff',
            # 'color': 'black'
        }
    ),

and then the col 1 and 2 were still initialized as empty string but would only take numeric type as inputs. I no longer had to use float or int to convert it either.

1 Like

Sorry I’ve been away for a few days…

If you take a look at my last reply you’ll see that I declared the type to be numeric. a bigger chunk of the code is as follows:

columns = [
{‘name’: [’’, ‘Date’],
‘id’ : ‘Date’,
‘editable’ : False
},
{‘name’: [‘Interest Rate Type’,‘Freddie Mac’],
‘id’ : ‘Freddie Mac’,
‘type’ : ‘numeric’,
‘format’ : Format(
precision=3,
scheme=Scheme.fixed,
symbol=Symbol.yes,
symbol_suffix= ‘%’),

I declare the name, id, type, etc for each variable separately. This allows me to give each variable different formats, etc.

I’ll try your way and see what happens