diff --git a/packages/grid/_modules_/grid/components/toolbar/GridToolbarExport.tsx b/packages/grid/_modules_/grid/components/toolbar/GridToolbarExport.tsx index b8029d608198..d42eae3078bb 100644 --- a/packages/grid/_modules_/grid/components/toolbar/GridToolbarExport.tsx +++ b/packages/grid/_modules_/grid/components/toolbar/GridToolbarExport.tsx @@ -7,28 +7,44 @@ import MenuItem from '@material-ui/core/MenuItem'; import { isHideMenuKey, isTabKey } from '../../utils/keyboardUtils'; import { GridApiContext } from '../GridApiContext'; import { GridMenu } from '../menu/GridMenu'; -import { GridExportOption } from '../../models'; +import { GridExportCsvOptions } from '../../models/gridExport'; -export const GridToolbarExport = React.forwardRef( +interface GridExportFormatCsv { + format: 'csv'; + formatOptions?: GridExportCsvOptions; +} + +type GridExportFormatOption = GridExportFormatCsv; + +type GridExportOption = GridExportFormatOption & { + label: React.ReactNode; +}; + +export interface GridToolbarExportProps extends ButtonProps { + csvOptions?: GridExportCsvOptions; +} + +export const GridToolbarExport = React.forwardRef( function GridToolbarExport(props, ref) { + const { csvOptions, ...other } = props; const apiRef = React.useContext(GridApiContext); - const exportButtonId = useId(); - const exportMenuId = useId(); + const buttonId = useId(); + const menuId = useId(); const [anchorEl, setAnchorEl] = React.useState(null); const ExportIcon = apiRef!.current.components!.ExportIcon!; - const ExportOptions: Array = [ - { - label: apiRef!.current.getLocaleText('toolbarExportCSV'), - format: 'csv', - }, - ]; + const exportOptions: Array = []; + exportOptions.push({ + label: apiRef!.current.getLocaleText('toolbarExportCSV'), + format: 'csv', + formatOptions: csvOptions, + }); - const handleExportSelectorOpen = (event) => setAnchorEl(event.currentTarget); - const handleExportSelectorClose = () => setAnchorEl(null); - const handleExport = (format) => { - if (format === 'csv') { - apiRef!.current.exportDataAsCsv(); + const handleMenuOpen = (event) => setAnchorEl(event.currentTarget); + const handleMenuClose = () => setAnchorEl(null); + const handleExport = (option: GridExportOption) => () => { + if (option.format === 'csv') { + apiRef!.current.exportDataAsCsv(option.formatOptions); } setAnchorEl(null); @@ -39,16 +55,10 @@ export const GridToolbarExport = React.forwardRef = ExportOptions.map((option, index) => ( - handleExport(option.format)}> - {option.label} - - )); - return ( - {renderExportOptions} + {exportOptions.map((option, index) => ( + + {option.label} + + ))} diff --git a/packages/grid/_modules_/grid/hooks/features/export/useGridCsvExport.tsx b/packages/grid/_modules_/grid/hooks/features/export/useGridCsvExport.tsx index a788eaafa7e9..560ac4fa9eb0 100644 --- a/packages/grid/_modules_/grid/hooks/features/export/useGridCsvExport.tsx +++ b/packages/grid/_modules_/grid/hooks/features/export/useGridCsvExport.tsx @@ -5,7 +5,8 @@ import { useGridSelector } from '../core/useGridSelector'; import { visibleGridColumnsSelector } from '../columns'; import { visibleSortedGridRowsSelector } from '../filter'; import { gridSelectionStateSelector } from '../selection'; -import { GridCsvExportApi } from '../../../models'; +import { GridCsvExportApi } from '../../../models/api/gridCsvExportApi'; +import { GridExportCsvOptions } from '../../../models/gridExport'; import { useLogger } from '../../utils/useLogger'; import { exportAs } from '../../../utils'; import { buildCSV } from './seralizers/csvSeraliser'; @@ -16,19 +17,30 @@ export const useGridCsvExport = (apiRef: GridApiRef): void => { const visibleSortedRows = useGridSelector(apiRef, visibleSortedGridRowsSelector); const selection = useGridSelector(apiRef, gridSelectionStateSelector); - const getDataAsCsv = React.useCallback((): string => { - logger.debug(`Get data as CSV`); + const getDataAsCsv = React.useCallback( + // TODO remove once we use the options + // eslint-disable-next-line @typescript-eslint/no-unused-vars + (options?: GridExportCsvOptions): string => { + logger.debug(`Get data as CSV`); - return buildCSV(visibleColumns, visibleSortedRows, selection, apiRef.current.getCellValue); - }, [logger, visibleColumns, visibleSortedRows, selection, apiRef]); + return buildCSV(visibleColumns, visibleSortedRows, selection, apiRef.current.getCellValue); + }, + [logger, visibleColumns, visibleSortedRows, selection, apiRef], + ); - const exportDataAsCsv = React.useCallback((): void => { - logger.debug(`Export data as CSV`); - const csv = getDataAsCsv(); - const blob = new Blob([csv], { type: 'text/csv' }); + const exportDataAsCsv = React.useCallback( + (options?: GridExportCsvOptions): void => { + logger.debug(`Export data as CSV`); + const csv = getDataAsCsv(options); - exportAs(blob, 'csv', 'data'); - }, [logger, getDataAsCsv]); + const blob = new Blob([options?.utf8WithBom ? new Uint8Array([0xef, 0xbb, 0xbf]) : '', csv], { + type: 'text/csv', + }); + + exportAs(blob, 'csv', options?.fileName); + }, + [logger, getDataAsCsv], + ); const csvExportApi: GridCsvExportApi = { getDataAsCsv, diff --git a/packages/grid/_modules_/grid/models/api/gridCsvExportApi.ts b/packages/grid/_modules_/grid/models/api/gridCsvExportApi.ts index e3fe81214025..7a4b7e949e50 100644 --- a/packages/grid/_modules_/grid/models/api/gridCsvExportApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridCsvExportApi.ts @@ -1,14 +1,19 @@ +import { GridExportCsvOptions } from '../gridExport'; + /** - * The csv export API interface that is available in the grid [[apiRef]]. + * The CSV export API interface that is available in the grid [[apiRef]]. */ export interface GridCsvExportApi { /** - * Returns the grid data formatted as CSV. - * @returns {string} The data as CSV. + * Returns the grid data as a CSV string. + * This method is used internally by `exportDataAsCsv`. + * @param {GridExportCsvOptions} options The options to apply on the export. + * @returns string */ - getDataAsCsv: () => string; + getDataAsCsv: (options?: GridExportCsvOptions) => string; /** - * Exports the grid data as CSV and sends it to the user. + * Downloads and exports a CSV of the grid's data. + * @param {GridExportCsvOptions} options The options to apply on the export. */ - exportDataAsCsv: () => void; + exportDataAsCsv: (options?: GridExportCsvOptions) => void; } diff --git a/packages/grid/_modules_/grid/models/gridExport.ts b/packages/grid/_modules_/grid/models/gridExport.ts index cd8e73764dac..eeb97c272a99 100644 --- a/packages/grid/_modules_/grid/models/gridExport.ts +++ b/packages/grid/_modules_/grid/models/gridExport.ts @@ -1,12 +1,12 @@ /** - * Available export formats. To be extended in future. + * The options to apply on the CSV export. */ -export type GridExportFormat = 'csv'; +export interface GridExportCsvOptions { + fileName?: string; + utf8WithBom?: boolean; +} /** - * Export option interface + * Available export formats. */ -export interface GridExportOption { - label: React.ReactNode; - format: GridExportFormat; -} +export type GridExportFormat = 'csv';