DevExtreme Angular - Data Binding
All DevExtreme controls that operate with data collections have the DataSource()
method. Unlike other control methods, DataSource()
do not have a direct counterpart in the DevExtreme JavaScript API, although its purpose resembles that of the Stores in the DevExtreme Data Layer. The DataSource()
method configures data access for a control. The following topics describe in details how to use this method for accessing data from different sources.
Besides DataSource()
, data-bound controls (except PivotGrid) have the DataSourceOptions()
method. It exposes a builder that configures initial sorting, filtering, grouping, and other data shaping operations. The builder's methods do have JavaScript API counterparts, which are described in this section.
See Also
Static Collections
A static collection will be serialized to JSON and embedded into a control's configuration.
@(Html.DevExtreme().SelectBox() .DataSource(new[] { "red", "green", "blue" }) )
@(Html.DevExtreme().SelectBox() _ .DataSource({ "red", "green", "blue" }) )
ASP.NET MVC and Web API Controllers
Access to MVC controllers in an MVC 5 and .NET Core MVC app is configured using the Mvc()
method the DataSource()
's lambda parameter exposes. The following example shows the DataGrid control accessing a GridDataController
whose actions (GetOrders
, InsertOrder
, UpdateOrder
, and DeleteOrder
) implement CRUD operations:
@(Html.DevExtreme().DataGrid() .DataSource(ds => ds .Mvc() .Controller("GridData") .Key("OrderID") .LoadAction("GetOrders") .InsertAction("InsertOrder") .UpdateAction("UpdateOrder") .DeleteAction("DeleteOrder") ) )
@(Html.DevExtreme().DataGrid() _ .DataSource(Function(ds) Return ds.Mvc() _ .Controller("GridData") _ .Key("OrderID") _ .LoadAction("GetOrders") _ .InsertAction("InsertOrder") _ .UpdateAction("UpdateOrder") _ .DeleteAction("DeleteOrder") End Function) )
The code below details the GridDataController
. CRUD operations are performed on the Northwind database's "Orders" collection. Note the use of DevExtreme.AspNet.Data, a library that facilitates writing a controller for DevExtreme ASP.NET MVC Controls.
MVC 5 Controller
using System; using System.Linq; using System.Net; using System.Web.Mvc; using DevExtreme.AspNet.Data; using DevExtreme.AspNet.Mvc; using Newtonsoft.Json; using ProjectName.Models; namespace ProjectName.Controllers { public class GridDataController : Controller { NorthwindContext _nwind = new NorthwindContext(); const string ValidationErrorMessage = "The record cannot be saved due to a validation error"; // Fetching items from the "Orders" collection public ActionResult GetOrders(DataSourceLoadOptions loadOptions) { var result = DataSourceLoader.Load(_nwind.Orders, loadOptions); var resultJson = JsonConvert.SerializeObject(result); return Content(resultJson, "application/json"); } // Inserting a new item into the "Orders" collection public ActionResult InsertOrder(string values) { var newOrder = new Order(); // Creating a new item JsonConvert.PopulateObject(values, newOrder); // Populating the item with the values if (!TryValidateModel(newOrder)) // Validating the item return new HttpStatusCodeResult(HttpStatusCode.BadRequest, ValidationErrorMessage); _nwind.Orders.Add(newOrder); // Adding the item to the database _nwind.SaveChanges(); return new HttpStatusCodeResult(HttpStatusCode.OK); } // Updating an item in the "Orders" collection public ActionResult UpdateOrder(int key, string values) { var order = _nwind.Orders.First(o => o.OrderID == key); // Finding the item to be updated by key JsonConvert.PopulateObject(values, order); // Populating the found item with the changed values if (!TryValidateModel(order)) // Validating the updated item return new HttpStatusCodeResult(HttpStatusCode.BadRequest, ValidationErrorMessage); _nwind.SaveChanges(); return new HttpStatusCodeResult(HttpStatusCode.Created); } // Removing an item from the "Orders" collection public void DeleteOrder(int key) { var order = _nwind.Orders.First(o => o.OrderID == key); // Finding the item to be removed by key _nwind.Orders.Remove(order); // Removing the found item _nwind.SaveChanges(); } } }
Imports System.Linq Imports System.Net Imports DevExtreme.AspNet.Data Imports DevExtreme.AspNet.Mvc Imports Newtonsoft.Json Imports ProjectName.Models Namespace Controllers Public Class OrdersController Inherits Controller Dim _nwind As New NorthwindContext() Const ValidationErrorMessage As String = "The record cannot be saved due to a validation error" ' Fetching items from the "Orders" collection Public Function GetOrders(ByVal loadOptions As DataSourceLoadOptions) As ActionResult Dim result = DataSourceLoader.Load(_nwind.Orders, loadOptions); Dim resultJson = JsonConvert.SerializeObject(result); Return Content(resultJson, "application/json") End Function ' Inserting a new item into the "Orders" collection Public Function InsertOrder(ByVal values As String) As ActionResult Dim newOrder As New Order() ' Creating the a item JsonConvert.PopulateObject(values, newOrder) ' Populating the item with values If TryValidateModel(newOrder) = False Then ' Validating the item Return New HttpStatusCodeResult(HttpStatusCode.BadRequest, ValidationErrorMessage) End If _nwind.Orders.Add(newOrder) ' Adding the item to the database _nwind.SaveChanges() Return New HttpStatusCodeResult(HttpStatusCode.Created) End Function ' Updating an item in the "Orders" collection Public Function UpdateOrder(ByVal key As Integer, ByVal values As String) As ActionResult Dim order = _nwind.Orders.First(Function(o) ' Finding the item to be updated by key Return o.OrderID = key End Function) JsonConvert.PopulateObject(values, order) ' Populating the found item with the changed values If TryValidateModel(order) = False Then ' Validating the updated item Return New HttpStatusCodeResult(HttpStatusCode.BadRequest, ValidationErrorMessage) End If _nwind.SaveChanges() Return New HttpStatusCodeResult(HttpStatusCode.OK) End Function ' Removing an item from the "Orders" collection Public Sub DeleteOrder(ByVal key As Integer) Dim order = _nwind.Orders.First(Function(o) ' Finding the item to be removed by key Return o.OrderID = key End Function) _nwind.Orders.Remove(order) ' Removing the found item _nwind.SaveChanges() End Sub End Class End Namespace
.NET Core MVC Controller
using System; using System.Linq; using Microsoft.AspNetCore.Mvc; using DevExtreme.AspNet.Data; using DevExtreme.AspNet.Mvc; using Newtonsoft.Json; using ProjectName.Models; namespace ProjectName.Controllers { public class GridDataController : Controller { NorthwindContext _nwind; public OrdersController(NorthwindContext nwind) { _nwind = nwind; } const string ValidationErrorMessage = "The record cannot be saved due to a validation error"; // Fetching items from the "Orders" collection public object GetOrders(DataSourceLoadOptions loadOptions) { return DataSourceLoader.Load(_nwind.Orders, loadOptions); } // Inserting a new item into the "Orders" collection public IActionResult InsertOrder(string values) { var newOrder = new Order(); // Creating the new item JsonConvert.PopulateObject(values, newOrder); // Populating the item with values if (!TryValidateModel(newOrder)) // Validating the item return BadRequest(ValidationErrorMessage); _nwind.Orders.Add(newOrder); // Adding the item to the database _nwind.SaveChanges(); return Ok(); } // Updating an item in the "Orders" collection public IActionResult UpdateOrder(int key, string values) { var order = _nwind.Orders.First(o => o.OrderID == key); // Finding the item to be updated by key JsonConvert.PopulateObject(values, order); // Populating the found item with the changed values if (!TryValidateModel(order)) // Validating the updated item return BadRequest(ValidationErrorMessage); _nwind.SaveChanges(); return Ok(); } // Removing an item from the "Orders" collection public void DeleteOrder(int key) { var order = _nwind.Orders.First(o => o.OrderID == key); // Finding the item to be removed by key _nwind.Orders.Remove(order); // Removing the found item _nwind.SaveChanges(); } } }
If you use a Web API controller in your app, configure access to it using the WebApi()
method of the DataSource()
's lambda parameter. The WebApi()
exposes the same methods as Mvc()
for specifying the controller and action names, but with one addition: You can pass true to the UpdateAction
, InsertAction
, and DeleteAction
methods for routing based on Http[Verb] attributes. The WebApi()
method is not intended for .NET Core MVC apps.
@(Html.DevExtreme().DataGrid() .DataSource(ds => ds .WebApi() .Controller("GridDataWebApi") .Key("OrderID") .UpdateAction(true) .InsertAction(true) .DeleteAction(true) ) )
@(Html.DevExtreme().DataGrid() _ .DataSource(Function(ds) Return ds.WebApi() _ .Controller("GridDataWebApi") _ .Key("OrderID") _ .UpdateAction(true) _ .InsertAction(true) _ .DeleteAction(true) End Function) )
The controller looks like this:
Web API Controller
using System; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using DevExtreme.AspNet.Data; using DevExtreme.AspNet.Mvc; using System.Net.Http.Formatting; using Newtonsoft.Json; using ProjectName.Models; namespace ProjectName.Controllers { public class GridDataWebApiController : ApiController { NorthwindContext _nwind = new NorthwindContext(); const string ValidationErrorMessage = "The record cannot be saved due to a validation error"; [HttpGet] // Fetching items from the "Orders" collection public HttpResponseMessage Get(DataSourceLoadOptions loadOptions) { return Request.CreateResponse(DataSourceLoader.Load(_nwind.Orders, loadOptions)); } [HttpPost] // Inserting a new item into the "Orders" collection public HttpResponseMessage Post(FormDataCollection form) { var values = form.Get("values"); // Getting JSON-formatted values for the new item var newOrder = new Order(); // Creating the new item JsonConvert.PopulateObject(values, newOrder); // Populating the item with values Validate(newOrder); // Validating the item if(!ModelState.IsValid) return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ValidationErrorMessage); _nwind.Orders.Add(newOrder); // Adding the item to the database _nwind.SaveChanges(); return Request.CreateResponse(HttpStatusCode.Created); } [HttpPut] // Updating an item in the "Orders" collection public HttpResponseMessage Put(FormDataCollection form) { var key = Convert.ToInt32(form.Get("key")); // Getting the key of the item to be updated var values = form.Get("values"); // and changed values for this item var order = _nwind.Orders.First(o => o.OrderID == key); // Finding the item to be updated by key JsonConvert.PopulateObject(values, order); // Populating the found item with the changed values Validate(order); // Validating the updated item if(!ModelState.IsValid) return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ValidationErrorMessage); _nwind.SaveChanges(); return Request.CreateResponse(HttpStatusCode.OK); } [HttpDelete] // Removing an item from the "Orders" collection public void Delete(FormDataCollection form) { var key = Convert.ToInt32(form.Get("key")); // Getting the key of the item to be removed var order = _nwind.Orders.First(o => o.OrderID == key); // Finding the item to be removed by key _nwind.Orders.Remove(order); // Removing the found item _nwind.SaveChanges(); } } }
Imports System.Linq Imports System.Net Imports System.Net.Http Imports System.Web.Http Imports DevExtreme.AspNet.Data Imports DevExtreme.AspNet.Mvc Imports System.Net.Http.Formatting Imports Newtonsoft.Json Imports ProjectName.Models Namespace Controllers Public Class GridDataWebApiController Inherits ApiController Dim _nwind As New NorthwindContext() Const ValidationErrorMessage As String = "The record cannot be saved due to a validation error" <HttpGet> ' Fetching items from the "Orders" collection Public Function [Get](ByVal loadOptions As DataSourceLoadOptions) As HttpResponseMessage Return Request.CreateResponse(DataSourceLoader.Load(_nwind.Orders, loadOptions)) End Function <HttpPost> ' Inserting a new item into the "Orders" collection Public Function [Post](ByVal form As FormDataCollection) As HttpResponseMessage Dim values = form.Get("values") ' Getting JSON-formatted values for the new item Dim newOrder As New Order() ' Creating the new item JsonConvert.PopulateObject(values, newOrder) ' Populating the item with values Validate(newOrder) ' Validating the item If ModelState.IsValid = False Then Return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ValidationErrorMessage) End If _nwind.Orders.Add(newOrder) ' Adding the item to the database _nwind.SaveChanges() Return Request.CreateResponse(HttpStatusCode.Created) End Function <HttpPut> ' Updating an item in the "Orders" collection Public Function [Put](ByVal form As FormDataCollection) As HttpResponseMessage Dim key = Convert.ToInt32(form.Get("key")) ' Getting the key of the item to be updated Dim values = form.Get("values") ' and changed values for this item Dim order = _nwind.Orders.First(Function(o) ' Finding the item to be updated by key Return o.OrderID = key End Function) JsonConvert.PopulateObject(values, order) ' Populating the found item with the changed values Validate(order) ' Validating the updated item If ModelState.IsValid = False Then Return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ValidationErrorMessage) End If _nwind.SaveChanges() Return Request.CreateResponse(HttpStatusCode.OK) End Function <HttpDelete> ' Removing an item from the "Orders" collection Public Sub [Delete](ByVal form As FormDataCollection) Dim key = Convert.ToInt32(form.Get("key")) ' Getting the key of the item to be removed Dim order = _nwind.Orders.First(Function(o) ' Finding the item to be removed by key Return o.OrderID = key End Function) _nwind.Orders.Remove(order) ' Removing the found item _nwind.SaveChanges() End Sub End Class End Namespace
Controller on a Different Site
Previous examples show use-cases in which a control is on the same site as the data it accesses, and routing helps find the right controller and actions. If the data is on a different site, you can use the URL to access it via the RemoteController()
method of the DataSource()
's lambda parameter. This method opens a chain whose members mirror the client-side method fields in the already familiar DevExtreme.AspNet.Data library.
@(Html.DevExtreme().DataGrid() .DataSource(ds => ds .RemoteController() .Key("OrderID") .LoadUrl("http://www.example.com/Orders/GetOrders") .InsertUrl("http://www.example.com/Orders/InsertOrder") .UpdateUrl("http://www.example.com/Orders/UpdateOrder") .DeleteUrl("http://www.example.com/Orders/DeleteOrder") ) )
@(Html.DevExtreme().DataGrid() _ .DataSource(Function(ds) Return ds.RemoteController() _ .Key("OrderID") _ .LoadUrl("http://www.example.com/Orders/GetAllOrders") _ .InsertUrl("http://www.example.com/Orders/InsertOrder") _ .UpdateUrl("http://www.example.com/Orders/UpdateOrder") _ .DeleteUrl("http://www.example.com/Orders/DeleteOrder") End Function) )
Controller in a Different Area
In an app organized into areas, a control from a view belonging to one area may need to access a data controller belonging to another. Use the Area()
method to specify the data controller's area in this case.
@(Html.DevExtreme().DataGrid() .DataSource(ds => ds .Mvc() .Area("DifferentArea") // ... ) )
@(Html.DevExtreme().DataGrid() _ .DataSource(Function(ds) Return ds.Mvc() _ .Area("DifferentArea") _ ' ... End Function) )
Passing Additional Load Parameters
DevExtreme ASP.NET MVC Controls internally transform your Razor code into HTML and JavaScript. However, certain functionality, passing load parameters being an example, cannot be implemented using Razor without accessing JavaScript variables directly.
Consider the following code example that implements the master-detail interface in the DataGrid control. This interface is a grid inside a grid, with the inner grid filtering its data source according to the master row key. The API reference states that the master row key and data are available in the master-detail template through the key
and data
JavaScript variables. Only the key
's value is needed for the master-detail, and it is accessed using the new JS()
construct. This construct inserts any JavaScript expression passed to it into the resulting JavaScript code verbatim.
@(Html.DevExtreme().DataGrid() .DataSource(d => d.WebApi().Controller("Employees").Key("ID")) .Columns(columns => { columns.Add().DataField("FirstName"); columns.Add().DataField("LastName"); // ... }) .MasterDetail(md => md .Enabled(true) .Template(@<text> @(Html.DevExtreme().DataGrid() .DataSource(d => d.WebApi() .Controller("Employees") .LoadAction("TasksDetails") .LoadParams(new { id = new JS("key") }) ) ) </text>) ) )
@Code ' Wrap the widget in Code if you use @<text> inside Html.DevExtreme().DataGrid() _ .DataSource(Function(d) d.WebApi().Controller("Employees").Key("ID")) _ .Columns(Sub(columns) columns.Add().DataField("FirstName") columns.Add().DataField("LastName") ' ... End Sub) _ .MasterDetail(Sub(md) md.Enabled(True) _ .Template(Sub() @<text> @(Html.DevExtreme().DataGrid() _ .DataSource(Function(d) Return d.WebApi() _ .Controller("Employees") _ .LoadAction("TasksDetails") _ .LoadParams(New With { .id = New JS("key") }) End Function) ) </text> End Sub) End Sub) _ .Render() ' End the configuration with Render() because it is inside Code End Code
If the control is not in a template and no variables are provided, you can get data for a load parameter using a JavaScript function accessed with the same new JS()
construct. In the following code, the DataGrid control uses the getDateBoxValue()
function to get a value for the orderDate
load parameter from the DateBox control. The refreshGrid()
function, which is called each time the DateBox value changes, calls the DataGrid's refresh() method that makes a new load query with the updated load parameter.
@(Html.DevExtreme().DateBox() .ID("orderDate") .Type(DateBoxType.Date) .Value(DateTime.Now) .OnValueChanged("refreshGrid") ) @(Html.DevExtreme().DataGrid() .ID("targetDataGrid") .DataSource(ds => ds.WebApi() .Controller("Orders") .LoadAction("GetOrdersByDate") .LoadParams(new { orderDate = new JS("getDateBoxValue") }) ) .Columns(cols => { cols.Add().DataField("OrderID"); cols.Add().DataField("OrderDate"); // ... }) ) <script type="text/javascript"> function getDateBoxValue () { return $("#orderDate").dxDateBox("option", "text"); } function refreshGrid() { $("#targetDataGrid").dxDataGrid("refresh"); } </script>
@(Html.DevExtreme().DateBox() _ .ID("orderDate") _ .Type(DateBoxType.Date) _ .Value(DateTime.Now) _ .OnValueChanged("refreshGrid") ) @(Html.DevExtreme().DataGrid() _ .ID("targetDataGrid") _ .DataSource(Function(ds) Return ds.WebApi() _ .Controller("Orders") _ .LoadAction("GetOrdersByDate") _ .LoadParams(New With { .orderDate = New JS("getDateBoxValue") }) End Function ) _ .Columns(Sub(cols) cols.Add().DataField("OrderID") cols.Add().DataField("OrderDate") ' ... End Sub) ) <script type="text/javascript"> function getDateBoxValue () { return $("#orderDate").dxDateBox("option", "text"); } function refreshGrid() { $("#targetDataGrid").dxDataGrid("refresh"); } </script>
Read-Only Data in JSON Format
A server-side control can access JSON data returned from a resource by an AJAX request. For this purpose, the lambda parameter of the DataSource()
method exposes the StaticJson()
method. It opens a chain of methods configuring access to JSON data.
@(Html.DevExtreme().SelectBox() .DataSource(ds => ds .StaticJson() .Url("http://www.example.com/dataservices/jsondata") .Key("ID") .CacheAllData(true) // loads all data at once and saves it in cache; true by default ) )
@(Html.DevExtreme().SelectBox() _ .DataSource(Function(ds) Return ds.StaticJson() _ .Url("http://www.example.com/dataservices/jsondata") _ .Key("ID") _ .CacheAllData(True) ' loads all data at once and saves it in cache; true by default End Function) )
Besides accepting absolute URLs, which is shown in the previous code, the Url()
method can accept virtual paths.
@(Html.DevExtreme().SelectBox() .DataSource(ds => ds .StaticJson() .Url(@Url.Content("~/dataservices/jsondata")) ) )
@(Html.DevExtreme().SelectBox() _ .DataSource(Function(ds) Return ds.StaticJson() _ .Url(Url.Content("~/dataservices/jsondata")) End Function) )
You can also use a JSONP callback parameter supported by jQuery.ajax().
@(Html.DevExtreme().SelectBox() .DataSource(ds => ds .StaticJson() .Url("http://www.example.com/dataservices/jsonpdata?callback=?") ) )
@(Html.DevExtreme().SelectBox() _ .DataSource(Function(ds) Return ds.StaticJson() _ .Url("http://www.example.com/dataservices/jsonpdata?callback=?") End Function) )
In addition, the DataSource()
method has several overloads for configuring access to JSON data more briefly. Using them, you can specify the data's URL...
@(Html.DevExtreme().SelectBox() .DataSource("http://www.example.com/dataservices/jsondata") )
@(Html.DevExtreme().SelectBox() _ .DataSource("http://www.example.com/dataservices/jsondata") )
... or the URL and the key field.
@(Html.DevExtreme().SelectBox() .DataSource("http://www.example.com/dataservices/jsondata", "ID") )
@(Html.DevExtreme().SelectBox() _ .DataSource("http://www.example.com/dataservices/jsondata", "ID") )
OData
Also, DevExtreme ASP.NET MVC Controls operate with an OData service out of the box. To address an OData service, call the DataSource()
method and pass a lambda expression to it. The lambda parameter exposes the OData()
method that configures access to the OData service.
@(Html.DevExtreme().DataGrid() .DataSource(ds => ds .OData() .Version(4) .Url("http://services.odata.org/V4/Northwind/Northwind.svc/Products") .JSONP(true) .Key("ProductID") .Expand("Category") ) )
@(Html.DevExtreme().DataGrid() _ .DataSource(Function(ds) Return ds.OData() _ .Version(4) _ .Url("http://services.odata.org/V4/Northwind/Northwind.svc/Products") _ .JSONP(True) _ .Key("ProductID") _ .Expand("Category") End Function) )
OLAP Cube
An OLAP cube is a multi-dimensional dataset that allows for data mining and analysis. For displaying data from an OLAP cube, DevExtreme provides the PivotGrid control. You can access the OLAP cube by calling the DataSource()
method as shown in the following code. The lambda expression passed to this method configures the XmlaStore data store.
@(Html.DevExtreme().PivotGrid() .DataSource(ds => ds .Store(s => s.Xmla() .Url("http://my-web-srv01/OLAP/msmdpump.dll") .Catalog("AdventureWorksDW2012") .Cube("Adventure Works") ) ) )
@(Html.DevExtreme().PivotGrid() _ .DataSource(Function(ds) Return ds.Store(Function(s) Return s.Xmla() _ .Url("http://my-web-srv01/OLAP/msmdpump.dll") _ .Catalog("AdventureWorksDW2012") _ .Cube("Adventure Works") End Function) End Function) )
Refresh Data
Use the JavaScript API to refresh server-side controls' data. Any data-bound control has the getDataSource() method. It returns the control's DataSource instance. Call its reload() method to refresh the control's data, as shown in the following DataGrid example:
@(Html.DevExtreme().DataGrid() .ID("targetDataGrid") .DataSource(ds => ds.Mvc() .Controller("GridData") .Key("OrderID") .LoadAction("GetOrders") .InsertAction("InsertOrder") .UpdateAction("UpdateOrder") .DeleteAction("DeleteOrder") ) ) @(Html.DevExtreme().Button() .Text("Refresh Grid") .OnClick("reloadData") ) <script type="text/javascript"> function reloadData() { $("#targetDataGrid").dxDataGrid("getDataSource").reload(); } </script>
@(Html.DevExtreme().DataGrid() _ .ID("targetDataGrid") _ .DataSource(Function(ds) Return ds.Mvc() _ .Controller("GridData") _ .Key("OrderID") _ .LoadAction("GetOrders") _ .InsertAction("InsertOrder") _ .UpdateAction("UpdateOrder") _ .DeleteAction("DeleteOrder") End Function) ) @(Html.DevExtreme().Button() _ .Text("Refresh Grid") _ .OnClick("reloadData") ) <script type="text/javascript"> function reloadData() { $("#targetDataGrid").dxDataGrid("getDataSource").reload(); } </script>
If you have technical questions, please create a support ticket in the DevExpress Support Center.