Angular TreeList - editing

Configures editing.

Type:

Object

The UI component allows a user to edit data in several modes, which are detailed in the mode property. To define what editing operations a user can perform, specify the allowAdding, allowUpdating and allowDeleting properties. Before enabling an operation, make sure that your data source supports it.

NOTE
Editing does not work with hierarchical data sources out of the box, but you can use the code sample from this KB to implement it.

View Demo

See Also

allowAdding

Specifies whether a user can add new rows. It is called for each data row when defined as a function.

Type:

Boolean

|

Function

Function parameters:
options:

Object

Information about the current row.

Object structure:
Name Type Description
component

TreeList

The UI component's instance.

row

TreeList Row

The row's properties.

Return Value:

Boolean

true if the row can be added; otherwise false.

Default Value: false

In the following code, the Add button is added to rows whose status is not "Completed":

jQuery
JavaScript
$(function(){
    $("#treeListContainer").dxTreeList({
        // ...
        editing: {
            allowAdding: function(e) {
                return e.row.data.Task_Status !== "Completed";
            }
        }
    })
})
Angular
TypeScript
HTML
import { DxTreeListModule } from "devextreme-angular";
// ...
export class AppComponent {
    allowAdding: function(e) {
        return e.row.data.Task_Status !== "Completed";
    }
}
@NgModule({
    imports: [
        // ...
        DxTreeListModule
    ],
    // ...
})
<dx-tree-list ... >
    <dxo-editing
        [allowAdding]="allowAdding">
    </dxo-editing>
</dx-tree-list>
Vue
App.vue
<template>
    <DxTreeList ... >
        <DxEditing
            :allow-adding="allowAdding"
        />
    </DxTreeList>
</template>

<script>
import 'devextreme/dist/css/dx.light.css';

import DxTreeList, {
    DxEditing
} from 'devextreme-vue/tree-list';

export default {
    components: {
        DxTreeList,
        DxEditing
    },
    // ...
    methods: {
        allowAdding(e) {
            return e.row.data.Task_Status !== "Completed";
        }
    }
}
</script>
React
App.js
import React, { useCallback } from 'react';
import 'devextreme/dist/css/dx.light.css';

import TreeList, {
    Editing
} from 'devextreme-react/tree-list';

export default function App() {
    const allowAdding = useCallback((e) => {
        return e.row.data.Task_Status !== "Completed";
    }, []);

    return (
        <TreeList ... >
            <Editing
                allowAdding={allowAdding}
            />
        </TreeList>
    );
}
See Also

allowDeleting

Specifies whether a user can delete rows. It is called for each data row when defined as a function.

Type:

Boolean

|

Function

Function parameters:
options:

Object

Information about the current row.

Object structure:
Name Type Description
component

TreeList

The UI component's instance.

row

TreeList Row

The row's properties.

Return Value:

Boolean

true if the row can be deleted; otherwise false.

Default Value: false

allowUpdating

Specifies whether a user can update rows. It is called for each data row when defined as a function

Type:

Boolean

|

Function

Function parameters:
options:

Object

Information about the current row.

Object structure:
Name Type Description
component

TreeList

The UI component's instance.

row

TreeList Row

The row's properties.

Return Value:

Boolean

true if the row can be updated; otherwise false.

Default Value: false

changes CTP

Pending row changes.

Type:

Array<any>

Default Value: []
Raised Events: onOptionChanged

NOTE
This functionality is available as a community technology preview (CTP). Should you have any questions or suggestions prior to its official release, please create a new ticket in the DevExpress Support Center.

Each change is an object that can have the following fields:

  • type: String
    Data change type: "insert", "update", or "remove".

  • data: Object
    An object with updated row fields.

  • key: any
    The key of the row being updated or removed.

The changes array can be changed from the UI, with native JavaScript methods, or with UI component methods (addRow, editRow, editCell, deleteRow). However, objects with the "insert" type cannot be added with native JavaScript methods. We plan to add this functionality in future releases.

View Demo

confirmDelete

Specifies if confirmation is required when a user deletes a row.

Type:

Boolean

Default Value: true

editColumnName

The name of a column being edited. Applies only if editing.mode is "cell" or "batch".

Type:

String

Default Value: null
Raised Events: onOptionChanged

See Also

editRowKey

The key(s) of a row being edited.

Type: any
Default Value: null
Raised Events: onOptionChanged

Values for this property are taken from the data field(s) specified in the keyExpr property or the key property of the store.

View Demo

See Also

form

Configures the form. Used only if editing.mode is "form" or "popup".

Default form editors depend on the columns' configuration. If the generated form does not meet your requirements, and you need to reorganize form items or set other form properties, specify it in the form object. To link a form item with a grid column, assign identical values to the form.items.dataField and columns.dataField properties.

jQuery
index.js
$(function() {
    $("#treeListContainer").dxTreeList({
        // ...
        editing: {
            allowUpdating: true,
            mode: "form",
            form: {
                items: [{
                    itemType: "group",
                    caption: "Personal Data",
                    items: [
                        { dataField: "Prefix" },
                        { dataField: "Full_Name" },
                        { dataField: "Position" },
                        { dataField: "Duties", editorType: "dxTextArea" }
                    ]
                    // or simply
                    // items: ["Prefix", "Full_Name", "Position"]
                }, {
                    itemType: "group",
                    caption: "Contacts",
                    items: ["Email", "Skype"]
                }]
            }
        },
        columns: [ 
            { dataField: "Full_Name" }, 
            { dataField: "Prefix" },
            { dataField: "Position" },
            { dataField: "Duties" },
            { dataField: "Email" },
            { dataField: "Skype" } 
        ]
    });
});
Angular
app.component.html
app.component.ts
app.module.ts
<dx-tree-list ... >
    <dxo-editing
        [allowUpdating]="true"
        mode="form">
        <dxo-form>
            <dxi-item itemType="group" caption="Personal Data">
                <dxi-item dataField="Prefix"></dxi-item>
                <dxi-item dataField="Full_Name"></dxi-item>
                <dxi-item dataField="Position"></dxi-item>
                <dxi-item dataField="Duties" editorType="dxTextArea"></dxi-item>
            </dxi-item>
            <dxi-item itemType="group" caption="Contacts">
                <dxi-item dataField="Email"></dxi-item>
                <dxi-item dataField="Skype"></dxi-item>
            </dxi-item>
        </dxo-form>
    </dxo-editing>
    <dxi-column dataField="Full_Name"></dxi-column>
    <dxi-column dataField="Prefix"></dxi-column>
    <dxi-column dataField="Position"></dxi-column>
    <dxi-column dataField="Duties"></dxi-column>
    <dxi-column dataField="Email"></dxi-column>
    <dxi-column dataField="Skype"></dxi-column>
</dx-tree-list>
import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    // ...
}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

import { DxTreeListModule } from 'devextreme-angular';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        DxTreeListModule
    ],
    providers: [ ],
    bootstrap: [AppComponent]
})
export class AppModule { }
ASP.NET MVC Controls
Razor C#
@(Html.DevExtreme().TreeList()
    // ...
    .Editing(e => e
        .AllowUpdating(true)
        .Mode(GridEditMode.Form)
        .Form(f => f
            .Items(i => {
                i.AddGroup()
                    .Caption("Personal Data")
                    .Items(groupItems => {
                        groupItems.AddSimple().DataField("Prefix");
                        groupItems.AddSimple().DataField("Full_Name");
                        groupItems.AddSimple().DataField("Position");
                        groupItems.AddSimple().DataField("Duties")
                            .Editor(e => e.TextArea());
                    });
                i.AddGroup()
                    .Caption("Contacts")
                    .Items(groupItems => {
                        groupItems.AddSimple().DataField("Email");
                        groupItems.AddSimple().DataField("Skype");
                    });
            })
        )
    )
    .Columns(cols => {
        cols.Add().DataField("Full_Name");
        cols.Add().DataField("Prefix");
        cols.Add().DataField("Position");
        cols.Add().DataField("Duties");
        cols.Add().DataField("Email");
        cols.Add().DataField("Skype");
    })
)
Vue
App.vue
<template>
    <DxTreeList ... >
        <DxEditing
            :allow-updating="true"
            mode="form">
                <DxForm>
                    <DxItem itemType="group" caption="Personal Data">
                        <DxItem dataField="Prefix" />
                        <DxItem dataField="Full_Name" />
                        <DxItem dataField="Position" />
                        <DxItem dataField="Duties" editorType="dxTextArea" />
                    </DxItem>
                    <DxItem itemType="group" caption="Contacts">
                        <DxItem dataField="Email" />
                        <DxItem dataField="Skype" />
                    </DxItem>
                </DxForm>
        </DxEditing>
        <DxColumn data-field="Full_Name" />
        <DxColumn data-field="Prefix" />
        <DxColumn data-field="Position" />
        <DxColumn data-field="Duties" />
        <DxColumn data-field="Email" />
        <DxColumn data-field="Skype" />
    </DxTreeList>
</template>

<script>
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import DxTreeList, { DxColumn, DxEditing, DxForm } from 'devextreme-vue/tree-list';
import { DxItem } from 'devextreme-vue/form';

export default {
    components: {
        DxTreeList,
        DxEditing,
        DxForm,
        DxItem
    },
    data() {
        return {
            // ...
        }
    }
}
</script>
React
App.js
import React from 'react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import TreeList, {
    Column,
    Editing,
    Form
} from 'devextreme-react/tree-list';
import { Item } from 'devextreme-react/form';

class App extends React.Component {
    render() {
        return (
            <TreeList ... >
                <Editing
                    mode="form"
                    allowUpdating={true}>
                    <Form>
                        <Item itemType="group" caption="Personal Data">
                            <Item dataField="Prefix" />
                            <Item dataField="Full_Name" />
                            <Item dataField="Position" />
                            <Item dataField="Duties" editorType="dxTextArea" />
                        </Item>
                        <Item itemType="group" caption="Contacts">
                            <Item dataField="Email" />
                            <Item dataField="Skype" />
                        </Item>
                    </Form>
                </Editing>
                <Column dataField="Prefix" />
                <Column dataField="Full_Name" />
                <Column dataField="Position" />
                <Column dataField="Duties" />
                <Column dataField="Email" />
                <Column dataField="Skype" />
            </TreeList>
        );
    }
}
export default App;

Do not specify the following properties in the form object:

Also, the colCount property defaults to 2, but it can be redefined.

NOTE
In Angular and Vue, the nested component that configures the form property does not support event bindings and two-way property bindings.

If you need to customize an individual form item, use the formItem object.

View Demo

See Also

mode

Specifies how a user edits data.

Type:

String

Default Value: 'row'
Accepted Values: 'batch' | 'cell' | 'row' | 'form' | 'popup'

The following list points out the differences in editing modes:

  • Row
    A user edits one row at a time. The UI component saves changes when the row leaves the editing state.

    View Demo

  • Batch
    A user edits data cell by cell. The UI component does not save changes until a user clicks the global "Save" button.

    View Demo

  • Cell
    Differs from the batch mode in that the UI component saves changes when the cell leaves the editing state.

    View Demo

  • Form
    On entering the editing state, a row becomes a form with editable fields. The UI component saves changes after a user clicks the "Save" button.

    View Demo

  • Popup
    Differs from the form mode in that the form with editable fields is placed in a popup window.

    View Demo

popup

Configures the popup. Used only if editing.mode is "popup".

You can specify any Popup property in this object, but note that the following properties override the TreeList's internal logic:

The popup always contains a form whose items are used for editing. Use the form property to customize the form's items.

NOTE
In Angular and Vue, the nested component that configures the popup property does not support event bindings and two-way property bindings.

View Demo

refreshMode

Specifies operations that are performed after saving changes.

Type:

String

Default Value: 'full'
Accepted Values: 'full' | 'reshape' | 'repaint'

The following table shows the operations that are performed after saving changes in different modes:

Mode Data reloading Data processing operations1 UI component repaint2
full + + +
reshape - 3 +
(on the client)
+
repaint - - +
  1. Data processing operations include paging, filtering, sorting, grouping, and summary calculation (in the DataGrid).
  2. Set repaintChangesOnly to true to repaint only elements whose data changed.
  3. Set remoteOperations to false and cacheEnabled to true to avoid data reloading.

View Demo

NOTE

When the refreshMode is "reshape" or "repaint", the server should respond to the insert or update request by sending back the data item saved in the database. See the DataGridWebApiController tab in the CRUD Operations demo for an example of the server-side implementation. The InsertOrder and UpdateOrder actions illustrate this case.

selectTextOnEditStart

Specifies whether to select text in a cell when a user starts editing.

Type:

Boolean

Default Value: false

startEditAction

Specifies whether a single or double click should switch a cell to the editing state. Applies if editing.mode is "cell" or "batch".

Type:

String

Default Value: 'click'
Accepted Values: 'click' | 'dblClick'

View Demo

See Also

texts

Contains properties that specify texts for editing-related UI elements.

Type:

Object

The following code shows the editing.texts declaration syntax:

jQuery
index.js
$(function() {
    $("#treeListContainer").dxTreeList({
        // ...
        editing: {
            // ...
            texts: {
                deleteRow: "Remove"
            }
        }
    });
});
Angular
app.component.html
app.component.ts
app.module.ts
<dx-tree-list ... >
    <dxo-editing ... >
        <dxo-texts
            deleteRow="Remove">
        </dxo-texts>
    </dxo-editing>
</dx-tree-list>
import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    // ...
}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

import { DxTreeListModule } from 'devextreme-angular';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        DxTreeListModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }
Vue
App.vue
<template>
    <DxTreeList ... >
        <DxEditing ... >
            <DxTexts
                delete-row="Remove"
            />
        </DxEditing>
    </DxTreeList> 
</template>

<script>
import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import DxTreeList, {
    DxEditing,
    DxTexts
} from 'devextreme-vue/tree-list';

export default {
    components: {
        DxTreeList,
        DxEditing,
        DxTexts
    },
    data() {
        // ...
    }
}
</script>
React
App.js
import React from 'react';

import 'devextreme/dist/css/dx.common.css';
import 'devextreme/dist/css/dx.light.css';

import TreeList, {
    Editing,
    Texts
} from 'devextreme-react/tree-list';

class App extends React.Component {
    render() {
        return (
            <TreeList ... >
                <Editing>
                    <Texts
                        deleteRow="Remove"
                    />
                </Editing>
            </TreeList>
        );
    }
}
export default App;

useIcons

Specifies whether the edit column uses icons instead of links.

Type:

Boolean

Default Value: false, true (Material)