Using Unions Instead of Base Classes
Inheritance is a part of internal implementation. You should not rely on the knowledge of relationships between base classes and their descendants. For generalization, use a union to define your own type.
For example, if you need a type for properties of multiple editor components, define the following union:
jQuery
type EditorProps = DxTextAreaTypes.Properties | DxTextBoxTypes.Properties | DxAutocompleteTypes.Properties | DxLookupTypes.Properties;
Angular
type EditorProps = DxTextAreaTypes.Properties | DxTextBoxTypes.Properties | DxAutocompleteTypes.Properties | DxLookupTypes.Properties;
Vue
type EditorProps = DxTextAreaTypes.Properties | DxTextBoxTypes.Properties | DxAutocompleteTypes.Properties | DxLookupTypes.Properties;
React
type EditorProps = TextAreaTypes.Properties | TextBoxTypes.Properties | AutocompleteTypes.Properties | LookupTypes.Properties;
Generic Parameters
Some types are generic. This is mostly the case for data-aware component types, such as DataGrid:
Angular
import { Component, ViewChild } from '@angular/core';
import { DxDataGridComponent, DxDataGridTypes } from 'devextreme-angular/ui/data-grid';
import { Employee } from './data';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
@ViewChild(DxDataGridComponent) dataGrid!: DxDataGridComponent<Employee, number>;
onEditorPreparing(e: DxDataGridTypes.EditorPreparingEvent<Employee, number>) {
if (e.dataField === 'LastName' && e.parentType === 'dataRow') {
e.editorOptions.disabled = e.row?.data && e.row?.data.FirstName === '';
}
}
onButtonClick() {
const keys: number[] = this.dataGrid.instance.getSelectedRowKeys();
}
}
<dx-button
text="Get Selected Keys"
(onClick)="onButtonClick()"
>
</dx-button>
<dx-data-grid ...
(onEditorPreparing)="onEditorPreparing($event)"
>
</dx-data-grid>Vue
<template>
<div>
<DxButton
text="Disable DataGrid"
@click="onButtonClick"
/>
<DxDataGrid
:data-source="dataSource"
ref="dataGridRef"
@editor-preparing="onEditorPreparing"
>
</DxDataGrid>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { DxDataGrid } from "devextreme-vue/data-grid";
import { DxButton } from "devextreme-vue/button";
import { type DxDataGridTypes } from "devextreme-vue/data-grid";
import type dxDataGrid from 'devextreme/ui/data_grid';
import { type Employee } from '../data';
const dataGridRef = ref<DxDataGrid>();
function onButtonClick() {
const dataGridInstance: dxDataGrid<Employee, number> = dataGridRef.value?.instance!;
dataGridInstance.option("disabled", true);
}
function onEditorPreparing(e: DxDataGridTypes.EditorPreparingEvent<Employee, number>) {
if (e.dataField === 'LastName' && e.parentType === 'dataRow') {
e.editorOptions.disabled = e.row?.data?.FirstName === '';
}
}
</script>React
import { useRef } from 'react';
import { type Employee, employees as dataSource } from './data';
import DataGrid, { type DataGridTypes, DataGridRef } from 'devextreme-react/data-grid';
import Button from 'devextreme-react/button';
function onEditorPreparing(e: DataGridTypes.EditorPreparingEvent<Employee, number>) {
if (e.dataField === 'LastName' && e.parentType === 'dataRow') {
e.editorOptions.disabled = e.row?.data && e.row?.data.FirstName === '';
}
}
function App() {
const dataGrid = useRef<DataGridRef<Employee, number>>(null);
const onButtonClick = () => {
const dataGridInstance = dataGrid.current!.instance();
dataGridInstance.option("disabled", true);
}
return (
<>
<Button
text={"Disable DataGrid"}
onClick={onButtonClick}
/>
<DataGrid<Employee, number>
ref={dataGrid}
onEditorPreparing={onEditorPreparing}
dataSource={dataSource}>
</DataGrid>
</>
);
}
export default App;Configuration Components
DevExtreme Angular allows you to configure UI component settings using configuration components. These start with the dxo and dxi prefixes. DevExtreme includes two types of configuration components:
- Named configuration components
Components such asdxo-data-grid-popupare specific to their parent UI components. The name of the parent UI component is included after thedxoordxiprefix. - Generic configuration components
You can use components such asdxo-popupto configure any supported UI component.
We recommend using named configuration components that are specific to the UI component you need to configure. Named configuration components are strictly typed in TypeScript and contain only properties related to their top-level UI components.
<!-- Stepper item example -->
<dx-stepper ... >
<dxi-stepper-item
icon="docfile"
label="Upload Supporting Files"
[optional]="true"
></dxi-stepper-item>
</dx-stepper>
<!-- CardView editing example -->
<dx-card-view ... >
<dxo-card-view-editing
[allowAdding]="true"
[allowDeleting]="true"
[allowUpdating]="true"
></dxo-card-view-editing>
</dx-card-view>You can implement named configuration components for nested DevExtreme components, such as the editing Popup within the DataGrid. To do this, specify top-level component names. For instance, to configure Popup animation settings within a DataGrid, implement the <dxo-data-grid-animation> configuration component:
<dx-data-grid ... >
<dxo-editing mode="popup" />
<dxo-data-grid-popup>
<dxo-data-grid-animation
[show]="showOptions"
[hide]="hideOptions"
></dxo-data-grid-animation>
</dxo-data-grid-popup>
</dx-data-grid>Specify Popup and Popover toolbar items as <...-toolbar-item> (both for nested and non-nested controls), and other component toolbar items as <...-item>:
<!-- Toolbar item in a DataGrid editing Popup -->
<dx-data-grid ... >
<dxo-editing mode="popup" />
<dxo-data-grid-popup>
<dxi-data-grid-toolbar-item
widget="dxButton"
location="after"
[options]="buttonOptions"
></dxi-data-grid-toolbar-item>
</dxo-data-grid-popup>
</dx-data-grid>
<!-- Toolbar item in a Scheduler -->
<dx-scheduler ... >
<dxo-scheduler-toolbar>
<dxi-scheduler-item name="dateNavigator"></dxi-scheduler-item>
</dxo-scheduler-toolbar>
</dx-scheduler>If you have technical questions, please create a support ticket in the DevExpress Support Center.