justpy
justpy copied to clipboard
How to use AgGrid API
https://www.ag-grid.com/javascript-grid-data-update-transactions/ hi i'm looking for a guide to use the grid API applyTransaction(transaction) to correctly update the data in my grid. i read your example :https://justpy.io/grids_tutorial/grid_api/ but in this example the functions: self.grid.run_api('selectAll()', msg.page) and self.grid.run_api('deselectAll()', msg.page) don't need any parameter. applyTransaction(transaction) instead need the transaction object, can you show me how to pass it correctly? thanks for the help
In order for applyTransaction to work, it looks like changes are required in the JavaScript part of the AgGrid component. You can still get the same results by changing the rowData in the grid options on the server side. Is that not a viable option for you?
it's not the same , look at the example: https://www.ag-grid.com/javascript-grid-data-update-transactions/ the add items button insert new data without losing the selection; changing the rowData directly will delete this information. The difference is explained here: https://www.ag-grid.com/javascript-grid-data-update/#setting-fresh-row-data
I see. I will add support for this in a future version.
I too would love this feature. I would like to refresh ag-grid cell values as new (streaming) values arrive. Updating row data redraws the entire table, which leads to a number of undesirable side effects. I have found this easy using Quasar, but it seems impossible using ag-grid as applyTransaction (and similar api methods) are not supported.
Below is an example of how I've been interacting with Ag-grid API, particularly with applyTransaction. Using this approach, I've been able to use most (if not all) of the API methods
import justpy as jp
grid_options = {
'defaultColDef': {
'filter': True,
},
'columnDefs': [
{'headerName': "Make", 'field': "make"},
{'headerName': "Model", 'field': "model"},
{'headerName': "Price", 'field': "price"}
],
'rowData': [
{'make': "Toyota", 'model': "Celica", 'price': 35000},
{'make': "Ford", 'model': "Mondeo", 'price': 32000},
{'make': "Porsche", 'model': "Boxter", 'price': 72000}
],
}
async def new_row(self, msg):
wp = msg.page
new_row = {"make": "Chevy", "model": "Corevette", "price": 42100}
await wp.run_javascript(f"""cached_grid_def['g' + {wp.grid.id}].api.applyTransaction({{ add: [{new_row}] }})""")
def grid_test():
wp = jp.QuasarPage()
jp.QBtn(a=wp, icon='fas fa-plus-square', color="light-green-14", click=new_row)
wp.grid = jp.AgGrid(a=wp, options=grid_options)
return wp
jp.justpy(grid_test)
Thank you for posting this!
Based on your solution I added a new method to the AgGrid class that will be available in the upcoming version. The new_row
event handler would then look like this:
async def new_row(self, msg):
wp = msg.page
new_row = {"make": "Chevy", "model": "Corevette", "price": 42100}
transaction = {'add': [new_row]}
# await wp.run_javascript(f"""cached_grid_def['g' + {wp.grid.id}].api.applyTransaction({{ add: [{new_row}] }})""")
await wp.grid.apply_transaction(transaction, wp)
If you are doing more things like this, let me know and I will add them as methods to AgGrid.
I need update functionality. This is slightly more complex as it requires a row node object. I will give a shot at adapting the method suggested by @rroyer-xyz and will post any working code.
The challenge is that grid options will require a function to be defined for getting the row node id as in the below example. @elimintz and others, any suggestions?
const gridOptions = {
getRowNodeId: (data) => data.id,
// other grid options ...
}
A few notes, questions, and suggestions:
ag-grid version
In case anyone is attempting to test out the above code before a new release, I needed to update ag-grid to a newer version as applyTransaction does not exist in ag-grid 23.0.2
. I updated the local copy to ag-grid 25.3.0
with no problems.
Minor code improvement in run_javascript(...)
usage
@elimintz: A minor improvement to improve efficiency by better utilizing Python:
Take this line of code from the above example:
await wp.run_javascript(f"""cached_grid_def['g' + {wp.grid.id}].api.applyTransaction({{ add: [{new_row}] }})""")
This code can be improved thus:
await wp.run_javascript(f"""cached_grid_def['g{wp.grid.id}'].api.applyTransaction({{ add: [{new_row}] }})""")
Same processing time on the server and it saves computation time on the client side. I am happy to submit a PR changing all similar instances in the code base, however it appears you are not keeping development code in GitHub and this would need to happen on the current code base.
Below is an example using update functionality and getRowNodeId. The line "wp.grid.evaluate" is needed to set the row id
import justpy as jp
grid_options = {
'defaultColDef': {
'filter': True,
},
'columnDefs': [
{'headerName': "Make", 'field': "make"},
{'headerName': "Model", 'field': "model"},
{'headerName': "Price", 'field': "price"}
],
'getRowNodeId': '''function (data) {
return data.id;
}''',
'rowData': [
{'id': 1, 'make': "Toyota", 'model': "Celica", 'price': 35000},
{'id': 2, 'make': "Ford", 'model': "Mondeo", 'price': 32000},
{'id': 3, 'make': "Porsche", 'model': "Boxter", 'price': 72000}
],
}
async def update_row(self, msg):
wp = msg.page
update_rows = [{'id': 1, 'make': "Toyota", 'model': "Celica", 'price': 999},
{'id': 2, 'make': "Ford", 'model': "Mondeo", 'price': 888}]
await wp.run_javascript(f"""cached_grid_def['g' + {wp.grid.id}].api.applyTransaction({{ update: {update_rows} }})""")
def grid_test():
wp = jp.QuasarPage()
jp.QBtn(a=wp, icon='fas fa-plus-square', color="light-green-14", click=update_row)
wp.grid = jp.AgGrid(a=wp, options=grid_options)
wp.grid.evaluate = ['getRowNodeId']
return wp
jp.justpy(grid_test)
Thanks again. This looks like it solves the issue of working with node ids. @othalan does this solve your problem?
Thank you @rroyer-xyz. As it happens, mere seconds before your update I came to the same solution.
@elimintz, yes this does solve my problem. It took me awhile to find wp.grid.evaluate
.
(NOTE: I posted this comment before, but realized I needed a few changes. So deleted the old comment and added a new version....)
However, as an implementation detail I wonder if there is a better way to provide access to API methods. The proposed new_row
method is a very narrow use of the highly flexible ag-grid applyTransaction
function.
In a perfect world, it would be nice to have the ag-grid api function calls mirrored in the python api. Perhaps there is a method to automate this via inspection of the javascript code?
Alternatively, rather than providing narrow use case methods such as new_row
, perhaps more extensive documentation around using api calls would be sufficient.
Or another alternative, perhaps a more flexible run_api
call would be sufficient. Such as this:
async def run_api(self, page, command, args=None):
await page.run_javascript(f"cached_grid_def.g{self.id}.api.{command}({','.join([str(x) for x in args or []])})")
Example usage:
await self.run_api(wp, "applyTransaction", {"update": updated_rows_list, "add": new_row_list})
I would need to examine the ag-grid api in more detail to determine if the above is sufficient, but at a quick glance I think it would cover most use cases.
Please see https://github.com/elimintz/justpy/issues/158#issuecomment-875674681 above. I added the apply_transaction method to my development version and it will be part of the upcoming version.
Please see #158 (comment) above. I added the apply_transaction method to my development version and it will be part of the upcoming version.
My apologies, I wasn't thinking straight looking at that comment! I still wonder if API calls in general could be helped about by a bit of more flexible code.
No need to apologize. Would be happy to improve the api interface. If you think of something, let me know.
I will feed back my ideas as I continue development on my project.