Passing Morris Chart data by Viewmodel property with MVC - javascript

I am building a Morris Chart based on a database data and I pass to the View using the Viewmodel:
Razor code:
#Html.HiddenFor(m => m.SurveyLastDaysChartData)
HTML code:
<input id="SurveyLastDaysChartData" name="SurveyLastDaysChartData" type="hidden" value="[{"Date":"2016-07-18","Average":0},{"Date":"2016-07-17","Average":0},{"Date":"2016-07-16","Average":0},{"Date":"2016-07-15","Average":4.125},{"Date":"2016-07-14","Average":0},{"Date":"2016-07-13","Average":0},{"Date":"2016-07-12","Average":0}]">
The problem is that the Javascript side can't read the data because it's in string format.
var _surveyLastDaysChartId = "dsb-survey-last-days-chart";
var _surveyLastDaysChartData = $("#SurveyLastDaysChartData");
Morris.Line({
// ID of the element in which to draw the chart.
element: _surveyLastDaysChartId,
// Chart data records -- each entry in this array corresponds to a point on the chart.
data: _surveyLastDaysChartData.val(),
// The name of the data record attribute that contains x-values.
xkey: 'Date',
// A list of names of data record attributes that contain y-values.
ykeys: ['Average'],
// Labels for the ykeys -- will be displayed when you hover over the chart.
labels: ['Value']
});
I would like to keep the chart data in the Viewmodel and avoid Javascript in the View, how can I do that?
Thanks.

In your view, serialize the property and set to a javascript variable. This will be JSON.
<script>
var chartData = #Html.Raw(Newtonsoft.Json.JsonConvert
.SerializeObject(Model.SurveyLastDaysChartData));
</script>
Now you can use the chartData variable in your javascript code.

data : #(Html.Raw(System.Web.Helpers.Json.Encode(Model.ListOfYouNeed)))

Related

Chart JS Implementation of Gantt Chart

I would like to add dynamic data to a chart JS Horizontal Bar Graph,
How would I implement this on a data that is coming from mysql
data: [
['2022-01-01', '2022-01-15'], <<<<< this one how would I able to replace it with my own data
]
data

Update stock price in anychart without re-plotting whole chart

I am playing with the Anychart stock candlestick chart which is very nice, in order to update the chart I use a setInterval function but it re-plots the entire chart which sucks because if I am zooming or something it resets and starts over obviously. Is there a way I can just update last price from the database every couple seconds without re-plotting the whole chart?
Current setInterval function to load chart:
setInterval(function() {
$.get('chart_data.php', function(data) {
$(".main_cont").replaceWith(data);
});
}, 2000);
My chart_data variable:
$chart_data .= "{'x':'".$open_time."','open': ".$open.",'high': ".$high.",'low': ".$low.",'close': ".$close."},";
chart_data.php file:
anychart.onDocumentReady(function() {
// create a data table
var table = anychart.data.table('x');
// add data
table.addData([<?php echo $chart_data;?>]);
// add data
//table.addData([ {'x':'08/09/2020 10:11','open': 11000,'high': 10000,'low': 8000,'close': 8500}]);
// create a stock chart
var chart = anychart.stock(true);
// create a mapping
var mapping = table.mapAs({
'date': 'date',
'open': 'open',
'high': 'high',
'low': 'low',
'close': 'close',
'fill': 'fill'
});
var plot = chart.plot(0);
// add a series using the mapping
chart.plot(0).candlestick(mapping).name();
// set container id for the chart
chart.container('container');
var series = chart.plot(0).candlestick(mapping);
chart.scroller().xAxis(false);
// initiate chart drawing
chart.draw();
});
I would like to replace the setInterval function with something that just replaces the last price data from the database to move the candle up or down, if a new record is added then draw the new candle. I have the script to update the candle or add a new candle I just cannot find a way to do it without re-drawing the whole chart.
You can use the functions for manipulating data to alter the chart.
You can use JS to fetch new data every two seconds, and use addData() to replace the existing data. If that still causes a complete refresh, you'll have to compare the difference between two arrays to determine the difference between the current data and newly fetched data, and use the insert, delete and update methods as described in the docs to alter just the changed data. However, this may still may result in a complete refresh.
You would use AJAX (from JS) to request updated data from a PHP script. The data gets returned to your JS. It's probably easiest to send/receive data in JSON format via jQuery.getJSON.
There's no need to recreate the chart or even reapply the whole data. The AnyStock API provides all you need to update a part of the data. The series will be updated automatically.
For this purpose, you can use addData() function. It replaces all rows with duplicating keys by the last seen row with that key. It means that new points will be added to the table, points with already existing keys in the table will be overridden.
So, all you need is to manage keys and apply points according to your mapping. For details, check the following sample, that simulates exactly what you need - https://playground.anychart.com/Cplq7KMd

oData binding to table generates repeated lines in table output

I have an OData connection using which I read an entityset with conditions that returns me data in the following structure. The data being in the root node itself rather than in an object array-
oData Structure
I am then setting this data to a JSON Model and binding this model to my oTable.
The code in controller looks something like below-
//Get data for the table
var oTabData = sap.ui.getCore().byId("MyTable");
var sServiceUrl = "http://example.com/sap/opu/odata/SAP/ZXX_SRV";
var oModel2 = new sap.ui.model.odata.ODataModel(sServiceUrl,true);
var oJsonModel = new sap.ui.model.json.JSONModel();
oModel2.read("/MyEntitySet(Myvar1='000001',Myvar2='abc')?
$format=json",null,null,true,function(oData,response){
oJsonModel.setData(oData);
});
oTabData.setModel(oJsonModel);
The view contains the table and the binding is as below. Have ignored rest of table declaration code to keep it short. Table declared as oTable with id MyTable and with all the right columns-
//Template to map the data to the respective column
var template = new sap.m.ColumnListItem({
id:"table_template",
type: "Navigation",
visible: true,
cells:[
new sap.m.Label({
text: "{/Myvar1}"
}),
new sap.m.Label({
text: "{/Myvar2}"
}),
new sap.m.Label({
text: "{/Myvar3}"
}),
new sap.m.Label({
text: "{/Myvar4}"
})
]
});
var oFilters = null;
oTable.bindItems("/",template,null,oFilters);
The issues are-
As I have made a service call with conditions the oData output
received does not output an array of data like it does when we make
a call without conditions
(oModel2.read("/MyEntitySet?$format=json",null,null,true,function(oData,response)).
In the latter case the output comes under results array for which
the binding assignment is /results and that works right as expected.
In current case (service call with conditions), as the columns in
output are available right in the root level, have used binding /
and in template as well using / in front of every element (e.g.
{/Myvar1} as seen above). But using this technique it also creates 3
default blank lines in table initially. When the above controller
code is executed, it fills the table 3 x 4 times i.e. 12 rows for a
single row output.
Due to organization restrictions I cannot put the original code here. But this is how the scenario is. Any help would be appreciated.
Thanks.
PS: Haven't used any loop that would generate the repeated lines.
You can bind your table directly to the ODataModel:
Steps:
Before doing binding, you need to create a template for the table rows, in sap.m.Table it is ColumnListItem control, I would suggest to carry it out to the XML fragment. Try to use XML for markup as much as possible, becasue it much clearer and maintainablier than js coding;
All the controls in "cells" should be bound to the rows' properties using relative paths.
Tell the View about your model by calling "oView.setModel(MODEL_INSTANCE)", by this line you set the default model to the view. From now on all the controls inside are able to see it. The model is default because the name of it was not specified.
oTable.bindItems("/MyEntitySet", { template: oColumnListItem, filters: aFilters}); - this will automatically trigger an OData call to grab all needed data. The table will be updated automatically. You should see the rows.

Highcharts Line Chart - Hyperlink on a data point

I am working on an application to create Line Chart using the Highcharts API. This application involves plotting a Date vs. Time Line Chart.
I need to have dynamic hyperlinks, for all or some of the data points.
The data for this chart is being retrieved from a database table and converted into JSON. This JSON is then being parsed by JavaScript and converted into data array that can be consumed by the Highcharts API. There is some data manipulation being done in the JavaScript while converting the data from JSON to data array.
The Highcharts API accepts the input in data array format that comprises of [x, y] combinations.
As I need to have a dynamic hyperlink for all or some of the data points, I have created another array that comprises of the hyperlinks.
I am unable to retrieve the hyperlink URL from the array on the fly as a particular hyperlink is clicked by the user.
I tried using it they was it has been used in this fiddle, http://jsfiddle.net/awasM/1/
A snippet of my code is given below:
series: [{
name: 'Release',
data: dataArray,
URLs: urlArray,
point: {
events: {
click: function() {
var someURL = this.series.userOptions.URLs[this.x];
if (someURL != "undefined")
window.open(someURL);
}
}
}
}]
However, as in my case date (in Unix/Epoch time format) is on x-axis (and time on y-axis), so using the x-axis value does not work.
i hope you could match this code to fix something.
point: {
events: {
click: function() {
var pointObject = this;
var pointindex = pointObject.x;
var pointdata = pointObject.y;
var getIndexOfURL = this.series.userOptions.URLs[pointindex];
var getIndexOfData = this.series.userOptions.data[pointindex];
if (getIndexOfURL){
window.open('http://'+getIndexOfURL);
}
}
}
}

amcharts: trying to dynamically add multiple datasets to javascript stockChart

I am using AmCharts for displaying some charts and I am trying to dynamically add the data from a series of JSON data sets which are acquired using jquery's getJSON
My question in short is, how do I loop through my various data sets creating dataSets for the charts using something like:
$.getJSON("GET NUMBER OF DATA SETS REQUIRED", function (locdata) {
$.each(locdata, function (i, item) {
$.getJSON("GET DATA FOR THIS DATASET", function (data) {
var dataSet = new AmCharts.DataSet();
dataSet.title = locdata[i].name;
dataSet.fieldMappings = [{
fromField: "takings",
toField: "takings"
}, {
fromField: "qty",
toField: "qty"
}];
dataSet.dataProvider = data; ;
dataSet.categoryField = "date";
)};
)};
)};
To explain what I am doing here:
Firstly, getting some JSON output from my database to determine how many record sets are required
Looping through the result from this to create recordsets
During each loop, the data is acquired by a second jQuery getJSON call to grab data based on the data required for this recordset
Creating an AmCharts Dataset
I can manually do this by explicitly coding to create each dataset individually and then doing
chart.dataSets = [dataSet0, dataSet1, dataSet2, dataSet3, dataSet4];
So I guess what I need to do is turn the whole of the code above into some kind of function which generates an array of datasets as per the line above?
I'm not sure how to do this with javascript though
you can simply push each data set to chart.dataSets array:
chart.dataSets.push(dataSet);

Categories

Resources