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()