DevExtreme Angular - Best Practices

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:

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
app.component.ts
app.component.html
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
App.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 = dataGridRef.value?.instance! as dxDataGrid<Employee, number>;
    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
App.tsx
import { useRef } from 'react';
import { Employee, employees as dataSource } from './data';
import DataGrid, { 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 as dxo-data-grid-popup are specific to their parent UI components. The name of the parent UI component is included after the dxo or dxi prefix.
  • Generic configuration components
    You can use components such as dxo-popup to 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 parent UI components.

app.component.html
<dx-data-grid ... >
    <dxo-editing mode="popup" />
    <dxo-data-grid-popup>
        <dxi-data-grid-toolbar-item
            widget="dxButton"
            location="after"
            [options]="{
                text: 'Refresh',
                onClick: refresh
            }">
        </dxi-data-grid-toolbar-item>
    </dxo-data-grid-popup>
</dx-data-grid>