All docs
V19.1
19.2 (CTP)
19.1
18.2
The page you are viewing does not exist in version 18.2. This link will take you to the root page.
18.1
The page you are viewing does not exist in version 18.1. This link will take you to the root page.
17.2
The page you are viewing does not exist in version 17.2. This link will take you to the root page.
17.1
The page you are viewing does not exist in version 17.1. This link will take you to the root page.
16.2
The page you are viewing does not exist in version 16.2. This link will take you to the root page.

Component Configuration Syntax

Static String Option Value

HTML
<dx-button text="Simple button" />

Static Non-String Option Value

HTML
<dx-button
    :disabled="false"
    :width="50"
/>

Options of the Object Type

Use nested configuration components. In the following example, we configure the Chart widget's tooltip option:

App.vue
<template>
    <dx-chart>
        <dx-tooltip
            :enabled="true"
            format="thousands"
        />
    </dx-chart>
</template>

<script>
import DxChart, {
    DxTooltip
} from 'devextreme-vue/chart';

export default {
    components: {
        DxChart,
        DxTooltip
    }
}
</script>

Certain object type options are not implemented as nested configuration components because they depend on other options' values and cannot be typed (editorOptions in the DataGrid, editorOptions in the Form, widget options in the Toolbar). These options should be specified with an object. We recommend that you declare the object outside the configuration component to prevent unnecessary re-rendering.

App.vue
<template>
    <dx-data-grid>
        <dx-column
            :editor-options="columnEditorOptions"
        />
    </dx-data-grid>
</template>

<script>
import DxDataGrid, {
    DxColumn
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn
    },
    data() {
        return {
            columnEditorOptions: { width: 100 }
        }
    }
}
</script>

Collections

Use nested configuration components. The following example shows how to configure the DataGrid widget's columns option:

App.vue
<template>
    <dx-data-grid>
        <dx-column
            data-field="firstName"
            caption="Name"
        />
        <dx-column
            data-field="lastName"
            caption="Surname"
        />
    </dx-data-grid>
</template>

<script>
import DxDataGrid, {
    DxColumn
} from 'devextreme-vue/data-grid';

export default {
    components: {
        DxDataGrid,
        DxColumn
    }
}
</script>

DevExtreme collection widgets also support the DxItem component. It allows you to declare collection items in the widget markup. A dx-item element can contain custom markup and have attributes that control parts of item appearance, such as badge in the following code. The attributes are described in the Default Item Template section of each collection widget. Ensure to specify that an item's content is in the default slot.

App.vue
<template>
    <dx-list>
        <dx-item #default>Orange</dx-item>
        <dx-item #default badge="New">White</dx-item>
        <dx-item #default>Black</dx-item>
    </dx-list>
</template>

<script>
import DxList, {
    DxItem
} from 'devextreme-vue/list';

export default {
    components: {
        DxList,
        DxItem
    }
}
</script>

dx-item also supports structural directives provided by Vue, such as v-for:

App.vue
<template>
    <dx-list>
        <dx-item #default><h1>Available items</h1></dx-item>
        <dx-item
            v-for="item in listItems"
            :key="item.text"
            :badge="item.badge"
            #default>
            {{ item.text }}
        </dx-item>
    </dx-list>
</template>

<script>
import DxList, {
    DxItem
} from 'devextreme-vue/list';

export default {
    components: {
        DxList,
        DxItem
    },
    data() {
        return {
            listItems: [{
                text: 'Cars',
                badge: '12'
            }, {
                text: 'Bikes',
                badge: '5'
            }]
        }
    }
}
</script>

Event Handling

App.vue
<template>
    <dx-button
        text="OK"
        @click="okClicked"
    />
</template>

<script>
import DxButton from 'devextreme-vue/button';
import notify from 'devextreme/ui/notify';

export default {
    components: {
        DxButton
    },
    methods: {
        okClicked: function(e) {
            notify('The OK button was clicked')
        }
    }
}
</script>

Callback Functions

App.vue
<template>
    <dx-vector-map>
        <dx-layer :customize="customizeLayers" />
    </dx-vector-map>
</template>

<script>
import DxVectorMap, {
    DxLayer
} from 'devextreme-vue/vector-map';

export default {
    components: {
        DxVectorMap,
        DxLayer
    },
    methods: {
        customizeLayers(elements) {
            // ...
        }
    }
}
</script>

One-Way Option Binding

Changes in the bindingProperty are propagated to the TextBox's value, but not vice versa. : before value is a shorthand for the v-bind directive.

App.vue
<template>
    <dx-text-box :value="bindingProperty" />
</template>

<script>
import DxTextBox from 'devextreme-vue/text-box';

export default {
    components: {
        DxTextBox
    },
    data() {
        return {
            bindingProperty: 'Some value'
        }
    }
}
</script>

Two-Way Option Binding

Changes in the bindingProperty are propagated to the TextBox's value and vice versa. The sync modifier provides two-way binding.

App.vue
<template>
    <dx-text-box :value.sync="bindingProperty" />
</template>

<script>
import DxTextBox from 'devextreme-vue/text-box';

export default {
    components: {
        DxTextBox
    },
    data() {
        return {
            bindingProperty: 'Some value'
        }
    }
}
</script>

Declare Content in the Markup

The following widgets allow you to declare their content directly in the markup:

The following is an example with ScrollView:

App.vue
<template>
    <dx-scroll-view>
        <div>Some scrollable content</div>
    </dx-scroll-view>
</template>

<script>
import DxScrollView from 'devextreme-vue/scroll-view';

export default {
    components: {
        DxScrollView
    }
}
</script>

Templates

Templates allow you to customize widget elements. DevExtreme templates make use of the named slots functionality provided by Vue.

In the following code, an itemTemplate called list-item and a groupTemplate called list-group customize items and groups in the List widget. The data slot prop exposes the item or group data object; the index slot prop gives access to the item index.

App.vue
<template>
    <dx-list
        :items="groupedItems"
        :grouped="true"
        item-template="list-item"
        group-template="list-group">
        <template #list-item="{ data, index }">
            {{ index }} - {{ data.itemProperty }}
        </template>
        <template #list-group="{ data }">
            {{ data.groupProperty }}
        </template>
    </dx-list>
</template>

<script>
import DxList from 'devextreme-vue/list';

export default {
    components: {
        DxList
    },
    data() {
        return {
            groupedItems: [ /* ... */ ]
        }
    }
}
</script>
IMPORTANT
A <template> should not contain more than one root element.

Refer to the common Custom Templates article for more information.

Call Methods

To call widget methods, you need the widget instance. Define the target component's key in the ref attribute. Then, pass the key to the $refs property to get the component. The widget instance is stored in the component's instance field:

App.vue
<template>
    <div>
        <dx-text-box :ref="textBoxRefKey" />
        <dx-button text="Focus TextBox" @click="focusTextBox" />
    </div>
</template>

<script>
import DxButton from 'devextreme-vue/button';
import DxTextBox from 'devextreme-vue/text-box';

const textBoxRefKey = "my-text-box";

export default {
    components: {
        DxTextBox,
        DxButton
    },
    data: function() {
        return {
            textBoxRefKey
        };
    },
    methods: {
        focusTextBox: function() {
            this.textBox.focus();
        }
    },
    computed: {
        textBox: function() {
            return this.$refs[textBoxRefKey].instance;
        }
    }
};
</script>

Alternatively, you can save the widget instance in a component property once the widget is initialized:

App.vue
<template>
    <div>
        <dx-data-grid ...
            @initialized="saveGridInstance">
        </dx-data-grid>
        <dx-button text="Refresh data" @click="refresh"/>
    </div>
</template>

<script>
import DxDataGrid from 'devextreme-vue/data-grid';
import DxButton from 'devextreme-vue/button';

export default {
    components: {
        DxDataGrid,
        DxButton
    },
    data: function() {
        return {
            dataGridInstance: null
        };
    },
    methods: {
        saveGridInstance: function(e) {
            this.dataGridInstance = e.component;
        },
        refresh: function() {
            this.dataGridInstance.refresh();
        }
    }
};
</script>

Get a Widget Instance

For information on this matter, refer to Call Methods.

Data Layer

DevExtreme Data Layer is a set of components for working with data. Refer to the Data Layer API reference for code examples.

DevExtreme Validation Features

In the following example, two textboxes are placed in a validation group that is validated on a button click. Each textbox has a set of validation rules. The validation result is displayed under the textboxes in a validation summary.

App.vue
<template>
    <dx-validation-group>
        <dx-text-box :value.sync="email">
            <dx-validator>
                <dx-required-rule message="Email is required" />
                <dx-email-rule message="Email is invalid" />
            </dx-validator>
        </dx-text-box>

        <dx-text-box :value.sync="password" mode="password">
            <dx-validator>
                <dx-required-rule message="Password is required" />
            </dx-validator>
        </dx-text-box>

        <dx-validation-summary />

        <dx-button @click="validate" text="Submit" />
    </dx-validation-group>
</template>

<script>
import DxTextBox from 'devextreme-vue/text-box';
import DxValidator, {
    DxRequiredRule,
    DxEmailRule
} from 'devextreme-vue/validator';
import DxValidationGroup from 'devextreme-vue/validation-group';
import DxValidationSummary from 'devextreme-vue/validation-summary';
import DxButton from 'devextreme-vue/button';

export default {
    components: {
        DxTextBox,
        DxValidator,
        DxRequiredRule,
        DxEmailRule,
        DxValidationGroup,
        DxValidationSummary,
        DxButton
    },
    data() {
        return {
            email: undefined,
            password: undefined
        }
    },
    methods: {
        validate(params) {
            let result = params.validationGroup.validate();
            if (result.isValid) {
                // the values are valid
                // submit and reset them
                // params.validationGroup.reset();
                console.log(result);
            }
        }
    }
}
</script>

Refer to the Data Validation article for more information.

Vue Form Input Bindings Support

DevExtreme editors support the v-model directive that creates two-way binding on the editor's value.

App.vue
<template>
    <dx-text-box v-model="bindingProperty" />
</template>

<script>
import DxTextBox from 'devextreme-vue/text-box';

export default {
    components: {
        DxTextBox
    },
    data() {
        return {
            bindingProperty: 'Some value'
        }
    }
}
</script>

Alternatively, you can use the sync modifier.