diff --git a/apps/demos/Demos/CardView/ColumnChooser/React/App.tsx b/apps/demos/Demos/CardView/ColumnChooser/React/App.tsx index b0712bffc0b7..6b121d99172b 100644 --- a/apps/demos/Demos/CardView/ColumnChooser/React/App.tsx +++ b/apps/demos/Demos/CardView/ColumnChooser/React/App.tsx @@ -86,7 +86,7 @@ const App = () => { keyExpr="ID" cardsPerRow="auto" cardMinWidth={300} - allowColumnReordering={allowColumnReordering} + allowColumnReordering={!!allowColumnReordering} > { height="340px" > { keyExpr="ID" cardsPerRow="auto" cardMinWidth={300} - allowColumnReordering={allowColumnReordering} + allowColumnReordering={!!allowColumnReordering} > { mode={columnChooserMode} height="340px" > - + { { diff --git a/apps/demos/Demos/DataGrid/AIColumns/React/Category.tsx b/apps/demos/Demos/DataGrid/AIColumns/React/Category.tsx index c14abb877b09..9a5ff7dedc01 100644 --- a/apps/demos/Demos/DataGrid/AIColumns/React/Category.tsx +++ b/apps/demos/Demos/DataGrid/AIColumns/React/Category.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { type Vehicle } from './types'; -import { type DataGridTypes } from 'devextreme-react/data-grid'; +import type { DataGridTypes } from 'devextreme-react/data-grid'; export default function Category(props: DataGridTypes.ColumnCellTemplateData) { - return
{props.data.CategoryName}
; + return
{props.data?.CategoryName}
; } diff --git a/apps/demos/Demos/DataGrid/AIColumns/React/service.ts b/apps/demos/Demos/DataGrid/AIColumns/React/service.ts index d0abbf6ef21d..21c6cb973993 100644 --- a/apps/demos/Demos/DataGrid/AIColumns/React/service.ts +++ b/apps/demos/Demos/DataGrid/AIColumns/React/service.ts @@ -25,10 +25,10 @@ async function getAIResponse(messages: AIMessage[], signal: AbortSignal) { const response = await aiService.chat.completions.create(params, { signal }); const result = response.choices[0].message?.content; - return result; + return result ?? ''; } -async function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { +async function getAIResponseRecursive(messages: AIMessage[], signal: AbortSignal): Promise { return getAIResponse(messages, signal) .catch(async (error) => { if (!error.message.includes('Connection error')) { @@ -62,8 +62,8 @@ export const aiIntegration = new AIIntegration({ const signal = controller.signal; const aiPrompt: AIMessage[] = [ - { role: 'system', content: prompt.system }, - { role: 'user', content: prompt.user }, + { role: 'system', content: prompt.system ?? '' }, + { role: 'user', content: prompt.user ?? '' }, ]; const promise = getAIResponseRecursive(aiPrompt, signal); diff --git a/apps/demos/Demos/DataGrid/AIColumns/ReactJs/Category.js b/apps/demos/Demos/DataGrid/AIColumns/ReactJs/Category.js index 0546e93e7587..4141984774fc 100644 --- a/apps/demos/Demos/DataGrid/AIColumns/ReactJs/Category.js +++ b/apps/demos/Demos/DataGrid/AIColumns/ReactJs/Category.js @@ -1,5 +1,5 @@ import React from 'react'; export default function Category(props) { - return
{props.data.CategoryName}
; + return
{props.data?.CategoryName}
; } diff --git a/apps/demos/Demos/DataGrid/AIColumns/ReactJs/service.js b/apps/demos/Demos/DataGrid/AIColumns/ReactJs/service.js index faa0d021a89e..4c34b46da72e 100644 --- a/apps/demos/Demos/DataGrid/AIColumns/ReactJs/service.js +++ b/apps/demos/Demos/DataGrid/AIColumns/ReactJs/service.js @@ -19,7 +19,7 @@ async function getAIResponse(messages, signal) { }; const response = await aiService.chat.completions.create(params, { signal }); const result = response.choices[0].message?.content; - return result; + return result ?? ''; } async function getAIResponseRecursive(messages, signal) { return getAIResponse(messages, signal).catch(async (error) => { @@ -48,8 +48,8 @@ export const aiIntegration = new AIIntegration({ const controller = new AbortController(); const signal = controller.signal; const aiPrompt = [ - { role: 'system', content: prompt.system }, - { role: 'user', content: prompt.user }, + { role: 'system', content: prompt.system ?? '' }, + { role: 'user', content: prompt.user ?? '' }, ]; const promise = getAIResponseRecursive(aiPrompt, signal); const result = { diff --git a/apps/demos/Demos/DataGrid/AdvancedMasterDetailView/React/OrderHistory.tsx b/apps/demos/Demos/DataGrid/AdvancedMasterDetailView/React/OrderHistory.tsx index 8bb6e4aa1d7b..dbd4ca553348 100644 --- a/apps/demos/Demos/DataGrid/AdvancedMasterDetailView/React/OrderHistory.tsx +++ b/apps/demos/Demos/DataGrid/AdvancedMasterDetailView/React/OrderHistory.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; +import type { CustomStore } from 'devextreme-react/common/data'; import { Column, DataGrid, Paging, Summary, TotalItem, ValueFormat, } from 'devextreme-react/data-grid'; @@ -12,7 +13,7 @@ interface OrderHistoryProps { } const OrderHistory = ({ productId }: OrderHistoryProps) => { - const [orderHistoryStore, setOrderHistoryStore] = useState(null); + const [orderHistoryStore, setOrderHistoryStore] = useState(null); useEffect(() => { if (productId) { diff --git a/apps/demos/Demos/DataGrid/AdvancedMasterDetailView/React/ProductSelectBox.tsx b/apps/demos/Demos/DataGrid/AdvancedMasterDetailView/React/ProductSelectBox.tsx index 04edb4a37e58..3f42bfdaa36c 100644 --- a/apps/demos/Demos/DataGrid/AdvancedMasterDetailView/React/ProductSelectBox.tsx +++ b/apps/demos/Demos/DataGrid/AdvancedMasterDetailView/React/ProductSelectBox.tsx @@ -1,5 +1,8 @@ import React, { useCallback, useEffect, useState } from 'react'; -import { SelectBox, type SelectBoxTypes } from 'devextreme-react/select-box'; + +import type { CustomStore } from 'devextreme-react/common/data'; +import { SelectBox } from 'devextreme-react/select-box'; +import type { SelectBoxTypes } from 'devextreme-react/select-box'; import { createStore } from 'devextreme-aspnet-data-nojquery'; const url = 'https://js.devexpress.com/Demos/NetCore/api/DataGridAdvancedMasterDetailView'; @@ -12,7 +15,7 @@ interface ProductSelectBoxProps { } const ProductSelectBox = (props: ProductSelectBoxProps) => { - const [productsData, setProductsData] = useState(null); + const [productsData, setProductsData] = useState(null); const valueChanged = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { props.onProductChanged(e.value); diff --git a/apps/demos/Demos/DataGrid/CascadingLookups/React/App.tsx b/apps/demos/Demos/DataGrid/CascadingLookups/React/App.tsx index 38c702e2e93d..acf4713bbb44 100644 --- a/apps/demos/Demos/DataGrid/CascadingLookups/React/App.tsx +++ b/apps/demos/Demos/DataGrid/CascadingLookups/React/App.tsx @@ -10,7 +10,7 @@ import type { Employee } from './data.ts'; const onEditorPreparing = (e: DataGridTypes.EditorPreparingEvent) => { if (e.parentType === 'dataRow' && e.dataField === 'CityID') { - e.editorOptions.disabled = e.row.data.StateID === undefined; + e.editorOptions.disabled = e.row?.data.StateID === undefined; } }; @@ -19,9 +19,9 @@ const getFilteredCities = (options: { data?: Employee; }) => ({ filter: options.data ? ['StateID', '=', options.data.StateID] : null, }); -function setStateValue(rowData: Employee, value: number) { +function setStateValue(this: DataGridTypes.Column, rowData: Employee, value: number) { rowData.CityID = null; - this.defaultSetCellValue?.(rowData, value); + this.defaultSetCellValue?.(rowData, value, undefined); } const App = () => ( diff --git a/apps/demos/Demos/DataGrid/CascadingLookups/React/data.ts b/apps/demos/Demos/DataGrid/CascadingLookups/React/data.ts index 06c559f1aabe..a475c83f3cc8 100644 --- a/apps/demos/Demos/DataGrid/CascadingLookups/React/data.ts +++ b/apps/demos/Demos/DataGrid/CascadingLookups/React/data.ts @@ -4,8 +4,8 @@ export interface Employee { LastName: string; Prefix: string; Position: string; - StateID: number; - CityID: number; + StateID: number | null; + CityID: number | null; } export const employees: Employee[] = [{ diff --git a/apps/demos/Demos/DataGrid/CascadingLookups/ReactJs/App.js b/apps/demos/Demos/DataGrid/CascadingLookups/ReactJs/App.js index 9b8b73d262b0..197ebcd9370b 100644 --- a/apps/demos/Demos/DataGrid/CascadingLookups/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/CascadingLookups/ReactJs/App.js @@ -4,7 +4,7 @@ import { employees, states, cities } from './data.js'; const onEditorPreparing = (e) => { if (e.parentType === 'dataRow' && e.dataField === 'CityID') { - e.editorOptions.disabled = e.row.data.StateID === undefined; + e.editorOptions.disabled = e.row?.data.StateID === undefined; } }; const getFilteredCities = (options) => ({ @@ -13,7 +13,7 @@ const getFilteredCities = (options) => ({ }); function setStateValue(rowData, value) { rowData.CityID = null; - this.defaultSetCellValue?.(rowData, value); + this.defaultSetCellValue?.(rowData, value, undefined); } const App = () => (
diff --git a/apps/demos/Demos/DataGrid/Cell/React/ChartCell.tsx b/apps/demos/Demos/DataGrid/Cell/React/ChartCell.tsx index 29227b846918..0c8ad12ff331 100644 --- a/apps/demos/Demos/DataGrid/Cell/React/ChartCell.tsx +++ b/apps/demos/Demos/DataGrid/Cell/React/ChartCell.tsx @@ -1,6 +1,6 @@ import React from 'react'; import Sparkline, { Size, Tooltip } from 'devextreme-react/sparkline'; -import { type DataGridTypes } from 'devextreme-react/data-grid'; +import type { DataGridTypes } from 'devextreme-react/data-grid'; const ChartCell = (cellData: DataGridTypes.ColumnCellTemplateData) => (
diff --git a/apps/demos/Demos/DataGrid/Cell/React/DiffCell.tsx b/apps/demos/Demos/DataGrid/Cell/React/DiffCell.tsx index 5ec7997fa278..20a78c7b4a83 100644 --- a/apps/demos/Demos/DataGrid/Cell/React/DiffCell.tsx +++ b/apps/demos/Demos/DataGrid/Cell/React/DiffCell.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { formatNumber } from 'devextreme-react/common/core/localization'; -import { type DataGridTypes } from 'devextreme-react/data-grid'; +import type { DataGridTypes } from 'devextreme-react/data-grid'; -const getGridCellData = (gridData: DataGridTypes.ColumnCellTemplateData) => gridData.data[gridData.column.caption.toLowerCase()]; +const getGridCellData = (gridData: DataGridTypes.ColumnCellTemplateData) => gridData.data[gridData.column.caption?.toLowerCase() ?? '']; const DiffCell = (cellData: DataGridTypes.ColumnCellTemplateData) => { const gridCellData = getGridCellData(cellData); diff --git a/apps/demos/Demos/DataGrid/Cell/ReactJs/DiffCell.js b/apps/demos/Demos/DataGrid/Cell/ReactJs/DiffCell.js index e3fea88ba209..1e981de8626d 100644 --- a/apps/demos/Demos/DataGrid/Cell/ReactJs/DiffCell.js +++ b/apps/demos/Demos/DataGrid/Cell/ReactJs/DiffCell.js @@ -1,7 +1,7 @@ import React from 'react'; import { formatNumber } from 'devextreme-react/common/core/localization'; -const getGridCellData = (gridData) => gridData.data[gridData.column.caption.toLowerCase()]; +const getGridCellData = (gridData) => gridData.data[gridData.column.caption?.toLowerCase() ?? '']; const DiffCell = (cellData) => { const gridCellData = getGridCellData(cellData); return ( diff --git a/apps/demos/Demos/DataGrid/CellEditing/React/App.tsx b/apps/demos/Demos/DataGrid/CellEditing/React/App.tsx index 3b7ae2c0bc96..da68ec320353 100644 --- a/apps/demos/Demos/DataGrid/CellEditing/React/App.tsx +++ b/apps/demos/Demos/DataGrid/CellEditing/React/App.tsx @@ -14,7 +14,7 @@ const dataSource = new DataSource({ }); const App = () => { - const [selectedItemKeys, setSelectedItemKeys] = useState([]); + const [selectedItemKeys, setSelectedItemKeys] = useState([]); const deleteRecords = useCallback(() => { selectedItemKeys.forEach((key) => { diff --git a/apps/demos/Demos/DataGrid/CommandColumnConfiguration/React/App.tsx b/apps/demos/Demos/DataGrid/CommandColumnConfiguration/React/App.tsx index a2be3b0f4657..5a6d650a6686 100644 --- a/apps/demos/Demos/DataGrid/CommandColumnConfiguration/React/App.tsx +++ b/apps/demos/Demos/DataGrid/CommandColumnConfiguration/React/App.tsx @@ -6,13 +6,15 @@ import type { DataGridTypes } from 'devextreme-react/data-grid'; import { employees as defaultEmployees, states, getMaxID } from './data.ts'; -const isChief = (position: string) => position && ['CEO', 'CMO'].indexOf(position.trim().toUpperCase()) >= 0; +type ButtonRenderOptions = Pick; -const isCloneIconVisible = (e) => !e.row.isEditing; +const isChief = (position?: string) => !!position && ['CEO', 'CMO'].indexOf(position.trim().toUpperCase()) >= 0; -const isCloneIconDisabled = (e) => isChief(e.row.data.Position); +const isCloneIconVisible = (e: ButtonRenderOptions) => !e.row?.isEditing; -const isDeleteIconVisible = (e) => !isChief(e.row.data.Position); +const isCloneIconDisabled = (e: ButtonRenderOptions) => isChief(e.row?.data?.Position); + +const isDeleteIconVisible = (e: ButtonRenderOptions) => !isChief(e.row?.data?.Position); const onRowValidating = (e: DataGridTypes.RowValidatingEvent) => { const position = e.newData.Position; diff --git a/apps/demos/Demos/DataGrid/CommandColumnConfiguration/ReactJs/App.js b/apps/demos/Demos/DataGrid/CommandColumnConfiguration/ReactJs/App.js index 7de40fbb4bc8..af260a2830f7 100644 --- a/apps/demos/Demos/DataGrid/CommandColumnConfiguration/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/CommandColumnConfiguration/ReactJs/App.js @@ -5,10 +5,10 @@ import DataGrid, { import { employees as defaultEmployees, states, getMaxID } from './data.js'; const isChief = (position) => - position && ['CEO', 'CMO'].indexOf(position.trim().toUpperCase()) >= 0; -const isCloneIconVisible = (e) => !e.row.isEditing; -const isCloneIconDisabled = (e) => isChief(e.row.data.Position); -const isDeleteIconVisible = (e) => !isChief(e.row.data.Position); + !!position && ['CEO', 'CMO'].indexOf(position.trim().toUpperCase()) >= 0; +const isCloneIconVisible = (e) => !e.row?.isEditing; +const isCloneIconDisabled = (e) => isChief(e.row?.data?.Position); +const isDeleteIconVisible = (e) => !isChief(e.row?.data?.Position); const onRowValidating = (e) => { const position = e.newData.Position; if (isChief(position)) { diff --git a/apps/demos/Demos/DataGrid/CustomDataSource/React/App.tsx b/apps/demos/Demos/DataGrid/CustomDataSource/React/App.tsx index bd4d036ec698..ec49ec59b419 100644 --- a/apps/demos/Demos/DataGrid/CustomDataSource/React/App.tsx +++ b/apps/demos/Demos/DataGrid/CustomDataSource/React/App.tsx @@ -1,7 +1,8 @@ import React from 'react'; import DataGrid, { Column, Paging, Pager } from 'devextreme-react/data-grid'; -import { CustomStore, type LoadOptions, type LoadResultObject } from 'devextreme-react/common/data'; +import { CustomStore } from 'devextreme-react/common/data'; +import type { LoadOptions, LoadResultObject } from 'devextreme-react/common/data'; import 'whatwg-fetch'; function isNotEmpty(value: unknown) { diff --git a/apps/demos/Demos/DataGrid/CustomEditors/React/App.tsx b/apps/demos/Demos/DataGrid/CustomEditors/React/App.tsx index 15a758e950b9..531d01b545ba 100644 --- a/apps/demos/Demos/DataGrid/CustomEditors/React/App.tsx +++ b/apps/demos/Demos/DataGrid/CustomEditors/React/App.tsx @@ -24,7 +24,7 @@ const statusLabel = { 'aria-label': 'Status' }; const employees = createStore({ key: 'ID', loadUrl: `${url}/Employees`, - onBeforeSend(method, ajaxOptions) { + onBeforeSend(_method, ajaxOptions) { ajaxOptions.xhrFields = { withCredentials: true }; }, }); @@ -34,7 +34,7 @@ const tasks = createStore({ loadUrl: `${url}/Tasks`, updateUrl: `${url}/UpdateTask`, insertUrl: `${url}/InsertTask`, - onBeforeSend(method, ajaxOptions) { + onBeforeSend(_method, ajaxOptions) { ajaxOptions.xhrFields = { withCredentials: true }; }, }); @@ -46,7 +46,7 @@ const cellTemplate = ( const noBreakSpace = '\u00A0'; const assignees = (options.value || []).map( - (assigneeId: number) => options.column.lookup.calculateCellValue(assigneeId), + (assigneeId: number) => options.column.lookup?.calculateCellValue?.(assigneeId), ); const text = assignees.join(', '); @@ -73,7 +73,7 @@ function calculateFilterExpression( const onRowInserted = (e: DataGridTypes.RowInsertedEvent) => e.component.navigateToRow(e.key); -const statusEditorRender = (cell) => { +const statusEditorRender = (cell: DataGridTypes.ColumnEditCellTemplateData) => { const onValueChanged = (e: SelectBoxTypes.ValueChangedEvent) => cell.setValue(e.value); const itemRender = (data: { id: number, name: string } | null) => { @@ -91,10 +91,15 @@ const statusEditorRender = (cell) => { return (All); }; + const lookupDataSource = cell.column.lookup?.dataSource; + const dataSource = typeof lookupDataSource === 'function' + ? lookupDataSource({ data: cell.data, key: cell.row.key }) + : lookupDataSource; + return ( diff --git a/apps/demos/Demos/DataGrid/CustomEditors/ReactJs/App.js b/apps/demos/Demos/DataGrid/CustomEditors/ReactJs/App.js index f24c7d8ca14c..1eb4fd660953 100644 --- a/apps/demos/Demos/DataGrid/CustomEditors/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/CustomEditors/ReactJs/App.js @@ -20,7 +20,7 @@ const statusLabel = { 'aria-label': 'Status' }; const employees = createStore({ key: 'ID', loadUrl: `${url}/Employees`, - onBeforeSend(method, ajaxOptions) { + onBeforeSend(_method, ajaxOptions) { ajaxOptions.xhrFields = { withCredentials: true }; }, }); @@ -29,14 +29,14 @@ const tasks = createStore({ loadUrl: `${url}/Tasks`, updateUrl: `${url}/UpdateTask`, insertUrl: `${url}/InsertTask`, - onBeforeSend(method, ajaxOptions) { + onBeforeSend(_method, ajaxOptions) { ajaxOptions.xhrFields = { withCredentials: true }; }, }); const cellTemplate = (container, options) => { const noBreakSpace = '\u00A0'; const assignees = (options.value || []).map((assigneeId) => - options.column.lookup.calculateCellValue(assigneeId), + options.column.lookup?.calculateCellValue?.(assigneeId), ); const text = assignees.join(', '); container.textContent = text || noBreakSpace; @@ -66,10 +66,15 @@ const statusEditorRender = (cell) => { } return (All); }; + const lookupDataSource = cell.column.lookup?.dataSource; + const dataSource = + typeof lookupDataSource === 'function' + ? lookupDataSource({ data: cell.data, key: cell.row.key }) + : lookupDataSource; return ( { const [taskCount, setTaskCount] = useState(0); @@ -32,7 +34,7 @@ const App = () => { const [avgDuration, setAvgDuration] = useState(0); const calculateStatistics = useCallback(async () => { - const selectedItems = await dataGrid.getSelectedRowsData(); + const selectedItems = await dataGrid?.getSelectedRowsData() ?? []; const totalDuration = selectedItems.reduce((currentValue: number, item: { Task_Due_Date: string; Task_Start_Date: string; }) => { const dueDateTime = new Date(item.Task_Due_Date).getTime(); diff --git a/apps/demos/Demos/DataGrid/DeferredSelection/ReactJs/App.js b/apps/demos/Demos/DataGrid/DeferredSelection/ReactJs/App.js index 9a06ec232c37..4ac37cc11fa5 100644 --- a/apps/demos/Demos/DataGrid/DeferredSelection/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/DeferredSelection/ReactJs/App.js @@ -29,7 +29,7 @@ const App = () => { const [peopleCount, setPeopleCount] = useState(0); const [avgDuration, setAvgDuration] = useState(0); const calculateStatistics = useCallback(async () => { - const selectedItems = await dataGrid.getSelectedRowsData(); + const selectedItems = (await dataGrid?.getSelectedRowsData()) ?? []; const totalDuration = selectedItems.reduce((currentValue, item) => { const dueDateTime = new Date(item.Task_Due_Date).getTime(); const startDateTime = new Date(item.Task_Start_Date).getTime(); diff --git a/apps/demos/Demos/DataGrid/ExcelJSCellCustomization/React/App.tsx b/apps/demos/Demos/DataGrid/ExcelJSCellCustomization/React/App.tsx index ec0893462fc5..f805c54c4f93 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSCellCustomization/React/App.tsx +++ b/apps/demos/Demos/DataGrid/ExcelJSCellCustomization/React/App.tsx @@ -7,9 +7,12 @@ import type { DataGridTypes } from 'devextreme-react/data-grid'; import { Workbook } from 'devextreme-exceljs-fork'; import { saveAs } from 'file-saver-es'; import { exportDataGrid } from 'devextreme-react/common/export/excel'; +import type { DataGridExportOptions } from 'devextreme-react/common/export/excel'; import { companies } from './data.ts'; +type CustomizeCellOptions = Parameters['customizeCell']>[number]; + const onExporting = (e: DataGridTypes.ExportingEvent) => { const workbook = new Workbook(); const worksheet = workbook.addWorksheet('Companies'); @@ -23,22 +26,22 @@ const onExporting = (e: DataGridTypes.ExportingEvent) => { worksheet, keepColumnWidths: false, topLeftCell: { row: 2, column: 2 }, - customizeCell: ({ gridCell, excelCell }) => { - if (gridCell.rowType === 'data') { - if (gridCell.column.dataField === 'Phone') { + customizeCell: ({ gridCell, excelCell }: CustomizeCellOptions) => { + if (excelCell && gridCell?.rowType === 'data') { + if (gridCell.column?.dataField === 'Phone') { excelCell.value = parseInt(gridCell.value, 10); excelCell.numFmt = '[<=9999999]###-####;(###) ###-####'; } - if (gridCell.column.dataField === 'Website') { + if (gridCell.column?.dataField === 'Website') { excelCell.value = { text: gridCell.value, hyperlink: gridCell.value }; excelCell.font = { color: { argb: 'FF0000FF' }, underline: true }; excelCell.alignment = { horizontal: 'left' }; } } - if (gridCell.rowType === 'group') { + if (excelCell && gridCell?.rowType === 'group') { excelCell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'BEDFE6' } }; } - if (gridCell.rowType === 'totalFooter' && excelCell.value) { + if (excelCell && gridCell?.rowType === 'totalFooter' && excelCell.value) { excelCell.font.italic = true; } }, @@ -55,7 +58,7 @@ const phoneNumberFormat = (value: number) => { const valueStr = String(value); const USNumber = valueStr.match(/(\d{3})(\d{3})(\d{4})/); - return `(${USNumber[1]}) ${USNumber[2]}-${USNumber[3]}`; + return USNumber ? `(${USNumber[1]}) ${USNumber[2]}-${USNumber[3]}` : ''; }; const App = () => ( diff --git a/apps/demos/Demos/DataGrid/ExcelJSCellCustomization/ReactJs/App.js b/apps/demos/Demos/DataGrid/ExcelJSCellCustomization/ReactJs/App.js index 2cc28bda8d4f..c00b71dd5f14 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSCellCustomization/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/ExcelJSCellCustomization/ReactJs/App.js @@ -30,21 +30,21 @@ const onExporting = (e) => { keepColumnWidths: false, topLeftCell: { row: 2, column: 2 }, customizeCell: ({ gridCell, excelCell }) => { - if (gridCell.rowType === 'data') { - if (gridCell.column.dataField === 'Phone') { + if (excelCell && gridCell?.rowType === 'data') { + if (gridCell.column?.dataField === 'Phone') { excelCell.value = parseInt(gridCell.value, 10); excelCell.numFmt = '[<=9999999]###-####;(###) ###-####'; } - if (gridCell.column.dataField === 'Website') { + if (gridCell.column?.dataField === 'Website') { excelCell.value = { text: gridCell.value, hyperlink: gridCell.value }; excelCell.font = { color: { argb: 'FF0000FF' }, underline: true }; excelCell.alignment = { horizontal: 'left' }; } } - if (gridCell.rowType === 'group') { + if (excelCell && gridCell?.rowType === 'group') { excelCell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'BEDFE6' } }; } - if (gridCell.rowType === 'totalFooter' && excelCell.value) { + if (excelCell && gridCell?.rowType === 'totalFooter' && excelCell.value) { excelCell.font.italic = true; } }, @@ -66,7 +66,7 @@ const renderGridCell = (data) => ( const phoneNumberFormat = (value) => { const valueStr = String(value); const USNumber = valueStr.match(/(\d{3})(\d{3})(\d{4})/); - return `(${USNumber[1]}) ${USNumber[2]}-${USNumber[3]}`; + return USNumber ? `(${USNumber[1]}) ${USNumber[2]}-${USNumber[3]}` : ''; }; const App = () => (
diff --git a/apps/demos/Demos/DataGrid/ExcelJSExportImages/React/App.tsx b/apps/demos/Demos/DataGrid/ExcelJSExportImages/React/App.tsx index 68d2d818d78c..8470f2a2e2d4 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSExportImages/React/App.tsx +++ b/apps/demos/Demos/DataGrid/ExcelJSExportImages/React/App.tsx @@ -5,9 +5,12 @@ import DataGrid, { Column, Export } from 'devextreme-react/data-grid'; import type { DataGridTypes } from 'devextreme-react/data-grid'; import { Anchor, Workbook } from 'devextreme-exceljs-fork'; import { exportDataGrid } from 'devextreme-react/common/export/excel'; +import type { DataGridExportOptions } from 'devextreme-react/common/export/excel'; import { employees } from './data.ts'; +type CustomizeCellOptions = Parameters['customizeCell']>[number]; + const renderGridCell = (cellData: DataGridTypes.ColumnCellTemplateData) => (
Employee photo
); const onExporting = (e: DataGridTypes.ExportingEvent) => { @@ -19,9 +22,9 @@ const onExporting = (e: DataGridTypes.ExportingEvent) => { worksheet, autoFilterEnabled: true, topLeftCell: { row: 2, column: 2 }, - customizeCell: ({ gridCell, excelCell }) => { - if (gridCell.rowType === 'data') { - if (gridCell.column.dataField === 'Picture') { + customizeCell: ({ gridCell, excelCell }: CustomizeCellOptions) => { + if (gridCell?.rowType === 'data') { + if (excelCell && gridCell?.column?.dataField === 'Picture') { excelCell.value = undefined; const image = workbook.addImage({ diff --git a/apps/demos/Demos/DataGrid/ExcelJSExportImages/ReactJs/App.js b/apps/demos/Demos/DataGrid/ExcelJSExportImages/ReactJs/App.js index aae6d48b33cf..803db6b5586b 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSExportImages/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/ExcelJSExportImages/ReactJs/App.js @@ -22,8 +22,8 @@ const onExporting = (e) => { autoFilterEnabled: true, topLeftCell: { row: 2, column: 2 }, customizeCell: ({ gridCell, excelCell }) => { - if (gridCell.rowType === 'data') { - if (gridCell.column.dataField === 'Picture') { + if (gridCell?.rowType === 'data') { + if (excelCell && gridCell?.column?.dataField === 'Picture') { excelCell.value = undefined; const image = workbook.addImage({ base64: gridCell.value, diff --git a/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/App.tsx b/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/App.tsx index 8e24409b6ad3..7a2fcc83108b 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/App.tsx +++ b/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/App.tsx @@ -12,6 +12,7 @@ import { exportDataGrid } from 'devextreme-react/common/export/excel'; import type { DataGridCell } from 'devextreme-react/common/export/excel'; import { products } from './data.ts'; +import type { ExcelCell, CustomizeCellOptions } from './data.ts'; const priceDataSource: DataSourceOptions = { store: new ArrayStore({ @@ -31,14 +32,9 @@ const ratingDataSource: DataSourceOptions = { filter: ['Product_ID', '<', 10], }; -interface ExcelCell { - fullAddress: { row: number }; - fill: any; -} - -const setAlternatingRowsBackground = (gridCell: DataGridCell, excelCell: ExcelCell) => { - if (gridCell.rowType === 'header' || gridCell.rowType === 'data') { - if (excelCell.fullAddress.row % 2 === 0) { +const setAlternatingRowsBackground = (gridCell?: DataGridCell, excelCell?: ExcelCell) => { + if (gridCell?.rowType === 'header' || gridCell?.rowType === 'data') { + if (excelCell && excelCell.fullAddress.row % 2 === 0) { excelCell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'D3D3D3' }, bgColor: { argb: 'D3D3D3' }, }; @@ -63,14 +59,14 @@ const App = () => { exportDataGrid({ worksheet: priceSheet, - component: priceGridRef.current.instance(), + component: priceGridRef.current?.instance(), topLeftCell: { row: 4, column: 2 }, - customizeCell: ({ gridCell, excelCell }) => { + customizeCell: ({ gridCell, excelCell }: CustomizeCellOptions) => { setAlternatingRowsBackground(gridCell, excelCell); }, }).then(() => exportDataGrid({ worksheet: ratingSheet, - component: ratingGridRef.current.instance(), + component: ratingGridRef.current?.instance(), topLeftCell: { row: 4, column: 2 }, customizeCell: ({ gridCell, excelCell }) => { setAlternatingRowsBackground(gridCell, excelCell); diff --git a/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/data.ts b/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/data.ts index 88d31dc4b94d..991803016422 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/data.ts +++ b/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/React/data.ts @@ -1,17 +1,24 @@ +import type { DataGridCell } from 'devextreme-react/common/export/excel'; + export interface Product { Product_ID: number; - Product_Name: string; - Product_Sale_Price: number; - Product_Retail_Price: number; - Product_Consumer_Rating: number; - Product_Category: string; } +export interface ExcelCell { + fullAddress: { row: number }; + fill: any; +} + +export interface CustomizeCellOptions { + gridCell?: DataGridCell; + excelCell?: ExcelCell; +} + export const products: Product[] = [ { Product_ID: 1, diff --git a/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/ReactJs/App.js b/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/ReactJs/App.js index 9a1a423b7dfa..2279dbf4a1b6 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/ExcelJSExportMultipleGrids/ReactJs/App.js @@ -25,8 +25,8 @@ const ratingDataSource = { filter: ['Product_ID', '<', 10], }; const setAlternatingRowsBackground = (gridCell, excelCell) => { - if (gridCell.rowType === 'header' || gridCell.rowType === 'data') { - if (excelCell.fullAddress.row % 2 === 0) { + if (gridCell?.rowType === 'header' || gridCell?.rowType === 'data') { + if (excelCell && excelCell.fullAddress.row % 2 === 0) { excelCell.fill = { type: 'pattern', pattern: 'solid', @@ -49,7 +49,7 @@ const App = () => { ratingSheet.getRow(2).getCell(2).font = { bold: true, size: 16, underline: 'double' }; exportDataGrid({ worksheet: priceSheet, - component: priceGridRef.current.instance(), + component: priceGridRef.current?.instance(), topLeftCell: { row: 4, column: 2 }, customizeCell: ({ gridCell, excelCell }) => { setAlternatingRowsBackground(gridCell, excelCell); @@ -58,7 +58,7 @@ const App = () => { .then(() => exportDataGrid({ worksheet: ratingSheet, - component: ratingGridRef.current.instance(), + component: ratingGridRef.current?.instance(), topLeftCell: { row: 4, column: 2 }, customizeCell: ({ gridCell, excelCell }) => { setAlternatingRowsBackground(gridCell, excelCell); diff --git a/apps/demos/Demos/DataGrid/ExcelJSHeaderAndFooter/React/App.tsx b/apps/demos/Demos/DataGrid/ExcelJSHeaderAndFooter/React/App.tsx index 7efe0922aacd..2c91453a23b0 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSHeaderAndFooter/React/App.tsx +++ b/apps/demos/Demos/DataGrid/ExcelJSHeaderAndFooter/React/App.tsx @@ -5,6 +5,7 @@ import DataGrid, { Column, Export } from 'devextreme-react/data-grid'; import type { DataGridTypes } from 'devextreme-react/data-grid'; import { Workbook } from 'devextreme-exceljs-fork'; import { exportDataGrid } from 'devextreme-react/common/export/excel'; +import type { CellRange } from 'devextreme/excel_exporter'; import { countries } from './data.ts'; @@ -21,7 +22,7 @@ const onExporting = (e: DataGridTypes.ExportingEvent) => { component: e.component, worksheet, topLeftCell: { row: 4, column: 1 }, - }).then((cellRange) => { + }).then((cellRange: CellRange) => { // header const headerRow = worksheet.getRow(2); headerRow.height = 30; @@ -32,7 +33,7 @@ const onExporting = (e: DataGridTypes.ExportingEvent) => { headerRow.getCell(1).alignment = { horizontal: 'center' }; // footer - const footerRowIndex = cellRange.to.row + 2; + const footerRowIndex = (cellRange.to?.row ?? 0) + 2; const footerRow = worksheet.getRow(footerRowIndex); worksheet.mergeCells(footerRowIndex, 1, footerRowIndex, 8); diff --git a/apps/demos/Demos/DataGrid/ExcelJSHeaderAndFooter/ReactJs/App.js b/apps/demos/Demos/DataGrid/ExcelJSHeaderAndFooter/ReactJs/App.js index c1be5b80c496..5bcfc1c9d2af 100644 --- a/apps/demos/Demos/DataGrid/ExcelJSHeaderAndFooter/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/ExcelJSHeaderAndFooter/ReactJs/App.js @@ -25,7 +25,7 @@ const onExporting = (e) => { headerRow.getCell(1).font = { name: 'Segoe UI Light', size: 22 }; headerRow.getCell(1).alignment = { horizontal: 'center' }; // footer - const footerRowIndex = cellRange.to.row + 2; + const footerRowIndex = (cellRange.to?.row ?? 0) + 2; const footerRow = worksheet.getRow(footerRowIndex); worksheet.mergeCells(footerRowIndex, 1, footerRowIndex, 8); footerRow.getCell(1).value = 'www.wikipedia.org'; diff --git a/apps/demos/Demos/DataGrid/FilterPanel/React/App.tsx b/apps/demos/Demos/DataGrid/FilterPanel/React/App.tsx index e7ec3d6e81a9..3e2fc48afde8 100644 --- a/apps/demos/Demos/DataGrid/FilterPanel/React/App.tsx +++ b/apps/demos/Demos/DataGrid/FilterPanel/React/App.tsx @@ -1,4 +1,5 @@ import React from 'react'; + import DataGrid, { Column, FilterRow, @@ -7,7 +8,9 @@ import DataGrid, { FilterBuilderPopup, Scrolling, } from 'devextreme-react/data-grid'; + import { orders } from './data.ts'; +import type { Order, OrderFilter } from './data.ts'; const saleAmountEditorOptions = { format: 'currency', @@ -16,7 +19,7 @@ const saleAmountEditorOptions = { 'aria-label': 'Filter cell', }, }; -const getOrderDay = (rowData) => (new Date(rowData.OrderDate)).getDay(); +const getOrderDay = (rowData: Order) => (new Date(rowData.OrderDate)).getDay(); const filterBuilderPopupPosition = { of: window, @@ -39,7 +42,7 @@ const filterBuilder = { const filterValue = [['Employee', '=', 'Clark Morgan'], 'and', ['OrderDate', 'weekends']]; -const saleAmountHeaderFilters = [{ +const saleAmountHeaderFilters: OrderFilter[] = [{ text: 'Less than $3000', value: ['SaleAmount', '<', 3000], }, { diff --git a/apps/demos/Demos/DataGrid/FilterPanel/React/data.ts b/apps/demos/Demos/DataGrid/FilterPanel/React/data.ts index e9336764866b..c81f1a7c9816 100644 --- a/apps/demos/Demos/DataGrid/FilterPanel/React/data.ts +++ b/apps/demos/Demos/DataGrid/FilterPanel/React/data.ts @@ -1,4 +1,26 @@ -export const orders = [{ +import type { FilterBuilderTypes } from 'devextreme-react/filter-builder'; + +export interface Order { + ID: number; + OrderNumber: number; + OrderDate: string; + SaleAmount: number; + Terms: string; + Employee: string; + CustomerInfo: { + StoreState: string; + StoreCity: string; + }; +} + +export type OrderFilterValue = [T, FilterBuilderTypes.FilterOperation, Order[T]]; + +export interface OrderFilter { + text: string; + value: OrderFilterValue | OrderFilterValue[]; +} + +export const orders: Order[] = [{ ID: 1, OrderNumber: 35703, OrderDate: '2014/04/10', diff --git a/apps/demos/Demos/DataGrid/Filtering/React/App.tsx b/apps/demos/Demos/DataGrid/Filtering/React/App.tsx index de146a12ec6a..3d14d435b6aa 100644 --- a/apps/demos/Demos/DataGrid/Filtering/React/App.tsx +++ b/apps/demos/Demos/DataGrid/Filtering/React/App.tsx @@ -1,11 +1,22 @@ import React, { useCallback, useRef, useState } from 'react'; +import type { ComponentProps } from 'react'; + import DataGrid, { Column, FilterRow, HeaderFilter, Search, SearchPanel, Pager, } from 'devextreme-react/data-grid'; -import SelectBox, { type SelectBoxTypes } from 'devextreme-react/select-box'; -import CheckBox, { type CheckBoxTypes } from 'devextreme-react/check-box'; +import type { DataGridRef, DataGridTypes } from 'devextreme-react/data-grid'; +import SelectBox from 'devextreme-react/select-box'; +import type { SelectBoxTypes } from 'devextreme-react/select-box'; +import CheckBox from 'devextreme-react/check-box'; +import type { CheckBoxTypes } from 'devextreme-react/check-box'; import { orders } from './data.ts'; +import type { + Order, + OrderFilter, + HeaderFilterDataResult, + HeaderFilterDataSourceOptions, +} from './data.ts'; const saleAmountEditorOptions = { format: 'currency', @@ -24,7 +35,7 @@ const applyFilterTypes = [{ name: 'On Button Click', }]; -const saleAmountHeaderFilter = [{ +const saleAmountHeaderFilter: OrderFilter[] = [{ text: 'Less than $3000', value: ['SaleAmount', '<', 3000], }, { @@ -50,37 +61,44 @@ const saleAmountHeaderFilter = [{ value: ['SaleAmount', '>=', 20000], }]; -const getOrderDay = (rowData) => (new Date(rowData.OrderDate)).getDay(); +const getOrderDay = (rowData: Order) => (new Date(rowData.OrderDate)).getDay(); -function calculateFilterExpression(value: string, selectedFilterOperations, target: string) { +function calculateFilterExpression( + this: DataGridTypes.Column, + value: string, + selectedFilterOperations: string | null, + target: string +) { const column = this; if (target === 'headerFilter' && value === 'weekends') { return [[getOrderDay, '=', 0], 'or', [getOrderDay, '=', 6]]; } - return column.defaultCalculateFilterExpression(value, selectedFilterOperations, target); + return column.defaultCalculateFilterExpression?.(value, selectedFilterOperations, target); } -const orderHeaderFilter = (data) => { - data.dataSource.postProcess = (results) => { - results.push({ - text: 'Weekends', - value: 'weekends', - }); +const orderHeaderFilter = (data: HeaderFilterDataSourceOptions) => { + if (data.dataSource) { + data.dataSource.postProcess = (results: HeaderFilterDataResult[]) => { + results.push({ + text: 'Weekends', + value: 'weekends', + }); - return results; - }; + return results; + }; + } }; const App = () => { const [showFilterRow, setShowFilterRow] = useState(true); const [showHeaderFilter, setShowHeaderFilter] = useState(true); const [currentFilter, setCurrentFilter] = useState(applyFilterTypes[0].key); - const dataGridRef = useRef(null); + const dataGridRef = useRef(null); const clearFilter = useCallback(() => { - dataGridRef.current.instance().clearFilter(); + dataGridRef.current?.instance().clearFilter(); }, []); const onShowFilterRowChanged = useCallback((e: CheckBoxTypes.ValueChangedEvent) => { @@ -125,7 +143,7 @@ const App = () => { alignment="right" dataType="date" width={120} - calculateFilterExpression={calculateFilterExpression}> + calculateFilterExpression={calculateFilterExpression as ComponentProps['calculateFilterExpression']}> = [T, FilterBuilderTypes.FilterOperation, Order[T]]; + +export interface OrderFilter { + text: string; + value: OrderFilterValue | OrderFilterValue[]; +} + +export interface HeaderFilterDataResult { + text: string; + value: string; +} + +export interface HeaderFilterDataSourceOptions { + component: Record; + dataSource: DataSourceOptions | null; +} + +export const orders: Order[] = [{ ID: 1, OrderNumber: 35703, OrderDate: '2017/04/10', diff --git a/apps/demos/Demos/DataGrid/Filtering/ReactJs/App.js b/apps/demos/Demos/DataGrid/Filtering/ReactJs/App.js index f29dbe2d6eea..e5beb555d686 100644 --- a/apps/demos/Demos/DataGrid/Filtering/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/Filtering/ReactJs/App.js @@ -66,16 +66,18 @@ function calculateFilterExpression(value, selectedFilterOperations, target) { if (target === 'headerFilter' && value === 'weekends') { return [[getOrderDay, '=', 0], 'or', [getOrderDay, '=', 6]]; } - return column.defaultCalculateFilterExpression(value, selectedFilterOperations, target); + return column.defaultCalculateFilterExpression?.(value, selectedFilterOperations, target); } const orderHeaderFilter = (data) => { - data.dataSource.postProcess = (results) => { - results.push({ - text: 'Weekends', - value: 'weekends', - }); - return results; - }; + if (data.dataSource) { + data.dataSource.postProcess = (results) => { + results.push({ + text: 'Weekends', + value: 'weekends', + }); + return results; + }; + } }; const App = () => { const [showFilterRow, setShowFilterRow] = useState(true); @@ -83,7 +85,7 @@ const App = () => { const [currentFilter, setCurrentFilter] = useState(applyFilterTypes[0].key); const dataGridRef = useRef(null); const clearFilter = useCallback(() => { - dataGridRef.current.instance().clearFilter(); + dataGridRef.current?.instance().clearFilter(); }, []); const onShowFilterRowChanged = useCallback( (e) => { diff --git a/apps/demos/Demos/DataGrid/FilteringAPI/React/App.tsx b/apps/demos/Demos/DataGrid/FilteringAPI/React/App.tsx index 5f7bff68cf77..2ee075201972 100644 --- a/apps/demos/Demos/DataGrid/FilteringAPI/React/App.tsx +++ b/apps/demos/Demos/DataGrid/FilteringAPI/React/App.tsx @@ -15,12 +15,12 @@ const App = () => { const dataGridRef = useRef(null); const onValueChanged = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { - const dataGrid = dataGridRef.current.instance(); + const dataGrid = dataGridRef.current?.instance(); if (e.value === 'All') { - dataGrid.clearFilter(); + dataGrid?.clearFilter(); } else { - dataGrid.filter(['Task_Status', '=', e.value]); + dataGrid?.filter(['Task_Status', '=', e.value]); } setFilterStatus(e.value); diff --git a/apps/demos/Demos/DataGrid/FilteringAPI/ReactJs/App.js b/apps/demos/Demos/DataGrid/FilteringAPI/ReactJs/App.js index 994d7f7a721a..95208a76a8c8 100644 --- a/apps/demos/Demos/DataGrid/FilteringAPI/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/FilteringAPI/ReactJs/App.js @@ -9,11 +9,11 @@ const App = () => { const [filterStatus, setFilterStatus] = useState(statuses[0]); const dataGridRef = useRef(null); const onValueChanged = useCallback((e) => { - const dataGrid = dataGridRef.current.instance(); + const dataGrid = dataGridRef.current?.instance(); if (e.value === 'All') { - dataGrid.clearFilter(); + dataGrid?.clearFilter(); } else { - dataGrid.filter(['Task_Status', '=', e.value]); + dataGrid?.filter(['Task_Status', '=', e.value]); } setFilterStatus(e.value); }, []); diff --git a/apps/demos/Demos/DataGrid/FocusedRow/React/App.tsx b/apps/demos/Demos/DataGrid/FocusedRow/React/App.tsx index 287751e8a6c1..87527aa409bc 100644 --- a/apps/demos/Demos/DataGrid/FocusedRow/React/App.tsx +++ b/apps/demos/Demos/DataGrid/FocusedRow/React/App.tsx @@ -21,7 +21,7 @@ const App = () => { const [taskDetails, setTaskDetails] = useState(''); const [taskStatus, setTaskStatus] = useState(''); const [taskProgress, setTaskProgress] = useState(''); - const [focusedRowKey, setFocusedRowKey] = useState(117); + const [focusedRowKey, setFocusedRowKey] = useState(117); const [autoNavigateToFocusedRow, setAutoNavigateToFocusedRow] = useState(true); const onTaskIdChanged = useCallback((e: NumberBoxTypes.ValueChangedEvent) => { diff --git a/apps/demos/Demos/DataGrid/HorizontalVirtualScrolling/React/data.ts b/apps/demos/Demos/DataGrid/HorizontalVirtualScrolling/React/data.ts index f4ee55c5d469..8587a2fd83cd 100644 --- a/apps/demos/Demos/DataGrid/HorizontalVirtualScrolling/React/data.ts +++ b/apps/demos/Demos/DataGrid/HorizontalVirtualScrolling/React/data.ts @@ -1,10 +1,10 @@ export function generateData(rowCount: number, columnCount: number) { - let i; let - j; - const items: Object[] = []; + let i; + let j; + const items: Record[] = []; for (i = 0; i < rowCount; i += 1) { - const item: Object = {}; + const item: Record = {}; for (j = 0; j < columnCount; j += 1) { item[`field${j + 1}`] = `${i + 1}-${j + 1}`; } diff --git a/apps/demos/Demos/DataGrid/MultipleRecordSelectionAPI/React/App.tsx b/apps/demos/Demos/DataGrid/MultipleRecordSelectionAPI/React/App.tsx index b084ac83f6c3..c176a8ed8042 100644 --- a/apps/demos/Demos/DataGrid/MultipleRecordSelectionAPI/React/App.tsx +++ b/apps/demos/Demos/DataGrid/MultipleRecordSelectionAPI/React/App.tsx @@ -16,14 +16,14 @@ const getEmployeeName = (row: Employee) => `${row.FirstName} ${row.LastName}`; const getEmployeeNames = (selectedRowsData: Employee[]) => (selectedRowsData.length ? selectedRowsData.map(getEmployeeName).join(', ') : 'Nobody has been selected'); const App = () => { - const [prefix, setPrefix] = useState(''); - const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [prefix, setPrefix] = useState(''); + const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [selectedEmployeeNames, setSelectedEmployeeNames] = useState('Nobody has been selected'); const dataGridRef = useRef(null); const onClearButtonClicked = useCallback(() => { - dataGridRef.current.instance().clearSelection(); + dataGridRef.current?.instance().clearSelection(); }, []); const onSelectionChanged = useCallback( diff --git a/apps/demos/Demos/DataGrid/MultipleRecordSelectionAPI/ReactJs/App.js b/apps/demos/Demos/DataGrid/MultipleRecordSelectionAPI/ReactJs/App.js index 754da5eae27a..c207bea969f2 100644 --- a/apps/demos/Demos/DataGrid/MultipleRecordSelectionAPI/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/MultipleRecordSelectionAPI/ReactJs/App.js @@ -18,7 +18,7 @@ const App = () => { const [selectedEmployeeNames, setSelectedEmployeeNames] = useState('Nobody has been selected'); const dataGridRef = useRef(null); const onClearButtonClicked = useCallback(() => { - dataGridRef.current.instance().clearSelection(); + dataGridRef.current?.instance().clearSelection(); }, []); const onSelectionChanged = useCallback( ({ selectedRowKeys: changedRowKeys, selectedRowsData }) => { diff --git a/apps/demos/Demos/DataGrid/MultipleSorting/React/App.tsx b/apps/demos/Demos/DataGrid/MultipleSorting/React/App.tsx index 8b1eaff9f64b..51356d2b57fc 100644 --- a/apps/demos/Demos/DataGrid/MultipleSorting/React/App.tsx +++ b/apps/demos/Demos/DataGrid/MultipleSorting/React/App.tsx @@ -1,15 +1,16 @@ import React, { useCallback, useRef, useState } from 'react'; import DataGrid, { Column, Sorting } from 'devextreme-react/data-grid'; +import type { DataGridRef } from 'devextreme-react/data-grid'; import CheckBox from 'devextreme-react/check-box'; import { employees } from './data.ts'; const App = () => { const [positionDisableSorting, setPositionDisableSorting] = useState(false); - const dataGridRef = useRef(null); + const dataGridRef = useRef(null); const onPositionSortingChanged = useCallback(() => { setPositionDisableSorting((previousPositionDisableSorting) => !previousPositionDisableSorting); - dataGridRef.current.instance().columnOption(5, 'sortOrder', undefined); + dataGridRef.current?.instance().columnOption(5, 'sortOrder', undefined); }, []); return ( diff --git a/apps/demos/Demos/DataGrid/MultipleSorting/ReactJs/App.js b/apps/demos/Demos/DataGrid/MultipleSorting/ReactJs/App.js index b3c4dcd6aca4..a047dc7d8d66 100644 --- a/apps/demos/Demos/DataGrid/MultipleSorting/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/MultipleSorting/ReactJs/App.js @@ -8,7 +8,7 @@ const App = () => { const dataGridRef = useRef(null); const onPositionSortingChanged = useCallback(() => { setPositionDisableSorting((previousPositionDisableSorting) => !previousPositionDisableSorting); - dataGridRef.current.instance().columnOption(5, 'sortOrder', undefined); + dataGridRef.current?.instance().columnOption(5, 'sortOrder', undefined); }, []); return (
diff --git a/apps/demos/Demos/DataGrid/NewRecordPosition/React/App.tsx b/apps/demos/Demos/DataGrid/NewRecordPosition/React/App.tsx index 5509abee3205..6cba053f128c 100644 --- a/apps/demos/Demos/DataGrid/NewRecordPosition/React/App.tsx +++ b/apps/demos/Demos/DataGrid/NewRecordPosition/React/App.tsx @@ -1,10 +1,12 @@ import React, { useCallback, useState } from 'react'; + import DataGrid, { Column, Editing, ValidationRule, Button, Toolbar, Item, Scrolling, Pager, } from 'devextreme-react/data-grid'; -import type { IButtonProps, DataGridTypes } from 'devextreme-react/data-grid'; +import type { DataGridTypes } from 'devextreme-react/data-grid'; import SelectBox from 'devextreme-react/select-box'; import Guid from 'devextreme/core/guid'; + import { dataSource, positionLabel, scrollingModeLabel } from './data.ts'; const newRowPositionOptions = ['first', 'last', 'pageTop', 'pageBottom', 'viewportTop', 'viewportBottom']; @@ -19,15 +21,16 @@ const onRowInserted = (e: DataGridTypes.RowInsertedEvent) => { const App = () => { const [newRowPosition, setNewRowPosition] = useState('viewportTop'); const [scrollingMode, setScrollingMode] = useState('standard'); - const [changes, setChanges] = useState([]); - const [editRowKey, setEditRowKey] = useState(null); + const [changes, setChanges] = useState([]); + const [editRowKey, setEditRowKey] = useState(null); - const onAddButtonClick = useCallback((e) => { + const onAddButtonClick = useCallback((e: DataGridTypes.ColumnButtonClickEvent) => { const key = new Guid().toString(); setChanges([{ key, type: 'insert', - insertAfterKey: e.row.key, + insertAfterKey: e.row?.key, + data: {}, }]); setEditRowKey(key); }, []); diff --git a/apps/demos/Demos/DataGrid/NewRecordPosition/ReactJs/App.js b/apps/demos/Demos/DataGrid/NewRecordPosition/ReactJs/App.js index 592bc7bb6368..67afd96eb19c 100644 --- a/apps/demos/Demos/DataGrid/NewRecordPosition/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/NewRecordPosition/ReactJs/App.js @@ -37,7 +37,8 @@ const App = () => { { key, type: 'insert', - insertAfterKey: e.row.key, + insertAfterKey: e.row?.key, + data: {}, }, ]); setEditRowKey(key); diff --git a/apps/demos/Demos/DataGrid/PDFCellCustomization/React/App.tsx b/apps/demos/Demos/DataGrid/PDFCellCustomization/React/App.tsx index b629ead64d98..42170e52ab9f 100644 --- a/apps/demos/Demos/DataGrid/PDFCellCustomization/React/App.tsx +++ b/apps/demos/Demos/DataGrid/PDFCellCustomization/React/App.tsx @@ -1,12 +1,18 @@ import React from 'react'; +import { jsPDF } from 'jspdf'; + import DataGrid, { - Column, Summary, GroupPanel, Grouping, SortByGroupSummaryInfo, TotalItem, Export, type DataGridTypes, + Column, Summary, GroupPanel, Grouping, SortByGroupSummaryInfo, TotalItem, Export, } from 'devextreme-react/data-grid'; -import { jsPDF } from 'jspdf'; +import type { DataGridTypes } from 'devextreme-react/data-grid'; import { exportDataGrid } from 'devextreme-react/common/export/pdf'; +import type { DataGridExportOptions } from 'devextreme-react/common/export/pdf'; import { companies } from './data.ts'; +type CustomizeCellOptions = Parameters['customizeCell']>[number]; +type CustomDrawCellOptions = Parameters['customDrawCell']>[number]; + const exportFormats = ['pdf']; const onExporting = (e: DataGridTypes.ExportingEvent) => { @@ -16,27 +22,27 @@ const onExporting = (e: DataGridTypes.ExportingEvent) => { jsPDFDocument: doc, component: e.component, columnWidths: [40, 40, 30, 30, 40], - customizeCell({ gridCell, pdfCell }) { - if (gridCell.rowType === 'data' && gridCell.column.dataField === 'Phone') { + customizeCell({ gridCell, pdfCell }: CustomizeCellOptions) { + if (gridCell?.rowType === 'data' && gridCell?.column?.dataField === 'Phone' && pdfCell?.text) { pdfCell.text = pdfCell.text.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3'); - } else if (gridCell.rowType === 'group') { + } else if (gridCell?.rowType === 'group' && pdfCell) { pdfCell.backgroundColor = '#BEDFE6'; - } else if (gridCell.rowType === 'totalFooter') { + } else if (gridCell?.rowType === 'totalFooter' && pdfCell?.font) { pdfCell.font.style = 'italic'; } }, - customDrawCell(options) { - const { gridCell, pdfCell } = options; + customDrawCell(options: CustomDrawCellOptions) { + const { gridCell, pdfCell, rect } = options; - if (gridCell.rowType === 'data' && gridCell.column.dataField === 'Website') { + if (gridCell && pdfCell && rect && gridCell.rowType === 'data' && gridCell.column?.dataField === 'Website') { options.cancel = true; doc.setFontSize(11); doc.setTextColor('#0000FF'); - const textHeight = doc.getTextDimensions(pdfCell.text).h; + const textHeight = pdfCell.text ? doc.getTextDimensions(pdfCell.text).h : 0; doc.textWithLink('website', - options.rect.x + pdfCell.padding.left, - options.rect.y + options.rect.h / 2 + textHeight / 2, + rect.x + (pdfCell.padding?.left ?? 0), + rect.y + rect.h / 2 + textHeight / 2, { url: pdfCell.text }); } }, @@ -52,7 +58,7 @@ const renderGridCell = (data: DataGridTypes.ColumnCellTemplateData) => ( const phoneNumberFormat = (value: number) => { const valueStr = String(value); const USNumber = valueStr.match(/(\d{3})(\d{3})(\d{4})/); - return `(${USNumber[1]}) ${USNumber[2]}-${USNumber[3]}`; + return USNumber ? `(${USNumber[1]}) ${USNumber[2]}-${USNumber[3]}` : ''; }; const App = () => ( diff --git a/apps/demos/Demos/DataGrid/PDFCellCustomization/ReactJs/App.js b/apps/demos/Demos/DataGrid/PDFCellCustomization/ReactJs/App.js index bb4e6780b158..3294625943d4 100644 --- a/apps/demos/Demos/DataGrid/PDFCellCustomization/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/PDFCellCustomization/ReactJs/App.js @@ -1,4 +1,5 @@ import React from 'react'; +import { jsPDF } from 'jspdf'; import DataGrid, { Column, Summary, @@ -8,7 +9,6 @@ import DataGrid, { TotalItem, Export, } from 'devextreme-react/data-grid'; -import { jsPDF } from 'jspdf'; import { exportDataGrid } from 'devextreme-react/common/export/pdf'; import { companies } from './data.js'; @@ -20,25 +20,35 @@ const onExporting = (e) => { component: e.component, columnWidths: [40, 40, 30, 30, 40], customizeCell({ gridCell, pdfCell }) { - if (gridCell.rowType === 'data' && gridCell.column.dataField === 'Phone') { + if ( + gridCell?.rowType === 'data' && + gridCell?.column?.dataField === 'Phone' && + pdfCell?.text + ) { pdfCell.text = pdfCell.text.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3'); - } else if (gridCell.rowType === 'group') { + } else if (gridCell?.rowType === 'group' && pdfCell) { pdfCell.backgroundColor = '#BEDFE6'; - } else if (gridCell.rowType === 'totalFooter') { + } else if (gridCell?.rowType === 'totalFooter' && pdfCell?.font) { pdfCell.font.style = 'italic'; } }, customDrawCell(options) { - const { gridCell, pdfCell } = options; - if (gridCell.rowType === 'data' && gridCell.column.dataField === 'Website') { + const { gridCell, pdfCell, rect } = options; + if ( + gridCell && + pdfCell && + rect && + gridCell.rowType === 'data' && + gridCell.column?.dataField === 'Website' + ) { options.cancel = true; doc.setFontSize(11); doc.setTextColor('#0000FF'); - const textHeight = doc.getTextDimensions(pdfCell.text).h; + const textHeight = pdfCell.text ? doc.getTextDimensions(pdfCell.text).h : 0; doc.textWithLink( 'website', - options.rect.x + pdfCell.padding.left, - options.rect.y + options.rect.h / 2 + textHeight / 2, + rect.x + (pdfCell.padding?.left ?? 0), + rect.y + rect.h / 2 + textHeight / 2, { url: pdfCell.text }, ); } @@ -59,7 +69,7 @@ const renderGridCell = (data) => ( const phoneNumberFormat = (value) => { const valueStr = String(value); const USNumber = valueStr.match(/(\d{3})(\d{3})(\d{4})/); - return `(${USNumber[1]}) ${USNumber[2]}-${USNumber[3]}`; + return USNumber ? `(${USNumber[1]}) ${USNumber[2]}-${USNumber[3]}` : ''; }; const App = () => (
diff --git a/apps/demos/Demos/DataGrid/PDFExportImages/React/App.tsx b/apps/demos/Demos/DataGrid/PDFExportImages/React/App.tsx index 87e080df9319..973a79d2fe1f 100644 --- a/apps/demos/Demos/DataGrid/PDFExportImages/React/App.tsx +++ b/apps/demos/Demos/DataGrid/PDFExportImages/React/App.tsx @@ -1,9 +1,16 @@ import React from 'react'; -import DataGrid, { Column, type DataGridTypes, Export } from 'devextreme-react/data-grid'; -import { exportDataGrid } from 'devextreme-react/common/export/pdf'; import { jsPDF } from 'jspdf'; + +import DataGrid, { Column, Export } from 'devextreme-react/data-grid'; +import type { DataGridTypes } from 'devextreme-react/data-grid'; +import { exportDataGrid } from 'devextreme-react/common/export/pdf'; +import type { DataGridExportOptions } from 'devextreme-react/common/export/pdf'; + import { employees } from './data.ts'; +type RowExportingEvent = Parameters['onRowExporting']>[number]; +type CustomDrawCellEvent = Parameters['customDrawCell']>[number]; + const exportFormats = ['pdf']; const onExporting = ({ component }: DataGridTypes.ExportingEvent) => { @@ -20,14 +27,14 @@ const onExporting = ({ component }: DataGridTypes.ExportingEvent) => { }, topLeft: { x: 5, y: 5 }, columnWidths: [30, 30, 30, 30, 30, 30], - onRowExporting: (e) => { - const isHeader = e.rowCells[0].text === 'Picture'; + onRowExporting: (e: RowExportingEvent) => { + const isHeader = e.rowCells?.[0].text === 'Picture'; if (!isHeader) { e.rowHeight = 40; } }, - customDrawCell: (e) => { - if (e.gridCell.rowType === 'data' && e.gridCell.column.dataField === 'Picture') { + customDrawCell: (e: CustomDrawCellEvent) => { + if (e.gridCell && e.gridCell.rowType === 'data' && e.gridCell.column?.dataField === 'Picture' && e.rect) { doc.addImage(e.gridCell.value, 'PNG', e.rect.x, e.rect.y, e.rect.w, e.rect.h); e.cancel = true; } diff --git a/apps/demos/Demos/DataGrid/PDFExportImages/ReactJs/App.js b/apps/demos/Demos/DataGrid/PDFExportImages/ReactJs/App.js index 2a12044d74e4..c8ee1a61d2cb 100644 --- a/apps/demos/Demos/DataGrid/PDFExportImages/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/PDFExportImages/ReactJs/App.js @@ -1,7 +1,7 @@ import React from 'react'; +import { jsPDF } from 'jspdf'; import DataGrid, { Column, Export } from 'devextreme-react/data-grid'; import { exportDataGrid } from 'devextreme-react/common/export/pdf'; -import { jsPDF } from 'jspdf'; import { employees } from './data.js'; const exportFormats = ['pdf']; @@ -19,13 +19,18 @@ const onExporting = ({ component }) => { topLeft: { x: 5, y: 5 }, columnWidths: [30, 30, 30, 30, 30, 30], onRowExporting: (e) => { - const isHeader = e.rowCells[0].text === 'Picture'; + const isHeader = e.rowCells?.[0].text === 'Picture'; if (!isHeader) { e.rowHeight = 40; } }, customDrawCell: (e) => { - if (e.gridCell.rowType === 'data' && e.gridCell.column.dataField === 'Picture') { + if ( + e.gridCell && + e.gridCell.rowType === 'data' && + e.gridCell.column?.dataField === 'Picture' && + e.rect + ) { doc.addImage(e.gridCell.value, 'PNG', e.rect.x, e.rect.y, e.rect.w, e.rect.h); e.cancel = true; } diff --git a/apps/demos/Demos/DataGrid/PDFExportMultipleGrids/React/App.tsx b/apps/demos/Demos/DataGrid/PDFExportMultipleGrids/React/App.tsx index 73245afbf718..acca4e003b20 100644 --- a/apps/demos/Demos/DataGrid/PDFExportMultipleGrids/React/App.tsx +++ b/apps/demos/Demos/DataGrid/PDFExportMultipleGrids/React/App.tsx @@ -29,8 +29,8 @@ interface PDFCell { backgroundColor?: string; } -const setAlternatingRowsBackground = (dataGrid: DataGridRef, gridCell: DataGridCell, pdfCell: PDFCell) => { - if (gridCell.rowType === 'data') { +const setAlternatingRowsBackground = (dataGrid: DataGridRef | null, gridCell: DataGridCell, pdfCell: PDFCell) => { + if (dataGrid && gridCell?.rowType === 'data') { const rowIndex = dataGrid.instance().getRowIndexByKey(gridCell.data.Product_ID); if (rowIndex % 2 === 0) { pdfCell.backgroundColor = '#D3D3D3'; @@ -39,29 +39,33 @@ const setAlternatingRowsBackground = (dataGrid: DataGridRef, gridCell: DataGridC }; const App = () => { - const priceGridRef = useRef(null); - const ratingGridRef = useRef(null); + const priceGridRef = useRef(null); + const ratingGridRef = useRef(null); const exportGrids = useCallback(() => { const doc = new jsPDF(); exportDataGrid({ jsPDFDocument: doc, - component: priceGridRef.current.instance(), + component: priceGridRef.current?.instance(), topLeft: { x: 7, y: 5 }, columnWidths: [20, 50, 50, 50], customizeCell: ({ gridCell, pdfCell }) => { - setAlternatingRowsBackground(priceGridRef.current, gridCell, pdfCell); + if (gridCell && pdfCell) { + setAlternatingRowsBackground(priceGridRef.current, gridCell, pdfCell); + } }, }).then(() => { doc.addPage(); exportDataGrid({ jsPDFDocument: doc, - component: ratingGridRef.current.instance(), + component: ratingGridRef.current?.instance(), topLeft: { x: 7, y: 5 }, columnWidths: [20, 50, 50, 50], customizeCell: ({ gridCell, pdfCell }) => { - setAlternatingRowsBackground(ratingGridRef.current, gridCell, pdfCell); + if (gridCell && pdfCell) { + setAlternatingRowsBackground(ratingGridRef.current, gridCell, pdfCell); + } }, }).then(() => { doc.save('MultipleGrids.pdf'); diff --git a/apps/demos/Demos/DataGrid/PDFExportMultipleGrids/ReactJs/App.js b/apps/demos/Demos/DataGrid/PDFExportMultipleGrids/ReactJs/App.js index ca09bd83534d..209335e4e6df 100644 --- a/apps/demos/Demos/DataGrid/PDFExportMultipleGrids/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/PDFExportMultipleGrids/ReactJs/App.js @@ -22,7 +22,7 @@ const ratingDataSource = new DataSource({ filter: ['Product_ID', '<', 10], }); const setAlternatingRowsBackground = (dataGrid, gridCell, pdfCell) => { - if (gridCell.rowType === 'data') { + if (dataGrid && gridCell?.rowType === 'data') { const rowIndex = dataGrid.instance().getRowIndexByKey(gridCell.data.Product_ID); if (rowIndex % 2 === 0) { pdfCell.backgroundColor = '#D3D3D3'; @@ -36,21 +36,25 @@ const App = () => { const doc = new jsPDF(); exportDataGrid({ jsPDFDocument: doc, - component: priceGridRef.current.instance(), + component: priceGridRef.current?.instance(), topLeft: { x: 7, y: 5 }, columnWidths: [20, 50, 50, 50], customizeCell: ({ gridCell, pdfCell }) => { - setAlternatingRowsBackground(priceGridRef.current, gridCell, pdfCell); + if (gridCell && pdfCell) { + setAlternatingRowsBackground(priceGridRef.current, gridCell, pdfCell); + } }, }).then(() => { doc.addPage(); exportDataGrid({ jsPDFDocument: doc, - component: ratingGridRef.current.instance(), + component: ratingGridRef.current?.instance(), topLeft: { x: 7, y: 5 }, columnWidths: [20, 50, 50, 50], customizeCell: ({ gridCell, pdfCell }) => { - setAlternatingRowsBackground(ratingGridRef.current, gridCell, pdfCell); + if (gridCell && pdfCell) { + setAlternatingRowsBackground(ratingGridRef.current, gridCell, pdfCell); + } }, }).then(() => { doc.save('MultipleGrids.pdf'); diff --git a/apps/demos/Demos/DataGrid/PDFHeaderAndFooter/React/App.tsx b/apps/demos/Demos/DataGrid/PDFHeaderAndFooter/React/App.tsx index 27909d11f9e8..0bf8c320864b 100644 --- a/apps/demos/Demos/DataGrid/PDFHeaderAndFooter/React/App.tsx +++ b/apps/demos/Demos/DataGrid/PDFHeaderAndFooter/React/App.tsx @@ -24,10 +24,10 @@ const onExporting = (e: DataGridTypes.ExportingEvent) => { topLeft: { x: 1, y: 15 }, columnWidths: [30, 20, 30, 15, 22, 22, 20, 20], customDrawCell({ rect }) { - if (lastPoint.x < rect.x + rect.w) { + if (rect && lastPoint.x < rect.x + rect.w) { lastPoint.x = rect.x + rect.w; } - if (lastPoint.y < rect.y + rect.h) { + if (rect && lastPoint.y < rect.y + rect.h) { lastPoint.y = rect.y + rect.h; } }, diff --git a/apps/demos/Demos/DataGrid/PDFHeaderAndFooter/ReactJs/App.js b/apps/demos/Demos/DataGrid/PDFHeaderAndFooter/ReactJs/App.js index 84481b8e2b12..0b522b7b2d5f 100644 --- a/apps/demos/Demos/DataGrid/PDFHeaderAndFooter/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/PDFHeaderAndFooter/ReactJs/App.js @@ -18,10 +18,10 @@ const onExporting = (e) => { topLeft: { x: 1, y: 15 }, columnWidths: [30, 20, 30, 15, 22, 22, 20, 20], customDrawCell({ rect }) { - if (lastPoint.x < rect.x + rect.w) { + if (rect && lastPoint.x < rect.x + rect.w) { lastPoint.x = rect.x + rect.w; } - if (lastPoint.y < rect.y + rect.h) { + if (rect && lastPoint.y < rect.y + rect.h) { lastPoint.y = rect.y + rect.h; } }, diff --git a/apps/demos/Demos/DataGrid/RemoteCRUDOperations/React/App.tsx b/apps/demos/Demos/DataGrid/RemoteCRUDOperations/React/App.tsx index af3ca62975c8..2953795fc795 100644 --- a/apps/demos/Demos/DataGrid/RemoteCRUDOperations/React/App.tsx +++ b/apps/demos/Demos/DataGrid/RemoteCRUDOperations/React/App.tsx @@ -43,7 +43,7 @@ const App = () => { load: () => sendRequest(`${URL}/ShippersLookup`), })); - const [requests, setRequests] = useState([]); + const [requests, setRequests] = useState([]); const [refreshMode, setRefreshMode] = useState('reshape'); const handleRefreshModeChange = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { diff --git a/apps/demos/Demos/DataGrid/RemoteReordering/React/App.tsx b/apps/demos/Demos/DataGrid/RemoteReordering/React/App.tsx index 1fd494d28a3e..70e7a9da6c43 100644 --- a/apps/demos/Demos/DataGrid/RemoteReordering/React/App.tsx +++ b/apps/demos/Demos/DataGrid/RemoteReordering/React/App.tsx @@ -2,6 +2,7 @@ import React from 'react'; import DataGrid, { Column, RowDragging, Scrolling, Lookup, Sorting, } from 'devextreme-react/data-grid'; +import type { DataGridTypes, IRowDraggingProps } from 'devextreme-react/data-grid'; import { createStore } from 'devextreme-aspnet-data-nojquery'; const url = 'https://js.devexpress.com/Demos/NetCore/api/DataGridRowReordering'; @@ -23,7 +24,7 @@ const employeesStore = createStore({ }, }); -const processReorder = async (e) => { +const processReorder = async (e: DataGridTypes.RowDraggingReorderEvent) => { const visibleRows = e.component.getVisibleRows(); const newOrderIndex = visibleRows[e.toIndex].data.OrderIndex; @@ -31,7 +32,7 @@ const processReorder = async (e) => { await e.component.refresh(); }; -const onReorder = (e) => { +const onReorder = (e: DataGridTypes.RowDraggingReorderEvent) => { e.promise = processReorder(e); }; @@ -43,7 +44,7 @@ const App = () => ( > diff --git a/apps/demos/Demos/DataGrid/Row/React/DataRow.tsx b/apps/demos/Demos/DataGrid/Row/React/DataRow.tsx index 6a18be9f4d91..39246604a266 100644 --- a/apps/demos/Demos/DataGrid/Row/React/DataRow.tsx +++ b/apps/demos/Demos/DataGrid/Row/React/DataRow.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { type DataGridTypes } from 'devextreme-react/data-grid'; +import type { DataGridTypes } from 'devextreme-react/data-grid'; const formatDate = new Intl.DateTimeFormat('en-US').format; diff --git a/apps/demos/Demos/DataGrid/RowEditing/React/App.tsx b/apps/demos/Demos/DataGrid/RowEditing/React/App.tsx index 4476be283e10..603cf85d7df9 100644 --- a/apps/demos/Demos/DataGrid/RowEditing/React/App.tsx +++ b/apps/demos/Demos/DataGrid/RowEditing/React/App.tsx @@ -6,7 +6,7 @@ import DataGrid, { Column, Editing, Paging, Lookup } from 'devextreme-react/data import { employees, states } from './data.ts'; const App = () => { - const [events, setEvents] = useState([]); + const [events, setEvents] = useState([]); const logEvent = useCallback((eventName: string) => { setEvents((previousEvents) => [eventName, ...previousEvents]); diff --git a/apps/demos/Demos/DataGrid/SignalRService/React/App.tsx b/apps/demos/Demos/DataGrid/SignalRService/React/App.tsx index da22e4d46534..d14490d1155a 100644 --- a/apps/demos/Demos/DataGrid/SignalRService/React/App.tsx +++ b/apps/demos/Demos/DataGrid/SignalRService/React/App.tsx @@ -1,16 +1,15 @@ import React, { useEffect, useState } from 'react'; -import DataGrid, { - Column, -} from 'devextreme-react/data-grid'; -import { CustomStore } from 'devextreme-react/common/data'; import { HubConnectionBuilder, HttpTransportType } from '@aspnet/signalr'; +import { CustomStore } from 'devextreme-react/common/data'; +import DataGrid, { Column } from 'devextreme-react/data-grid'; + import PriceCell from './PriceCell.tsx'; import ChangeCell from './ChangeCell.tsx'; const App = () => { const [connectionStarted, setConnectionStarted] = useState(false); - const [dataSource, setDataSource] = useState(null); + const [dataSource, setDataSource] = useState(null); useEffect(() => { const hubConnection = new HubConnectionBuilder() diff --git a/apps/demos/Demos/DataGrid/SignalRService/React/PriceCell.tsx b/apps/demos/Demos/DataGrid/SignalRService/React/PriceCell.tsx index 8a2f8025fcd2..2f347e6430b4 100644 --- a/apps/demos/Demos/DataGrid/SignalRService/React/PriceCell.tsx +++ b/apps/demos/Demos/DataGrid/SignalRService/React/PriceCell.tsx @@ -1,6 +1,7 @@ -import { type DataGridTypes } from 'devextreme-react/data-grid'; import React from 'react'; +import type { DataGridTypes } from 'devextreme-react/data-grid'; + const PriceCell = (cell: DataGridTypes.ColumnCellTemplateData) => (
0 ? 'inc' : 'dec' }> {cell.text} diff --git a/apps/demos/Demos/DataGrid/SignalRService/ReactJs/App.js b/apps/demos/Demos/DataGrid/SignalRService/ReactJs/App.js index 1473fc7290fe..fac794c12d35 100644 --- a/apps/demos/Demos/DataGrid/SignalRService/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/SignalRService/ReactJs/App.js @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; -import DataGrid, { Column } from 'devextreme-react/data-grid'; -import { CustomStore } from 'devextreme-react/common/data'; import { HubConnectionBuilder, HttpTransportType } from '@aspnet/signalr'; +import { CustomStore } from 'devextreme-react/common/data'; +import DataGrid, { Column } from 'devextreme-react/data-grid'; import PriceCell from './PriceCell.js'; import ChangeCell from './ChangeCell.js'; diff --git a/apps/demos/Demos/DataGrid/StatePersistence/React/App.tsx b/apps/demos/Demos/DataGrid/StatePersistence/React/App.tsx index 8dbf538df440..ef35f0de75ec 100644 --- a/apps/demos/Demos/DataGrid/StatePersistence/React/App.tsx +++ b/apps/demos/Demos/DataGrid/StatePersistence/React/App.tsx @@ -17,7 +17,7 @@ const App = () => { const dataGridRef = useRef(null); const onStateResetClick = useCallback(() => { - dataGridRef.current.instance().state(null); + dataGridRef.current?.instance().state(null); }, []); return ( diff --git a/apps/demos/Demos/DataGrid/StatePersistence/ReactJs/App.js b/apps/demos/Demos/DataGrid/StatePersistence/ReactJs/App.js index 10697b0a3dab..087d39275e30 100644 --- a/apps/demos/Demos/DataGrid/StatePersistence/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/StatePersistence/ReactJs/App.js @@ -16,7 +16,7 @@ const onRefreshClick = () => { const App = () => { const dataGridRef = useRef(null); const onStateResetClick = useCallback(() => { - dataGridRef.current.instance().state(null); + dataGridRef.current?.instance().state(null); }, []); return ( <> diff --git a/apps/demos/Demos/DataGrid/Toolbar/React/App.tsx b/apps/demos/Demos/DataGrid/Toolbar/React/App.tsx index 6609d73d0bbe..06d59d536146 100644 --- a/apps/demos/Demos/DataGrid/Toolbar/React/App.tsx +++ b/apps/demos/Demos/DataGrid/Toolbar/React/App.tsx @@ -29,8 +29,8 @@ const App = () => { const toggleGroupColumn = useCallback((e: SelectBoxTypes.ValueChangedEvent) => { const newGrouping = e.value; - dataGridRef.current.instance().clearGrouping(); - dataGridRef.current.instance().columnOption(newGrouping, 'groupIndex', 0); + dataGridRef.current?.instance().clearGrouping(); + dataGridRef.current?.instance().columnOption(newGrouping, 'groupIndex', 0); setTotalCount(getGroupCount(newGrouping)); setGroupColumn(newGrouping); @@ -50,7 +50,7 @@ const App = () => { icon: 'refresh', text: 'Refresh', onClick: () => { - dataGridRef.current.instance().refresh(); + dataGridRef.current?.instance().refresh(); }, }), []); diff --git a/apps/demos/Demos/DataGrid/Toolbar/ReactJs/App.js b/apps/demos/Demos/DataGrid/Toolbar/ReactJs/App.js index 20b0fd41ec1c..c1c8e283c46e 100644 --- a/apps/demos/Demos/DataGrid/Toolbar/ReactJs/App.js +++ b/apps/demos/Demos/DataGrid/Toolbar/ReactJs/App.js @@ -32,8 +32,8 @@ const App = () => { const dataGridRef = useRef(null); const toggleGroupColumn = useCallback((e) => { const newGrouping = e.value; - dataGridRef.current.instance().clearGrouping(); - dataGridRef.current.instance().columnOption(newGrouping, 'groupIndex', 0); + dataGridRef.current?.instance().clearGrouping(); + dataGridRef.current?.instance().columnOption(newGrouping, 'groupIndex', 0); setTotalCount(getGroupCount(newGrouping)); setGroupColumn(newGrouping); }, []); @@ -53,7 +53,7 @@ const App = () => { icon: 'refresh', text: 'Refresh', onClick: () => { - dataGridRef.current.instance().refresh(); + dataGridRef.current?.instance().refresh(); }, }), [], diff --git a/apps/demos/Demos/DataGrid/WebAPIService/React/App.tsx b/apps/demos/Demos/DataGrid/WebAPIService/React/App.tsx index ee25cafe10d9..7f2855dad4db 100644 --- a/apps/demos/Demos/DataGrid/WebAPIService/React/App.tsx +++ b/apps/demos/Demos/DataGrid/WebAPIService/React/App.tsx @@ -20,6 +20,7 @@ import { ValueFormat, } from 'devextreme-react/data-grid'; import { createStore } from 'devextreme-aspnet-data-nojquery'; + import MasterDetailGrid from './MasterDetailGrid.tsx'; const url = 'https://js.devexpress.com/Demos/NetCore/api/DataGridWebApi'; diff --git a/apps/demos/Demos/DataGrid/WebAPIService/React/MasterDetailGrid.tsx b/apps/demos/Demos/DataGrid/WebAPIService/React/MasterDetailGrid.tsx index 44fd320ad10a..03408c012b93 100644 --- a/apps/demos/Demos/DataGrid/WebAPIService/React/MasterDetailGrid.tsx +++ b/apps/demos/Demos/DataGrid/WebAPIService/React/MasterDetailGrid.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; +import type { DataSourceOptions } from 'devextreme-react/common/data'; import DataGrid from 'devextreme-react/data-grid'; import type { DataGridTypes } from 'devextreme-react/data-grid'; import { createStore } from 'devextreme-aspnet-data-nojquery'; @@ -17,7 +18,7 @@ const getMasterDetailGridDataSource = (id: number) => ({ }); const MasterDetailGrid = (props: DataGridTypes.MasterDetailTemplateData) => { - const [dataSource, setDataSource] = useState(null); + const [dataSource, setDataSource] = useState(null); useEffect(() => { const masterDetailDataSource = getMasterDetailGridDataSource(props.data.key); diff --git a/apps/demos/Demos/TreeList/ColumnChooser/React/App.tsx b/apps/demos/Demos/TreeList/ColumnChooser/React/App.tsx index e399ffdfacc3..e38b7184ea89 100644 --- a/apps/demos/Demos/TreeList/ColumnChooser/React/App.tsx +++ b/apps/demos/Demos/TreeList/ColumnChooser/React/App.tsx @@ -63,13 +63,15 @@ const App = () => { /> + enabled={!!searchEnabled} + editorOptions={searchEditorOptions} + /> + allowSelectAll={!!allowSelectAll} + selectByClick={!!selectByClick} + recursive={!!recursive} + />
@@ -127,7 +129,6 @@ const App = () => { />
-
); diff --git a/apps/demos/Demos/TreeList/ColumnChooser/ReactJs/App.js b/apps/demos/Demos/TreeList/ColumnChooser/ReactJs/App.js index c7e6988d6ff9..d2cab95e42bb 100644 --- a/apps/demos/Demos/TreeList/ColumnChooser/ReactJs/App.js +++ b/apps/demos/Demos/TreeList/ColumnChooser/ReactJs/App.js @@ -78,14 +78,14 @@ const App = () => { /> diff --git a/apps/demos/Demos/TreeList/CustomizeKeyboardNavigation/React/App.tsx b/apps/demos/Demos/TreeList/CustomizeKeyboardNavigation/React/App.tsx index 7234d85a1400..b3d37d496ca0 100644 --- a/apps/demos/Demos/TreeList/CustomizeKeyboardNavigation/React/App.tsx +++ b/apps/demos/Demos/TreeList/CustomizeKeyboardNavigation/React/App.tsx @@ -38,7 +38,7 @@ const App = () => { defaultExpandedRowKeys={expandedRowKeys} onFocusedCellChanging={onFocusedCellChanging}> { onFocusedCellChanging={onFocusedCellChanging} > diff --git a/apps/demos/Demos/TreeList/LocalReordering/React/App.tsx b/apps/demos/Demos/TreeList/LocalReordering/React/App.tsx index 4cb874e92dfc..f8ae896365d4 100644 --- a/apps/demos/Demos/TreeList/LocalReordering/React/App.tsx +++ b/apps/demos/Demos/TreeList/LocalReordering/React/App.tsx @@ -78,9 +78,9 @@ const App = () => { diff --git a/apps/demos/Demos/TreeList/LocalReordering/ReactJs/App.js b/apps/demos/Demos/TreeList/LocalReordering/ReactJs/App.js index d2f9b25603ae..823bc576dfd5 100644 --- a/apps/demos/Demos/TreeList/LocalReordering/ReactJs/App.js +++ b/apps/demos/Demos/TreeList/LocalReordering/ReactJs/App.js @@ -67,9 +67,9 @@ const App = () => {