Your search did not match any results.

Charts - Load Data On Demand

In this demo, the range area Chart loads data as you pan it. Once the component loads a data block, this data stays in memory to reduce requests to the server.

www.kaggle.com
Backend API
@(Html.DevExtreme().Chart() .ID("chart") .Title("Temperature in Toronto (2017)") .DataSource(d => d.Array()) .DataSourceOptions(c => c .Sort("date") .Paginate(false) ) .ZoomAndPan(z => z.ArgumentAxis(ChartZoomAndPanMode.Pan)) .ScrollBar(s => s.Visible(true)) .ArgumentAxis(a => a .ArgumentType(ChartDataType.DateTime) .WholeRange(w => w .StartValue(new DateTime(2017, 1, 1)) .EndValue(new DateTime(2017, 12, 31)) ) .VisualRange(v => v .StartValue(new DateTime(2017, 4, 1)) .Length(l => l.Weeks(2)) ) .VisualRangeUpdateMode(VisualRangeUpdateMode.Keep) ) .ValueAxis(v => v.Add() .Name("temperature") .AllowDecimals(false) .Title(t => t .Text("Temperature, °C") .Font(f => f.Color("#ff950c")) ) .Label(l => l.Font(f => f.Color("#ff950c"))) ) .Series(s => s.Add() .Color("#ff950c") .Type(SeriesType.RangeArea) .ArgumentField("date") .RangeValue1Field("minTemp") .RangeValue2Field("maxTemp") .Name("Temperature range") ) .OnOptionChanged(@<text> function(e){ if(e.fullName === "argumentAxis.visualRange") { onVisualRangeChanged(e.value, e.component); } } </text>) .Animation(a => a.Enabled(false)) .LoadingIndicator(l => l .BackgroundColor("none") .Font(f => f.Size(14)) ) .Legend(l => l.Visible(false)) ) <script> var HALFDAY = 43200000; var packetsLock = 0; function onVisualRangeChanged(visualRange, component) { var items = component.getDataSource().items(); if (!items.length || items[0].date - visualRange.startValue >= HALFDAY || visualRange.endValue - items[items.length - 1].date >= HALFDAY) { uploadDataByVisualRange(visualRange, component); } } function uploadDataByVisualRange(visualRange, component) { var dataSource = component.getDataSource(); var storage = dataSource.items(); var ajaxArgs = { startVisible: getDateString(visualRange.startValue), endVisible: getDateString(visualRange.endValue), startBound: getDateString(storage.length ? storage[0].date : null), endBound: getDateString(storage.length ? storage[storage.length - 1].date : null) }; if (ajaxArgs.startVisible !== ajaxArgs.startBound && ajaxArgs.endVisible !== ajaxArgs.endBound && !packetsLock) { packetsLock++; component.showLoadingIndicator(); getDataFrame(ajaxArgs) .then(function(dataFrame) { packetsLock--; var componentStorage = dataSource.store(); dataFrame.forEach(function(item) { componentStorage.insert(item); }); dataSource.reload(); var range = component.getArgumentAxis().visualRange(); onVisualRangeChanged(range, component); }, function(reason) { packetsLock--; dataSource.reload(); }); } } function getDataFrame(args) { var deferred = $.Deferred(); $.ajax({ url: "@Url.Content("~/api/TemperatureData")", dataType: "json", data: args, success: function (result) { deferred.resolve(result.map(function(i) { return { date: new Date(i.Date), minTemp: i.MinTemp, maxTemp: i.MaxTemp }; })); }, error: function () { deferred.reject("Data Loading Error"); }, timeout: 2000 }); return deferred.promise(); } function getDateString(dateTime) { return dateTime ? dateTime.toLocaleDateString("en-US") : ""; } </script>
using DevExtreme.AspNet.Data; using DevExtreme.AspNet.Mvc; using DevExtreme.MVC.Demos.Models.SampleData; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Web.Mvc; namespace DevExtreme.MVC.Demos.Controllers { public class ChartsController : Controller { public ActionResult LoadDataOnDemand() { return View(); } } }
using System; using System.Collections.Generic; using System.Web.Http; using System.Web.Http.Cors; using DevExtreme.MVC.Demos.Models; using DevExtreme.MVC.Demos.Models.SampleData; using System.Linq; namespace DevExtreme.MVC.Demos.Controllers.ApiControllers { [EnableCors(origins: "*", headers: "*", methods: "*")] public class TemperatureDataController : ApiController { [HttpGet] public IEnumerable<TemperatureItem> Get(string startVisible = "01/01/2017", string endVisible = "12/31/2017", string startBound = "01/01/2017", string endBound = "12/31/2017") { var startVisibleDate = DateTime.Parse(startVisible); var endVisibleDate = DateTime.Parse(endVisible); var startBoundDate = string.IsNullOrEmpty(startBound) ? DateTime.MaxValue : DateTime.Parse(startBound); var endBoundDate = string.IsNullOrEmpty(endBound) ? DateTime.MinValue : DateTime.Parse(endBound); var startDate = startBoundDate > startVisibleDate ? startVisibleDate.AddDays(-7) : endBoundDate.AddDays(1); var endDate = endBoundDate < endVisibleDate ? endVisibleDate.AddDays(7) : startBoundDate.AddDays(-1); return SampleData.ServiceRepository.Instance.TemperatureItems.Where(t => t.Date >= startDate && t.Date <= endDate); } } }
using System.Collections.Generic; using System.Web; using System.Xml.Linq; using System.Linq; using System.Globalization; using System; using System.IO; using DevExpress.Utils; namespace DevExtreme.MVC.Demos.Models.SampleData { public partial class SampleData { public class ServiceRepository { public static readonly ServiceRepository Instance = new ServiceRepository(); public readonly IEnumerable<TemperatureItem> TemperatureItems; private ServiceRepository() { CultureInfo ci = (CultureInfo)CultureInfo.CurrentCulture.Clone(); ci.NumberFormat.CurrencyDecimalSeparator = "."; var xmlContent = File.ReadAllText(HttpContext.Current.Server.MapPath("~/Content/SampleData/TemperatureData.xml")); XDocument tempDoc = SafeXml.CreateXDocument(xmlContent); TemperatureItems = (from d in tempDoc.Root.Elements("dayItem") select new TemperatureItem { Date = DateTime.Parse(d.Element("date").Value, null, DateTimeStyles.RoundtripKind), MinTemp = float.Parse(d.Element("minTemp").Value, NumberStyles.Any, ci), MaxTemp = float.Parse(d.Element("maxTemp").Value, NumberStyles.Any, ci) }).ToArray(); } } } }
using System; using System.ComponentModel.DataAnnotations; namespace DevExtreme.MVC.Demos.Models { public class TemperatureItem { [Key] public DateTime Date { get; set; } public float MinTemp { get; set; } public float MaxTemp { get; set; } } }
#chart { height: 440px; }

To implement this functionality, do the following:

  1. Configure a data source.

  2. Configure the Chart to support on-demand data loading.

  3. Implement functions that load the data.

    • In this demo, Chart displays daily information. If a user pan the Chart left or right more than half a day, additional data starts to load. The onVisualRangeChanged initiates this procedure.

    • The uploadDataByVisualRange function analyzes the starting and ending points of the visual range and the bounds of already loaded data. If necessary, it calls the getDataFrame function to obtain new data points. Finally, it reloads the DataSource and saves the current visual range.

    • The getDataFrame Ajax request gets the new data frame from the server.