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

[DataGrid] Fix checkbox selection issue #285

Merged
merged 2 commits into from
Sep 15, 2020
Merged

Conversation

dtassone
Copy link
Member

@dtassone dtassone commented Sep 14, 2020

Fix #283

@dtassone dtassone changed the title Fix #283 selection issue [DataGrid] Fix #283 selection issue Sep 14, 2020
@dtassone dtassone changed the title [DataGrid] Fix #283 selection issue [DataGrid] Fix #283 checkbox selection issue Sep 14, 2020
@oliviertassinari oliviertassinari added bug 🐛 Something doesn't work component: data grid This is the name of the generic UI component, not the React module! labels Sep 14, 2020
@oliviertassinari oliviertassinari changed the title [DataGrid] Fix #283 checkbox selection issue [DataGrid] Fix checkbox selection issue Sep 14, 2020
Copy link
Member

@oliviertassinari oliviertassinari left a 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.

Comment on lines 35 to 36
setChecked(isCurrentChecked);
setIndeterminate(isCurrentIndeterminate);
Copy link
Member

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

Copy link
Member

@eps1lon eps1lon Sep 15, 2020

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure?
Capture d’écran 2020-09-14 à 20 43 02

vs.

Capture d’écran 2020-09-14 à 20 42 56

(Google Ads)

Copy link
Member Author

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

Copy link
Member

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?

Copy link
Member

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.

Copy link
Member

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.

Copy link
Member

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);
Copy link
Member

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.

Copy link
Member Author

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

Copy link
Member

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?

Copy link
Member Author

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 }) => {
Copy link
Member

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?

Copy link
Member

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?

Copy link
Member Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: data grid This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[DataGrid] The intermediate state is lost when scrolling
3 participants