-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[DataGrid] Fix checkbox selection issue #285
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have tried to think at how we could test this fix. I can't think of a simple answer. Maybe it's one of these rare cases where we can ignore it.
setChecked(isCurrentChecked); | ||
setIndeterminate(isCurrentIndeterminate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why have the logic in an effect? Would it be simpler to pull the value from the state at render time, with the context?
How will we handle the controllable API? #246: https://next.material-ui.com/components/data-grid/selection/#controlled-selection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All these derived states should be computable at render time which the naming of the methods indicated. E.g. get*
implies to me that there are no side-effects which means it's safe to call at render time. Then getDerivedStateFromProps
would apply which has a documented pattern for hooks: https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops
@@ -17,7 +17,7 @@ export const HeaderCheckbox: React.FC<ColParams> = React.memo(({ api }) => { | |||
const isAllSelected = | |||
api.getAllRowIds().length === event.rows.length && event.rows.length > 0; | |||
const hasNoneSelected = event.rows.length === 0; | |||
setChecked(isAllSelected || !hasNoneSelected); | |||
setChecked(isAllSelected && !hasNoneSelected); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me, checked is when all checkbox are checked and none are unchecked
But up to you, I can change it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes me think of mui/material-ui#20476. No strong preferences. It could simply surface that the intermediate state should always have the same visual look no matter the checked state. At least it's what bootstrap and ant design do.
@eps1lon any tips on the matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the question here? If this is about color then the mixed state should have the same color as the checked state. At least that's how our Checkbox behaves so if it behaves different here then there should be a rationale that doesn't apply to the general purpose use case.
Also note that the color doesn't really matter anyway because of SC 1.4.1 in WCAG 2.x. If there's a difference between checked+indeterminate and checked+determinate then it needs to be encoded in something other than color as well. Though ARIA does not support both of these states but rather a single "mixed"
state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK awesome. I think that it perfectly answer the question, when indeterminate
is set:
- It doesn't matter if checked is true or false, it's in a mixed state.
- The color shouldn't change based on the checked state, if it does, it could incentive people to break 1.4.1 in in WCAG 2.1.
So as the next step, I propose:
- On the main repository side, we update the CSS so indeterminate unchecked has the primary color.
- Here, we keep the previous logic as the fix will land on v5 and the grid depends on v4, we need the primary color.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the main repository side, we update the CSS so indeterminate unchecked has the primary color.
@dtassone Do you want to use this issue as an opportunity to make your first contribution to the core? :)
const isCurrentChecked = selectedRows.length === allRowsCount || isCurrentIndeterminate; | ||
|
||
const [isChecked, setChecked] = React.useState(isCurrentChecked); | ||
const [isIndeterminate, setIndeterminate] = React.useState(isCurrentIndeterminate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does api
not change if we select a different row? Seems very brittle to have individual components duplicate the logic of which row is considered checked and which isn't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just the header checkbox
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It always starts out with "just this small component". If we have the choice between robust and brittle we might as well use robust. I guess api
is not changing if the underlying data changes? How are "subscribers" usually notified when the data changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No Api is not changing. They can use an event handler to get latest data.
export const HeaderCheckbox: React.FC<ColParams> = React.memo(({ api }) => { | ||
const [isChecked, setChecked] = React.useState(false); | ||
const [isIndeterminate, setIndeterminate] = React.useState(false); | ||
export const HeaderCheckbox: React.FC<ColParams> = ({ api }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do no longer need the memo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to pull the api from the context here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just an implementation of the col prop renderHeader.
So we pass api as a prop so it's easier for the user.
Yes users could use the context as well.
Fix #283