Two-way binding is not recognising variable change in AngularJS - javascript

I have a slider that is used to changed a value in my controller like so
index:
<div>
<rzslider
rz-slider-model="slider.value"
rz-slider-options="slider.options">
</rzslider>
<p>{{slider.value}}</p>
</div>
controller:
app.controller('gbarchartController', function($scope) {
$scope.slider = {
value: 20,
options: {
floor: 0,
ceil: 30
}
};
When i change the value of the slider, the code below displays it on screen as 2 way binding should.
<p>{{slider.value}}</p>
The problem is , if i try to access this variable through a function in my controller, it uses the initial value of 20 that has been set. eg. If i change the slider to 10, the below code still uses the value 20. the variable in question is $scope.slider.value . The value is used to cut the length of an array, that in turn is used to display a graph using highchart.js.
$scope.graph = function(metric) {
Highcharts.chart(metric, {
chart: {
type: 'column'
},
title: {
text: 'Number Of Executions'
},
colors: [
'#7CFC00', '#FF0000'
],
xAxis: {
categories: numExe.hash.slice(0, $scope.slider.value),
title: {
text: 'Query Hash Value'
}
},
yAxis: {
title: {
text: '% of Total Executions'
}
},
tooltip: {
shared:true
},
series: [{
name: 'Baseline',
data: numExe.base.slice(0, $scope.slider.value)
},
{
name: 'Comparative',
data: numExe.compare.slice(0, $scope.slider.value)
}]
});
}
Long story short, The variable changes in the html but does not change in the controller. Any help would be great thanks.

I don't think Highcharts monitors its data for changes, so it won't detect changes to your series data (see docs here). Additionally the series data passed in to the graph is static, so it won't update after the slider changes. You'll need to create a local Series variable to hold the series data, and update the series data when the slider changes. I'm not sure what numExe is so I can't say how the data is generated, but the Series object has setData() method (with a redraw parameter) that should do the trick.

Related

Highchart xAxis labels formatter for multiple series values from multi-dim array

My Requirement
I want to label the X-Axis of multi-series graph from multi-dim array.
HighChart script
var chart_PT1 = new Highcharts.Chart({
chart: {
height: 532,
renderTo: 'review_high_container'
},
title: {
text: 'IO Signal Data'
},
subtitle: {
text: 'Source: GPS Modem'
},
yAxis: {
title: {
text: 'Value'
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
xAxis: {
type: 'datetime',
labels: {
enabled: true,
formatter: function () { try { return ddd[i][this.value][0]; } catch (err) { } },
}
},
});
for (i = 0; i < ddd.length; i++) {
chart_PT1.addSeries({ name: name[i], data: ddd[i], turboThreshold: 5000 });
}
My data array
Its an multi dim array signals=[] say 3 as shown below
signals[0] = {"Signal1",signalData[]} <=== signalData has say 20 data
signals[1] = {"Signal2",signalData[]} <=== signalData has say 10 data
signals[2] = {"Signal3",signalData[]} <=== signalData has say 80 data
signalData[] is expected to have the data for the signal say
signalData[0] ==> Value, TimeReceived,ID
signalData[1] ==> Value, TimeReceived,ID
signalData[2] ==> Value, TimeReceived,ID
.
.
.
signalData[20] ==> Value, TimeReceived,ID
Likewise signals[1].signalData[] and signals[2].signalData[] is expected to have data for its corresponding signals.
Each data in signalData includes data for value,TimeReceived and ID. So signals[0].signalData will contain array of data for signalOne; signals[1].signalData will contain array of data for signalTwo;
signals[2].signalData will contain array of data for signalThree;
and so on...
The graph would show one line for each signal(in this case 3 lines)
My Problem
I not able to label the X-Axis with the Time Value available inside the array - signals.signalData. Each signal may or may not have the same time within the array signals. So labelling by signals.signalData[0] do not pose right for other series signals.signalData[1],signals.signalData[2]....
How do I label X-Axis for the multi series?
Whats the best option to do this? as I see the time value inside the array say signals.signalData[0] may not be aligned with the the time value inside signals.signalData[1]
Update
Sample Data
signals ={
{ "SignalOne", {{"42","2/20/2018 05:25:09","S11"},{"99","2/20/2018 06:17:13","S12"},{"89","2/20/2018 07:25:09","S13"} },
{ "SignalTwo", {{"118","2/20/2018 05:25:09","S21"},{"33","2/20/2018 06:17:13","S22"} }
{ "SignalThree", {{"333","2/20/2018 05:25:09","S31"},{"43","2/20/2018 06:17:13","S32"},{"43","2/20/2018 06:17:13","S33"},{"43","2/20/2018 06:17:13","S34"} }
};

Highcharts navigator not working with data set

Can someone please take a look at this example? It works when I use a smaller data set, but when I use a larger historical data set, it stops working and the data series does not render. Please help.
Small data set example - http://jsfiddle.net/Yrygy/250/
Large data set example (SERIES DOES NOT RENDER) - http://jsfiddle.net/Yrygy/249
var chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
height: 120
},
navigator: {
series: {
data: chartData
}
},
series: [{
data: [null],
markers: {
enabled:true
}
}]
});
You need to have your data sorted in ascending time order. Currently your "large" data set is not.
There is a couple of problems. First of all, as said #wergeld, you need to sort your data:
chartData.sort(function(a,b) { return a[0] - b[0]; });
Then the problem is with setting option for navigator:
navigator: {
series: [{
name: 'MSFT',
data: chartData
}]
},
When should be an object, not an array:
navigator: {
series: {
name: 'MSFT',
data: chartData
}
},
And the last one, do you really need to set xAxis.min/max ? Escpecially to values 2 and 4. when you have timestamps like
Working demo: http://jsfiddle.net/Yrygy/253/

Highchart ticks start point change when categories names are set

I have a chart made with highcharts.js.
The graph works the way I wanted but then if I try to set the categories (programmatically or not) somehitng strange happen, the tick become smaller and move to the centre leaving a big space on the sides of the graph.
BEFORE:
AFTER:
$(function () {
$('#container').highcharts({
chart: {
renderTo: 'graph',
type: 'area',
},
xAxis: {
title: {
text: ''
},
startOnTick: false,
endOnTick: false,
tickmarkPlacement: 'on',
},
series: [{
data: [['aa',29.9], ['bb',71.5], ['cc',106.4],['dd', 129.2 ]]
}],
});
// the button handler
$('#button').click(function() {
var chart = $('#container').highcharts();
chart.xAxis[0].setCategories(['bb', 'bb', 'cc', 'dd']);
});
});
See this JsFiddle:
http://jsfiddle.net/MaurizioPiccini/d746v/3/
It all happens when you press the button (the categories can be set in the xAxis as well giving the same problem).
Is it possible to have named categories to start and end at the graph extremes?
You can use workaround which, updatse your axis with defined min/max value.
chart.xAxis[0].update({
categories: ['bb', 'bb', 'cc', 'dd'],
min: 0.5,
max: 2.5
});
http://jsfiddle.net/d746v/6/
I found a solution that is also reporteed here:
http://forum.highcharts.com/highcharts-usage/highchart-ticks-start-point-change-when-categories-names-are-t29052/
The solution is not to use categorized xAxis but linear or datetime with label formatter like this:
xAxis: {
labels: {
formatter: function(){
return categories[this.value];
}
}
}
where categories is an array of categories.
It looks like that is the only way to make the chart behave this way.

getting additional value fields from data source for dx.chartjs doughnut chart

For my chart, I use pieChartDataSource as my doughnut chart's data source. I've been pouring over the documentation to figure out a way to, instead of labeling the segments with valueField, display an additional field that is not the argumentField.
In my console, I know that pieChartDataSource has the field I am looking for. It is an array of objects. Each object has several fields of which I have product as the argumentField and count as the valueField. My presumption is that I somehow have to use the tagField in order to pass additional properties.
To reiterate, I want to display owner (a third value), instead of product in the segment label of my chart. How would I customize the label so that it shows the owner?
// ...
dataSource: pieChartDataSource,
// ...
series: { type: 'doughnut',
argumentField: 'product',
valueField: 'count',
tagField: 'owner',
valueType: 'numeric',
label: { visible: true,
font: {
family: 'sans-serif',
},
connector: { visible: false },
radialOffset: 0,
position: 'inside',
rotationAngle: 0,
customizeText: function () {/* use tagField here? */},
},
// ...
Can retrieve tag from point, that is an attribute of customizeText parameter
label: {
customizeText: function () {
return this.point.tag;
}
}

Kendo + Angular chart data

I'm trying out Kendo charts with angular, and I have problem displaying data, here is my code:
HTML:
<div kendo-chart="rchart" data-k-options="chartOptions" data-role="chart" class="k-chart" style="position: relative;"></div>
Javascript:
resultService.getResult().then(function (resultResponse) {
$scope.data = resultResponse.data;
$scope.oldReps = _.pluck($scope.data.TreningScores.Item1, 'Item2');
$scope.newReps = _.pluck($scope.data.TreningScores.Item2, 'Item2');
$scope.categories = _.pluck($scope.data.TreningScores.Item1, 'Item1');
});
$scope.chartOptions = {
legend: {
position: "bottom"
},
seriesDefaults: {
type: "column"
},
series: [{
name: "Total Visits",
data: $scope.oldReps
}, {
name: "Unique visitors",
data: $scope.newReps
}],
valueAxis: {
line: {
visible: false
}
},
tooltip: {
visible: true,
format: "{0}"
}
};
The problem is chart isn't updated after data is fetched from server, I've tried refreshing chart like this (but with no luck):
$scope.chart = {
refreshChart : function() {
$scope.rchart.refresh();
},
};
And calling this method in:
resultService.getResult().then(function (resultResponse) {});
And I've also tried to define $scope.chartOptions inside same function, but nothing. Is there any way to fix this ?
It's not well documented, but to get a UI control with remote data-binding to update after data has been returned from a server requires both watching the collection for updates from the Angular side and rebinding the data object to its respective UI control from the Kendo side.
In your controller, watch for changes to your data objects using $watchCollection, and update the objects/properties which are bound to those collections:
// API call
$http.get('...').success(function(data){
$scope.data = data;
});
// KendoUI config object
$scope.chart = {
dataSource: {
data: $scope.data
}
};
// Watch for changes to $scope.data
$scope.$watchCollection('data', function(newData) {
// Update data bindings with changes
$scope.chart.dataSource.data = newData;
});
In your view, define the object your UI control should be bound to when changes are made via the k-rebind Angular-Kendo directive:
<div kendo-chart k-options="chart" k-rebind="chart"></div>
Here is an example of a chart bound to remote data:
http://codepen.io/micjamking/pen/4980a5e22cbd4de01264fadae5f25f06
The use of $watchCollection to track and assign the dataSource.data in the accepted answer and others is a needlessly convoluted approach.
Here's a straightforward implementation:
view:
<div kendo-chart k-theme='metro' k-options="chart" k-rebind="chart"></div>
controller:
$scope.chart = {
dataSource: new kendo.data.DataSource({
data: [{ title: "Loading", value: 100, color: '#EFEFEF' }]
}),
series: [{ field: 'value', categoryField: 'title', padding: 0, holeSize: 25 }],
seriesDefaults: { type: 'donut', startAngle: 90 }
};
Using the dataSource.data() method instead of assigning dataSource.data as an array is the key here:
payrollService.load(userId).then(function (result) {
$scope.chart.dataSource.data(result.items); //where result.items is an array like so:
//[
// { title: "Net Pay", value: 60, color: '#6BAE4B' },
// { title: "Taxes", value: 15, color: '#ED6347' },
// { title: "Deductions", value: 25, color: '#8161C2' }
//]
});
Codepen Demo:
http://codepen.io/TaeKwonJoe/pen/WGOpEv
I think your problem is that $scope.chartOptions is set before the data of the resultService is retrieved. Angular is returning an empty array in this case and filling in the data later.
But $scope.chartOptions not not updated with new data.
You could try with
$scope.$watchCollection('oldReps', function(newData, oldData) {
$scope.chartOptions.series[0].data = newData;
});
$scope.$watchCollection('newReps', function(newData, oldData) {
$scope.chartOptions.series[1].data = newData;
});
So chartOptions are updated if oldReps or newReps have changed.
I had a similiar problem and $watchCollection saved my day (Caching data and updating another object for an chart does not work)

Categories

Resources