Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabled programmatic edits to grid and additional configuration options for columns and rows #191

Closed

Conversation

vardaofthevalier
Copy link

Hello! First of all I just want to say thanks for this great widget. I took it upon myself to add a few features that I thought would be useful for a few particular use cases for a project that I'm currently working on at my job, and was hoping to get some feedback on them and possibly contribute the changes back if they might useful to other qgrid users.

The rationale behind many of these features can be described in terms of two different needs: 1) the ability to programmatically update values in the grid while also avoiding completely resetting the entire dataframe (which causes some flickering of the UI when it is redrawn); and 2) conditionally and dynamically setting which parts of the grid can be edited at a given time. Below is a summary of the added functionality:

  • Implemented a "toggle_editable" message type that can be sent to the widget front end to enable/disable edits to the entire grid dynamically
  • Implemented two internal update methods, set_value_internally() and add_row_internally(), which are intended for programmatically setting the value of a cell and programmatically adding a row, respectively. The add_row_internally() method can add rows to a dataframe with an arbitrary index type (i.e., not limited to integer-only indexes)
  • Added a grid option for conditionally bolding the index values
  • Added column-specific options (editable, toolTip) which are specified using a dictionary of (column name, column options dictionary) pairs
  • Implemented dynamic conditional editing of a row based on the content of the row in question

Below are some examples demonstrating how to use these features:

from qgrid import show_grid
import pandas as pd
from IPython.display import display

# row edit conditions grammar:
# ROW EDIT CONDITIONS => dict([ROW EDIT CONDITION])
# ROW EDIT CONDITION => (BOOLEAN OPERATOR, dict([(COLUMN NAME, COLUMN VALUE)]))
# BOOLEAN OPERATOR => AND | OR | NAND | NOR
# COLUMN NAME => <string>  
# COLUMN VALUE => <column dtype>
row_edit_conditions = {  # This set of conditions will cause any row where foo == 'hello' and bar == 'world' to have editing disabled
    'NAND': {
        'foo': 'hello',
        'bar': 'world'
    }
}

column_defs = {
    'foo': {
        'editable': True,
        'toolTip': "Editable"
    },
    'bar': {
        'editable': False,
        'toolTip': "Not editable"
    }
}

grid_options = {
    'boldIndex': False
}

df = pd.DataFrame({'foo': ['boo'], 'bar': ['world'], 'baz': [42], 'boo': [57]})
df.set_index('baz', inplace=True, drop=True)

q = show_grid(df, grid_options=grid_options, column_definitions=column_defs, row_edit_conditions=row_edit_conditions)
display(q)

# Verify that:
# - Tooltips for columns foo and bar are visible
# - Index column (baz) values are not bolded
# - Column bar is not editable
# - Column foo is editable
# - Row (index 42) is only editable until the value of foo is set to 'hello'

# A note on precedence of edit controls:
# - Toggle editable won't have an effect on columns or rows that have already had edits disabled via the column definitions or row edit conditions
# - Toggle editable also won't impact the ability to use the internal update methods (add_row_internally(), set_value_internally()) and only applies to manual edits

# Toggle editable -- running this once will disable edits to the grid, and running it again should reenable edits to the grid
q.send({'type': 'toggle_editable'})

# Add row internally
new_row = [
    ('baz', 43),
    ('bar', "new bar"),
    ('boo', 58), 
    ('foo', "new foo")
]
q.add_row_internally(new_row)

# Set value internally
q.set_value_internally(42, 'foo', 'hello')

This will be my first PR against an existing open-source project that I didn't create from scratch on my own, so please let me know if there are any glaring issues that need to be fixed before merging. I'm very interested in any feedback you may have and would be happy to make tweaks or to discuss improvements. Also, I have included unit tests for the internal update methods described above, but am a little stumped on how to write tests for the front-end parts that can only be observed through interaction. If anyone has any suggestions I will happily write more tests to cover those things as well.

Thanks for reading!

@vardaofthevalier vardaofthevalier changed the title Enabled programmatic edits to grid and additional configuration options for columns Enabled programmatic edits to grid and additional configuration options for columns and rows May 7, 2018
@TimShawver
Copy link
Contributor

This sounds amazing, thanks. I'm going to start looking at this today.

I'm spending some time this week figuring out the scope for the next release and I'm hoping we'll be able to include some or all of these new features.

@TimShawver
Copy link
Contributor

Sorry about the delay...I've been looking at this and it mostly looks great but I have an idea for making the row_edit_conditions functionality more flexible/powerful while also reducing amount of code and documentation that we have to maintain in this repository.

In a nutshell the idea is to pass in a callback function which gets called with the contents of the row and returns true or false to indicate whether the rows should be editable or not.

I've started working on this on a branch off of your branch, to confirm that it will work, and also because there are a few things I'd like to add now that we have more configuration infrastructure in place (thanks to your PR!).

Could you take a look at the changes I've made in the following PR and let me know if you think this strategy will work for you purposes? #195

Most of the changes are in this commit: 53bd229

I think if it looks good I'll just merge that PR...your name will still show up in the commits and all so I think it should be the same either way, but let me know if there's some benefit to updating this PR instead.

@vardaofthevalier
Copy link
Author

No problem at all! I reviewed #195 and I think things look pretty good to me, and I'm fine with the changes being made through #195 rather than #191. Let me know if you need me to take a look at anything else specifically, otherwise I'll give you the green light. Thanks!

@TimShawver
Copy link
Contributor

@vardaofthevalier sounds good, thanks again for your help. I'll let you know when everything is merged/released. Last thing I'm working on is adding support for some additional column options now that we have a mechanism in place for setting them.

To say thanks we'd like to give you a Qgrid t-shirt. We have unisex t-shirts in size S, M, and XL (we're out of L). If you email your preferred size and mailing address to [email protected] we'll send one out to you. If you could use your work email when you email that would be best because then I can easily verify that it's not someone that's trying to steal your t-shirt.

@vardaofthevalier
Copy link
Author

Oh cool, that's very nice of you! And you're welcome, it was my pleasure. I just sent you an email (from the Microsoft domain) with the requested information. Thanks again, and I'm looking forward to the next release!

@TimShawver
Copy link
Contributor

Closing this since it's been merged in this other PR: #195

@TimShawver TimShawver closed this Jul 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants