-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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] Make GridPreferencesPanel private #1855
Comments
FYI: I was able to use the built in
import * as xgrid from '@material-ui/data-grid';
declare module '@material-ui/data-grid' {
declare enum GridPreferencePanelsValue {
customPrefrences = 'customPrefrences',
}
}
import * as React from 'react';
export function CustomPreferencesComponent() {
return ...;
}
import * as React from 'react';
import {
allGridColumnsSelector,
GridApiContext,
gridPreferencePanelStateSelector,
GridPreferencePanelsValue,
GridPreferencesPanel,
useGridSelector,
} from '@material-ui/data-grid';
import CustomPreferencesComponent from './CustomPreferencesComponent';
export const CustomPreferencesPanel = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(function CustomPreferencesPanel(props, ref) {
const apiRef = React.useContext(GridApiContext);
const columns = useGridSelector(apiRef, allGridColumnsSelector);
const preferencePanelState = useGridSelector(apiRef, gridPreferencePanelStateSelector);
const isCustomPreferencesPanelOpen =
preferencePanelState.openedPanelValue === GridPreferencePanelsValue.customPreferences;
const Panel = apiRef!.current.components.Panel!;
return isCustomPreferencesPanelOpen ? (
<Panel
ref={ref}
open={columns.length > 0 && preferencePanelState.open}
{...apiRef?.current.componentsProps?.panel}
{...props}
>
{isCustomPreferencesPanelOpen && (
<CustomPreferencesComponent
{...apiRef?.current.componentsProps?.preferencesPanel?.customComponent}
/>
)}
</Panel>
) : (
<GridPreferencesPanel ref={ref} {...props} />
);
});
import * as React from 'react';
import { Button } from '@material-ui/core';
import {
GridApiContext,
GridPreferencePanelsValue,
gridPreferencePanelStateSelector,
useGridSelector,
} from '@material-ui/data-grid';
export const CustomPreferencesButton = React.forwardRef<
HTMLButtonElement,
React.HTMLAttributes<HTMLButtonElement>
>(function CustomPreferencesButton(props, ref) {
const apiRef = React.useContext(GridApiContext);
const { open, openedPanelValue } = useGridSelector(apiRef, gridPreferencePanelStateSelector);
const togglePreferences = () => {
if (open && openedPanelValue === GridPreferencePanelsValue.customPreferences) {
apiRef!.current.hidePreferences();
} else {
apiRef!.current.showPreferences(GridPreferencePanelsValue.customPreferences);
}
};
return (
<Button
variant="text"
ref={ref}
color="primary"
size="small"
onClick={togglePreferences}
>
Custom Preferences
</Button>
);
});
import * as React from 'react';
import {
GridToolbarColumnsButton,
GridToolbarFilterButton,
GridToolbarContainer,
GridToolbarDensitySelector,
GridToolbarExport,
} from '@material-ui/data-grid';
import CustomPreferencesComponent from './CustomPreferencesComponent';
export function CustomToolbar() {
return (
<GridToolbarContainer>
<GridToolbarColumnsButton />
<GridToolbarFilterButton />
<GridToolbarDensitySelector />
<GridToolbarExport />
<CustomPreferencesComponent />
</GridToolbarContainer>
);
}
<DataGrid
...
components={{
Toolbar: CustomToolbar,
PreferencesPanel: CustomPreferencesPanel,
}}
/> Although the above shown solution works, I think it smells a bit, since I would have to rely on some How do you think about the proposed change of the |
Thanks for raising this issue, I have also noticed issues with the current implementation of the preferencePanel. I think we should get rid of it as a component. We should keep a panel state to control which panel are currently displayed but we should dissociate the filter panel and column selector of the preference panel, to be able to control how to render those separately. Also it would allow to render more component and panels. Demo on how to render the column selector outside the grid. |
@sebastianfrey Could you describe the concrete problem you are trying to solve?
Do you have a visual illustration? What would be wrong with rendering your own pop-up or us allowing to extend the column selector panel and the filter selector panel specifically, making So far, the description of the GitHub issue seems to focus too much on "what" we should do, but not enough on "why". I mean, I think that we should focus first on what is the problem, second on what are the options we have to solve the problem, and last why a specific one is superior to the others solutions/options. |
@oliviertassinari I am building a custom toolbar button, which opens a panel where users can kick off backend workflows for further data processing. I thought it would be nice to have the ability to use the built-in The suggestion of @dtassone to have the ability as a developer to control how and especially where the filter panel or the column panel should be rendered, would make the requirement to use the built-in |
@sebastianfrey OK, thanks for the extra details. I think that it makes sense to make it easy to display custom panels. For the next step on this issue. I would propose we
The current position of the grid preference is KO (IMHO). I think that we should rework it to be as close as possible to the button that triggers it (either close to the column menu or the toolbar button). The fewer end-users have to move the cursor, the better the UX. |
At the end of the discussion, there still seems to be no apparent reason to make the GridPreferencesPanel private. |
@zivgit I think that the reason is that there is nothing to customize with the This is the source:
I see no use cases for using:
that can't be done by using |
While making In addition to the export function GridDefaultPanelContent({
panelValue,
}: {
panelValue?: GridPreferencePanelsValue;
}) {
const rootProps = useGridRootProps();
if (panelValue === GridPreferencePanelsValue.columns) {
return <rootProps.slots.columnsPanel {...rootProps.slotProps?.columnsPanel} />;
}
if (panelValue === GridPreferencePanelsValue.filters) {
return <rootProps.slots.filterPanel {...rootProps.slotProps?.filterPanel} />;
}
return null;
}
Then, users will be able to override the slot, like this: function CustomPanelContent({ panelValue }) {
if (panelValue === 'custom') {
return <div>Custom panel content</div>;
}
return <GridDefaultPanelContent panelValue={panelValue} />;
}
<DataGrid slots={{ panelContent: CustomPanelContent }} /> Finally, opening the custom panel content can be done using <Button onClick={() => apiRef.current.showPreferences('custom')}>
Open custom panel
</Button> This will work in JS runtime, for TS we will need to allow extending |
@cherniavskii to create a separate issue with a proposal for adding custom panels. We estimated the complexity as 3. |
@cherniavskii Regarding your concerns about extending When someone wants to extend export * from '@mui/x-data-grid-pro';
declare module '@mui/x-data-grid-pro' {
export enum GridPreferencePanelsValue {
custom = 'custom',
}
} The declaration file than must be referenced in |
@cherniavskii Unfortunately I have to correct my statement here: I did check again the source code of the project where I used the above approach. It seems that the approach worked well with previous version of typescript, with an up to date typescript version, you will get proper typing, but at runtime the enum is still the original one. Which means someone would have to monkey patch the import { GridPreferencesPanelValue } from '@mui/x-data-grid-pro';
(GridPreferencesPanelValue as any).custom = 'custom'; Also accessing the custom enum type is a bit annoying. As I have said, you will get proper typing, but when you try to compare enum values like the following const { openedPanelValue } = useGridSelector(apiRef, gridPreferencePanelStateSelector);
const isCustom = openedPanelValue === GridPreferencesPanelValue.custom; typescript starts complaining
To workaround you would have to use again an ugly const { openedPanelValue } = useGridSelector(apiRef, gridPreferencePanelStateSelector);
const isCustom = openedPanelValue === (GridPreferencesPanelValue as any).custom; |
@sebastianfrey thanks for your input! |
Summary 💡
It seems, that the current
GridPreferencesPanel
implementation hard coded the rendering of theColumnSelectorComponent
and theFilterPanelComponent
. This makes it impossible for a developer to leverage the built-inGridPreferencesPanel
to render additional actions along side the default grid preferences (ColumnSelectorComponent
andFilterPanelComponent
) without providing a customGridPreferencesPanel
implementation. Therefore it would be nice when a developer would be able to inject custom components for rendering in the defaultGridPreferncesPanel
.Examples 🌈
When the
GridApi#showPreferences()
method would accept a component instead of the current string constant, this feature would be fairly easy to support.Motivation 🔦
Allow developers to leverage the built-in
GridPreferencesPanel
implementation to inject custom components.Order id 💳
22075
The text was updated successfully, but these errors were encountered: