Your search did not match any results.
Data Grid

CRUD Operations

Documentation

This demo shows how to implement remote CRUD operations in the CustomStore. You can view the server implementation under the DataGridWebApiController tab in the ASP.NET MVC version of this demo. The requests sent to the server are displayed under the DataGrid.

After a cell is edited, the DataGrid can behave differently depending on the selected refresh mode: reload data from the server (the refreshMode is full), reapply data processing operations (reshape), or merely rerender the changed cells (repaint).

Copy to CodeSandBox
Apply
Reset
<template> <div> <dx-data-grid id="grid" :show-borders="true" :data-source="ordersData" :repaint-changes-only="true" > <dx-editing :refresh-mode="refreshMode" :allow-adding="true" :allow-updating="true" :allow-removing="true" mode="cell" /> <dx-column data-field="CustomerID" caption="Customer" > <dx-lookup :data-source="customersData" value-expr="Value" display-expr="Text" /> </dx-column> <dx-column data-field="OrderDate" data-type="date" /> <dx-column data-field="Freight"/> <dx-column data-field="ShipCountry"/> <dx-column data-field="ShipVia" caption="Shipping Company" data-type="number" > <dx-lookup :data-source="shippersData" value-expr="Value" display-expr="Text" /> </dx-column> <dx-scrolling mode="virtual"/> <dx-editing :refresh-mode="refreshMode" :allow-adding="true" :allow-updating="true" :allow-deleting="true" mode="cell" /> <dx-summary> <dx-total-item column="CustomerID" summary-type="count" /> <dx-total-item column="Freight" summary-type="sum" value-format="#0.00" /> </dx-summary> </dx-data-grid> <div class="options"> <div class="caption">Options</div> <div class="option"> <span>Refresh Mode:</span> <dx-select-box v-model="refreshMode" :items="refreshModes" /> </div> <div id="requests"> <div> <div class="caption">Network Requests</div> <dx-button id="clear" text="Clear" @click="clearRequests()" /> </div> <ul> <li v-for="(request, index) in requests" :key="index" >{{ request }}</li> </ul> </div> </div> </div> </template> <script> import { DxDataGrid, DxColumn, DxEditing, DxScrolling, DxSummary, DxLookup, DxTotalItem } from 'devextreme-vue/data-grid'; import { DxButton } from 'devextreme-vue/button'; import { DxSelectBox } from 'devextreme-vue/select-box'; import CustomStore from 'devextreme/data/custom_store'; import { formatDate } from 'devextreme/localization'; import 'whatwg-fetch'; const URL = 'https://js.devexpress.com/Demos/Mvc/api/DataGridWebApi'; export default { components: { DxDataGrid, DxColumn, DxEditing, DxScrolling, DxSummary, DxLookup, DxTotalItem, DxButton, DxSelectBox }, data() { return { ordersData: new CustomStore({ key: 'OrderID', load: () => this.sendRequest(`${URL}/Orders`), insert: (values) => this.sendRequest(`${URL}/InsertOrder`, 'POST', { values: JSON.stringify(values) }), update: (key, values) => this.sendRequest(`${URL}/UpdateOrder`, 'PUT', { key: key, values: JSON.stringify(values) }), remove: (key) => this.sendRequest(`${URL}/DeleteOrder`, 'DELETE', { key: key }) }), customersData: new CustomStore({ key: 'Value', loadMode: 'raw', load: () => this.sendRequest(`${URL}/CustomersLookup`) }), shippersData: new CustomStore({ key: 'Value', loadMode: 'raw', load: () => this.sendRequest(`${URL}/ShippersLookup`) }), requests: [], refreshMode: 'reshape', refreshModes: ['full', 'reshape', 'repaint'] }; }, methods: { sendRequest(url, method, data) { method = method || 'GET'; data = data || {}; this.logRequest(method, url, data); const params = Object.keys(data).map((key) => { return `${encodeURIComponent(key) }=${ encodeURIComponent(data[key])}`; }).join('&'); if(method === 'GET') { return fetch(url, { method: method, credentials: 'include' }).then(result => result.json().then(json => { if(result.ok) return json.data; throw json.Message; })); } return fetch(url, { method: method, body: params, headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' }, credentials: 'include' }).then(result => { if(result.ok) { return result.text().then(text => text && JSON.parse(text)); } else { return result.json().then(json => { throw json.Message; }); } }); }, logRequest(method, url, data) { var args = Object.keys(data || {}).map(function(key) { return `${key }=${ data[key]}`; }).join(' '); var time = formatDate(new Date(), 'HH:mm:ss'); this.requests.unshift([time, method, url.slice(URL.length), args].join(' ')); }, clearRequests() { this.requests = []; } }, }; </script> <style scoped> #grid { height: 440px; } .options { padding: 20px; margin-top: 20px; background-color: rgba(191, 191, 191, 0.15); } .caption { margin-bottom: 10px; font-weight: 500; font-size: 18px; } .option { margin-bottom: 10px; } .option > span { position: relative; top: 2px; margin-right: 10px; } .option > .dx-widget { display: inline-block; vertical-align: middle; } #requests .caption { float: left; padding-top: 7px; } #requests > div { padding-bottom: 5px; } #requests > div:after { content: ""; display: table; clear: both; } #requests #clear { float: right; } #requests ul { list-style: none; max-height: 100px; overflow: auto; margin: 0; } #requests ul li { padding: 7px 0; border-bottom: 1px solid #dddddd; } #requests ul li:last-child { border-bottom: none; } </style>
import Vue from 'vue'; import App from './App.vue'; new Vue({ el: '#app', components: { App }, template: '<App/>' });
<!DOCTYPE html> <html> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/18.2.7/css/dx.common.css" /> <link rel="dx-theme" data-theme="generic.light" href="https://cdn3.devexpress.com/jslib/18.2.7/css/dx.light.css" /> <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import('./index.js'); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"/> </div> </body> </html>
System.config({ transpiler: 'plugin-babel', paths: { 'npm:': 'https://unpkg.com/' }, map: { vue: 'npm:vue@2.5.16/dist/vue.esm.browser.js', 'vue-loader': 'npm:systemjs-vue-browser@latest/index.js', 'devextreme': 'npm:devextreme@18.2', 'devextreme-vue': 'npm:devextreme-vue@18.2', jszip: 'npm:jszip@3.1.3/dist/jszip.min.js', 'quill': 'npm:quill@1.3.6/dist/quill.js', 'whatwg-fetch': 'npm:whatwg-fetch@2.0.4/fetch.js', 'plugin-babel': 'npm:systemjs-plugin-babel@0/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel@0/systemjs-babel-browser.js' }, meta: { '*.vue': { loader: 'vue-loader' }, 'devextreme-aspnet-data-nojquery': { 'esModule': true } }, packages: { 'devextreme-vue': { main: 'index.js' }, 'devextreme': { defaultExtension: 'js' } }, babelOptions: { sourceMaps: false, stage0: true } });