In this post, we will show you how to use our jQuery Chart widget, called jqxChart with Knockout. Knockout will help us to update the Chart dynamically depending on the user’s actions or when the data is changed. We will also use the jqxDataAdapter plug-in and will bind the Chart to it. jqxDataAdapter automatically detects and responds to changes of the Knockout’s observable collection and updates the data bound UI widget(the Chart in this case). You can download Knockout from
here.
1. Add the JavaScript and CSS files. We need to load the jQuery Framework, Knockout, jQWidgets Framework(jqxcore.js), the jqxDataAdapter plug-in(jqxdata.js) and the jQuery Chart(jqxchart.js). We also include the jqxbutton.js to simulate dynamic data changes when a button is clicked.
<link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" type="text/css" /><script type="text/javascript" src="../../scripts/jquery-1.7.1.min.js"></script><script type="text/javascript" src="../../scripts/knockout-2.0.0.js"></script><script type="text/javascript" src="../../jqwidgets/jqxcore.js"></script><script type="text/javascript" src="../../jqwidgets/jqxdata.js"></script><script type="text/javascript" src="../../jqwidgets/jqxbuttons.js"></script><script type="text/javascript" src="../../jqwidgets/jqxchart.js"></script>
2. To create a view model with Knockout, we declare the following JavaScript object:
var sampleData = [ { Day: '1', Keith: 30, Erica: 15, George: 25 }, { Day: '2', Keith: 25, Erica: 25, George: 30 }, { Day: '3', Keith: 30, Erica: 20, George: 25 }, { Day: '4', Keith: 35, Erica: 25, George: 45 }, { Day: '5', Keith: 20, Erica: 20, George: 25 }, { Day: '6', Keith: 30, Erica: 20, George: 30 }, { Day: '7', Keith: 60, Erica: 45, George: 90 } ];
3. Then, we create a function called ChartModel:
var ChartModel = function (items) { this.items = ko.observableArray(items); // add a new item. this.addItem = function () { if (days < 20) { days++; this.items.push({ Day: days, Keith: Math.round(Math.random() * 30), Erica: Math.round(Math.random() * 60), George: Math.round(Math.random() * 90) }); } }; // remove the last item. this.removeItem = function () { if (days > 2) { days--; this.items.pop(); } }; // update the first item. this.updateItem = function () { var item = {}; item.Day = days[Math.floor(Math.random() * days.length)] item.Keith = Math.floor(Math.random() * 100); item.Erica = Math.floor(Math.random() * 100); item.George = Math.floor(Math.random() * 100); this.items.replace(this.items()[0], item); };};
The ChartModel simply adds, removes or updates items.
4. To activate Knockout, we need to call the applyBindings method and pass the view model object that we want to use.
var model = new ChartModel(sampleData);ko.applyBindings(model);
5. Now, its time to use the jqxDataAdapter which will perform the data bindings for us. We do this by creating a source object and passing the Knockout’s observable array to the localdata member. Then, we initialize the jqxDataAdapter plug-in and pass the source object as parameter.
var source = { localdata: model.items, datatype: 'local'}// create a new instance of the jqxDataAdapter plug-in.var dataAdapter = new $.jqx.dataAdapter(source);
The jQuery Chart’s source property should be set to the dataAdapter instance.
6. In the HTML markup, we add ‘Add’, ‘Remove’ and ‘Update’ buttons which call the ChartModel’s addItem, removeItem
and updateItem methods.
<input id="addButton" type="button" data-bind="click: addItem" value="Add Item"/><input id="removeButton" type="button" data-bind="click: removeItem" value="Remove Item"/><input id="updateButton" type="button" data-bind="click: updateItem" value="Update Item"/>
7. Below is the full source code:
<!DOCTYPE html><html lang="en"><head> <title id='Description'>This example shows how to integrate jqxChart with Knockout </title> <link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" type="text/css" /> <script type="text/javascript" src="../../scripts/jquery-1.7.1.min.js"></script> <script type="text/javascript" src="../../scripts/knockout-2.0.0.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxcore.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxdata.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxbuttons.js"></script> <script type="text/javascript" src="../../jqwidgets/jqxchart.js"></script> <script type="text/javascript"> $(document).ready(function () { // prepare chart data var sampleData = [ { Day: '1', Keith: 30, Erica: 15, George: 25 }, { Day: '2', Keith: 25, Erica: 25, George: 30 }, { Day: '3', Keith: 30, Erica: 20, George: 25 }, { Day: '4', Keith: 35, Erica: 25, George: 45 }, { Day: '5', Keith: 20, Erica: 20, George: 25 }, { Day: '6', Keith: 30, Erica: 20, George: 30 }, { Day: '7', Keith: 60, Erica: 45, George: 90 } ]; var days = 7; var ChartModel = function (items) { this.items = ko.observableArray(items); // add a new item. this.addItem = function () { if (days < 20) { days++; this.items.push({ Day: days, Keith: Math.round(Math.random() * 30), Erica: Math.round(Math.random() * 60), George: Math.round(Math.random() * 90) }); } }; // remove the last item. this.removeItem = function () { if (days > 2) { days--; this.items.pop(); } }; // update the first item. this.updateItem = function () { var item = {}; item.Day = days[Math.floor(Math.random() * days.length)] item.Keith = Math.floor(Math.random() * 100); item.Erica = Math.floor(Math.random() * 100); item.George = Math.floor(Math.random() * 100); this.items.replace(this.items()[0], item); }; }; // activate Knockout. var model = new ChartModel(sampleData); ko.applyBindings(model); // initialize jqxButtons. $('#addButton').jqxButton(); $('#removeButton').jqxButton(); $('#updateButton').jqxButton(); // create the jqxGrid source object. var source = { localdata: model.items, datatype: 'local' } // create a new instance of the jqxDataAdapter plug-in. var dataAdapter = new $.jqx.dataAdapter(source); // prepare jqxChart settings var settings = { title: "Fitness & exercise weekly scorecard", description: "Time spent in vigorous exercise", padding: { left: 5, top: 5, right: 5, bottom: 5 }, titlePadding: { left: 90, top: 0, right: 0, bottom: 10 }, source: dataAdapter, categoryAxis: { dataField: 'Day', showGridLines: false }, colorScheme: 'scheme01', seriesGroups: [ { type: 'line', columnsGapPercent: 30, seriesGapPercent: 0, valueAxis: { minValue: 0, maxValue: 100, unitInterval: 10, description: 'Time in minutes' }, series: [ { dataField: 'Keith', displayText: 'Keith' }, { dataField: 'Erica', displayText: 'Erica' }, { dataField: 'George', displayText: 'George' } ] } ] }; // select the chartContainer DIV element and render the chart. $('#chartContainer').jqxChart(settings); }); </script></head><body class='default'> <div id='jqxWidget'> <div id="chartContainer" style="width:600px; height: 400px"> </div> <div style="margin-top: 10px;"> <input id="addButton" type="button" data-bind="click: addItem" value="Add Item"/> <input id="removeButton" type="button" data-bind="click: removeItem" value="Remove Item"/> <input id="updateButton" type="button" data-bind="click: updateItem" value="Update Item"/> </div> </div></body></html>