from __future__ import annotations from typing import Dict, List, Optional, cast from .. import globals # pylint: disable=redefined-builtin from ..element import Element from ..functions.javascript import run_javascript try: import pandas as pd globals.optional_features.add('pandas') except ImportError: pass class AgGrid(Element, component='aggrid.js', libraries=['lib/aggrid/ag-grid-community.min.js']): def __init__(self, options: Dict, *, html_columns: List[int] = [], theme: str = 'balham', auto_size_columns: bool = True, ) -> None: """AG Grid An element to create a grid using `AG Grid `_. The `call_api_method` method can be used to call an AG Grid API method. :param options: dictionary of AG Grid options :param html_columns: list of columns that should be rendered as HTML (default: `[]`) :param theme: AG Grid theme (default: 'balham') :param auto_size_columns: whether to automatically resize columns to fit the grid width (default: `True`) """ super().__init__() self._props['options'] = options self._props['html_columns'] = html_columns self._props['auto_size_columns'] = auto_size_columns self._classes = ['nicegui-aggrid', f'ag-theme-{theme}'] @staticmethod def from_pandas(df: pd.DataFrame, *, theme: str = 'balham', auto_size_columns: bool = True, options: Dict = {}) -> AgGrid: """Create an AG Grid from a Pandas DataFrame. :param df: Pandas DataFrame :param theme: AG Grid theme (default: 'balham') :param auto_size_columns: whether to automatically resize columns to fit the grid width (default: `True`) :param options: dictionary of additional AG Grid options :return: AG Grid element """ return AgGrid({ 'columnDefs': [{'field': col} for col in df.columns], 'rowData': df.to_dict('records'), 'suppressDotNotation': True, **options, }, theme=theme, auto_size_columns=auto_size_columns) @property def options(self) -> Dict: return self._props['options'] def update(self) -> None: super().update() self.run_method('update_grid') def call_api_method(self, name: str, *args) -> None: """Call an AG Grid API method. See `AG Grid API `_ for a list of methods. :param name: name of the method :param args: arguments to pass to the method """ self.run_method('call_api_method', name, *args) def call_column_api_method(self, name: str, *args) -> None: """Call an AG Grid Column API method. See `AG Grid Column API `_ for a list of methods. :param name: name of the method :param args: arguments to pass to the method """ self.run_method('call_column_api_method', name, *args) async def get_selected_rows(self) -> List[Dict]: """Get the currently selected rows. This method is especially useful when the grid is configured with ``rowSelection: 'multiple'``. See `AG Grid API `_ for more information. :return: list of selected row data """ result = await run_javascript(f'return getElement({self.id}).gridOptions.api.getSelectedRows();') return cast(List[Dict], result) async def get_selected_row(self) -> Optional[Dict]: """Get the single currently selected row. This method is especially useful when the grid is configured with ``rowSelection: 'single'``. :return: row data of the first selection if any row is selected, otherwise `None` """ rows = await self.get_selected_rows() return rows[0] if rows else None async def get_client_data(self) -> List[Dict]: """Get the data from the client including any edits made by the client. This method is especially useful when the grid is configured with ``'editable': True``. See `AG Grid API `_ for more information. Note that when editing a cell, the row data is not updated until the cell exits the edit mode. This does not happen when the cell loses focus, unless ``stopEditingWhenCellsLoseFocus: True`` is set. :return: list of row data """ result = await run_javascript(f''' const rowData = []; getElement({self.id}).gridOptions.api.forEachNode(node => rowData.push(node.data)); return rowData; ''') return cast(List[Dict], result) async def load_client_data(self) -> None: """Obtain client data and update the element's row data with it. This syncs edits made by the client in editable cells to the server. Note that when editing a cell, the row data is not updated until the cell exits the edit mode. This does not happen when the cell loses focus, unless ``stopEditingWhenCellsLoseFocus: True`` is set. """ client_row_data = await self.get_client_data() self.options['rowData'] = client_row_data self.update()