Py.Cafe

wyvnthewolf/

solara-car-data-grid

Interactive Car Data Grid

DocsPricing
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

from typing import cast
import solara
import solara.lab
from ipyaggrid import Grid
import pandas as pd
from reacton.core import ValueElement
import reacton


aggrid_css: str = """
.ag-header-cell {
  background-color: #1c87c9;
  color: #FFF;
}

.ag-theme-balham {
    --ag-odd-row-background-color: #C6E6FB;
    --ag-value-change-value-highlight-background-color: lightgreen;
    --ag-row-hover-color: deepskyblue;
    font-family: 'Open Sans', sans-serif;
    font-size: 13px;
}

.ag-theme-balham-dark {
    font-family: 'Open Sans', sans-serif;
    font-size: 13px;
}
"""

default_col_def = {
    'sortable': True,
    'resizable': True,
    'minWidth': 100,
    'filter': 'agSetColumnFilter',
    'editable': True,
    'filterParams': {
        'excelMode': 'windows'
    }
}

default_grid_options = {
    'animateRows': True,
    'rowDragManaged': True,
    'enableRangeSelection': True,
    'rowSelection': True,
    'defaultColDef': default_col_def
}



class SolaraAgGrid(Grid):
    def __init__(self, *args, **kwargs):
        height = None
        if 'height' in kwargs:
            height = kwargs.pop('height')
        if 'grid_data_out' in kwargs:
            kwargs.pop('grid_data_out')
        if 'css_rules' not in kwargs:
            kwargs['css_rules'] = aggrid_css
        super().__init__(*args, **kwargs)
        self.height = f'{height}' if height is not None else '500px'

def AgGrid(dark_mode, **kwargs) -> ValueElement[Grid, dict]:
    theme = 'ag-theme-balham' if not dark_mode else 'ag-theme-balham-dark'
    kwargs['theme'] = theme
    df = kwargs['grid_data']
    grid_options = kwargs['grid_options']


    def update_df():
        widget = cast(SolaraAgGrid, solara.get_widget(el))
        if widget is not None:
            widget.grid_options = grid_options
            # without this, the height would go back to default
            if 'height' in kwargs:
                widget.height_in = int(kwargs['height'].split('px')[0])
            widget.update_grid_data(df)  # this also updates the grid_options

    # when df changes, grid_data will be updated, however, ...
    # grid_data and grid_options are not traits, so letting them update by reacton/solara has no effect
    # instead, we need to get a reference to the widget and call .update_grid_data in a use_effect
    solara.use_effect(effect=update_df, dependencies=[df, grid_options])

    comp = reacton.core.ComponentWidget(widget=SolaraAgGrid)
    el = ValueElement(value_property="grid_data_out", component=comp, kwargs=kwargs).key(f'theme-{theme}')
    return el


@solara.component
def Page():
    edit_dict = solara.Reactive(dict())
    data = [
        {"make": "Toyota", "model": "Celica", "price": 35000},
        {"make": "Ford", "model": "Mondeo", "price": 32000},
        {"make": "Porsche", "model": "Boxster", "price": 72000}
    ]
    column_defs = [
                    {"headerName": "Make", "field": "make", "sortable": True},
                    {"headerName": "Model", "field": "model"},
                    {"headerName": "Price", "field": "price"}
                 ]
    grid_options = default_grid_options.copy()
    grid_options['columnDefs'] = column_defs
    
    df, df_set = solara.use_state(pd.DataFrame.from_dict(data))
    with solara.AppBar():
        solara.lab.ThemeToggle()
    
    with solara.Card('Cars'):
        edittable_grid = AgGrid(
            grid_data=df,
            grid_options=grid_options,
            columns_fit = 'size_to_fit',
            dark_mode = solara.lab.use_dark_effective(),
            sync_on_edit = True,
            export_mode = 'auto',
            export_to_df = True,
            sync_grid = True,
        )
        edittable_grid.connect(edit_dict)

    if 'grid' in edit_dict.value:
        print(edit_dict.value)
        with solara.Card('Results'):
            solara.DataFrame(edit_dict.value['grid'])