How to redraw flot chart in angularjs? - angularjs

I am using flot chart Angularjs directive to draw a stacked bar chart. When I make a async call to an end point to fetch data for chart, it is unable show up. I suspect it needs to redraw. There is a draw() function which looks like re draws flot chart. Please help me re-draw my flot chart in Angularjs.
<flot dataset="tasksRunData" options="tasksRunChartOptions" class="center-block" width="100%" height="400px" id="reportTasksRunRange.id"></flot>
angular.module('myApp').controller('Step2Controller', function($scope, $location, $interval, dialogs, $modal, $transition, ReportingService) {
...
$scope.tasksRunData = mainArray;
$scope.tasksRunChartOptions = {
legend: {
show: true,
margin: 2
},
xaxis: {
ticks: yaxisArray,
alignTicksWithAxis: "right"
},
grid: {
labelMargin: 10,
hoverable: true,
borderWidth: 0
},
series: {
stack: true
},
colors: colorCodesArray,
tooltip: true
};
...
$scope.redrawTasksRunDataHistoByChart();
...
$scope.redrawTasksRunDataHistoByChart = function() {
$scope.tasksRunData.draw(); //TypeError: undefined is not a function
alert("AAAA");
}
});
Update
ReportService.getTasksRunDateHistoByType().then(function(result) {
$scope.renderTasksRunDateHistoByType(result);
});
$scope.renderTasksRunDateHistoByType = function(jsonInput) {
console.log(json[RUN_AGG_BY_DATE_HISTO].aggregations[TASK_TYPE_AGG].buckets);
var yaxis = [];
var buckets = json[RUN_AGG_BY_DATE_HISTO].aggregations[TASK_TYPE_AGG].buckets;
var log = [];
var mainArray = [];
var colorCodes = ["#5C832F","#7B52AB","#263248","#AB1A25","#FF8598","#AB1A25","#FEB41C","#193441","#193441","#BEEB9F","#E3DB9A","#917A56"],
idx = 0;
angular.forEach(buckets, function(value, key) {
this.push(key + ': ' + value +", "+value["key"]);
var dataArray = [], index = 0;
console.log(JSON.stringify(value[RUN_OVER_TIME_KEY]["buckets"]));
angular.forEach(value[RUN_OVER_TIME_KEY]["buckets"], function(value, key) {
var dataArr = [];
dataArr.push('['+index+', '+value["doc_count"]+']');
dataArray.push(dataArr);
yaxis.push(JSON.parse('['+index+', "'+$scope.translate(value["key"])+'", "'+value["key"]+'"]'));
index++;
}, log);
var barObject = '"bars": {"show": "true", "barWidth":0.8, "fillColor": "'+colorCodes[idx]+'", "order": 1, "align": "center"}';
var object = '{ "data": ['+dataArray+'], "label": "'+value["key"]+'", '+barObject+'}';
mainArray.push(JSON.parse(object));
idx++;
}, log);
console.log(yaxis);
$scope.tasksRunData = mainArray;
$scope.tasksRunChartOptions = {
legend: {
show: true,
margin: 2
},
xaxis: {
//ticks:[[0,'Oct 4'],[1,'Oct 5'],[2,'Oct 6'],[3,'Oct 7'],[4,'Oct 8'],[5,'Oct 9']],
ticks: yaxis,
alignTicksWithAxis: "right"
},
grid: {
labelMargin: 10,
hoverable: true,
borderWidth: 0
},
series: {
stack: true
},
colors: colorCodes,
tooltip: true
};
};
angularjs service
angular.module('myApp')
.service('ReportService', function ReportService($http, $q) {
var getTasksRunDateHistoByType = function() {
var deferred = $q.defer();
$http({
method: 'POST',
url: "http://localhost:4040/reports/taskRun",
data: '{ "client_user_info": { "client_id": "MU03"}}'
}).
success(function(result, status, headers, config) {
deferred.resolve(result);
}).
error(function(result, status, headers, config) {
console.log("Error");
});
return deferred.promise;
};
return {
getTasksRunDateHistoByType: getTasksRunDateHistoByType
};
});

Looking at the source code to the directive, it'll redraw automatically when $scope.dataset changes.
$scope.redrawChart = function() {
var tmp = [];
for (var i = 0; i < 10; i++){
tmp.push([i,Math.random() * 10]);
}
$scope.dataset = [{ data: tmp }];
};
Here's an example.
EDITS FOR UPDATES
I'm having a hard time following your code, but in the end, you'll end up in the $scope.renderTasksRunDateHistoByType with data in the variable jsonInput. You then store some variable mainArray (which doesn't exist as far as I can tell) into other $scope level variables. I never see you assign data back to $scope.dataset. This is what the flot directive is watching to trigger a redraw. It's just that simple.
$scope.renderTasksRunDateHistoByType = function(jsonInput) {
$scope.dataset = [{
data: jsonInput
}];
//console.log(jsonInput);
//$scope.tasksRunData = mainArray;
//$scope.tasksRunChartOptions
//getting data here once response is received from server
};
See updates here.

Related

ui-calendar cell background color not displaying for the first time

I am trying to get a list of dates from Rest and change the background color of those dates using dayRender .But when i try to do it the color is not getting changed for the first time.If i go to next month and come back to the month,it will work perfectly.Here are screenshots to make it more clear.
When i load the page
When i move from june to july
When move back to june
Here is my code .rest/leave/holidayList is the rest url for retreiving dates from db.
app.factory('calendarSer', ['$http', '$rootScope', 'uiCalendarConfig', function($http, $rootScope, uiCalendarConfig) {
return {
displayCalendar: function($scope) {
$http.get("rest/leave/holidayList", {}).success(function(data, status, headers, config) {
$scope.holidayList = data;
console.log($scope.holidayList);
}).error(function(data, status, headers, config) {
alert("error");
});
$calendar = $('[ui-calendar]');
var date = new Date(),
d = date.getDate(),
m = date.getMonth(),
y = date.getFullYear();
$scope.changeView = function(view) {
$calendar.fullCalendar('changeView', view);
};
var m = null;
if ($scope.selectable == "Yes") {
m = true;
} else {
m = false;
}
/* config object */
$scope.uiConfig = {
calendar: {
lang: 'da',
height: 400,
editable: true,
selectable: m,
header: {
left: 'month basicWeek basicDay',
center: 'title',
right: 'today prev,next'
},
eventClick: function(date, jsEvent, view) {
$scope.alertMessage = (date.title + ' was clicked ');
alert("clicked" + date.title);
},
select: function(start, end, allDay) {
var obj = {};
obj.startDate = start.toDate();
obj.endDate=moment(end - 1 * 24 * 3600 * 1000).format('YYYY-MM-DD');
$rootScope.selectionDate = obj;
$("#modal1").openModal();
// calendar.fullCalendar('unselect');
},
dayRender: function (date, cell) {
var today = new Date();
today=moment(today).toDate();
var end = new Date();
end=moment(end).toDate();
end.setDate(today.getDate()+7);
date=moment(date).toDate();
angular.forEach($scope.holidayList,function(value){
if(((moment(value.holiday_date).format("YYYY-MM-DD"))==moment(date).format("YYYY-MM-DD")))
{
cell.css("background-color", "red");
}
});
},
eventRender: $scope.eventRender,
}
};
$scope.events = [];
$scope.eventSources = [$scope.events];
$http.get($scope.url, {
cache: true,
params: {}
}).then(function(data) {
console.log(data);
$scope.events.slice(0, $scope.events.length);
angular.forEach(data.data, function(value) {
console.log(value.title);
if (value.approvalStatus == "Approved") {
var k = '#114727';
} else {
k = '#b20000'
}
$scope.events.push({
title: value.signum,
description: value.signum,
start: value.startDate,
end: value.endDate,
allDay: value.isHalfDay,
stick: true,
status: value.approvalStatus,
backgroundColor: k
});
});
});
}
}
}]);
Remember that the REST call is asynchronous. Just put all the code that set colours inside a promise, so when the REST service rest/leave/holidayList responses, then you paint the colours. You can use nested promises if needed.
Here's some code:
$http.get('rest/leave/holidayList').then(function(response) {
// success
$scope.holidayList = data;
/* config object */
$scope.uiConfig = {
calendar: {
/* calendar code */
}
}
}, function(response) {
// error handler
});
To compare the use of "success" and "then" have a look at:
https://stackoverflow.com/a/16385350/8058079

Angularjs - cannot pass data from factory to controller

I'm new to angular and find myself stuck. I am trying to pass data from a factory to a controller and it returns undefined no matter what I have tried. Can anyone help? Ultimately I will need to access the Time and Output variables in the controller to pass into a chart.
Code:
WaveChart.factory('waveService', function($http) {
var getWaveDataFunction = function(beach){
$http.get(waveData[beach])
.success(function(data) {
console.log('yay it works');
return data;
var Time = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
}
var Output = [];
for (var i = 0; i < data.length; i++) {
Output.push(data[i].Output);
}
//console.log(Time);
//console.log(Output);
});
}
return {
getWaveData: getWaveDataFunction
};
});
WaveChart.controller('chartCtrl', function ($scope, waveService, $state) {
var currentBeach = $state.current.title.toLowerCase();
$scope.waveData = waveService.getWaveData(currentBeach);
console.log($scope.waveData);
Tried to update based on refactored code provided in example 2 below, but $scope.waveData is now returning empty array. I am providing updated (and more complete) code:
Chart.js:
var WaveChart = angular.module('WaveChart', ["highcharts-ng"]);
var waveData = {
waimea: "assets/wave-waimea.json",
pauwela: "assets/wave-pauwela.json",
hanalei: "assets/wave-hanalei.json"
}
WaveChart.factory('waveService', function($http) {
var getWaveDataFunction = function(beach){
return $http.get(waveData[beach])
.then(function(data) {
var Time = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
}
var Output = [];
for (var i = 0; i < data.length; i++) {
Output.push(data[i].Output);
}
return { time: Time, output: Output };
});
}
return {
getWaveData: getWaveDataFunction
};
});
WaveChart.controller('chartCtrl', function ($scope, waveService, $state) {
var currentBeach = $state.current.title.toLowerCase();
waveService.getWaveData(currentBeach)
.then(function(waveData){
$scope.waveData = waveData;
console.log($scope.waveData);
$scope.chartConfig = {
title: {
text: 'Wave Height Observations'
},
subtitle: {
text: 'according to the PacIOOS'
},
options: {
chart: {
type: 'spline'
},
plotOptions: {
spline: {
lineWidth: 2,
states: {
hover: {
lineWidth: 3
}
},
marker: {
enabled: false
}
},
area: {
fillColor: {
linearGradient: { x1: 0, y1: 0},
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
},
marker: {
enabled: true
},
lineWidth: 1,
states: {
hover: {
lineWidth: 2
}
},
threshold: null
}
}
},
xAxis: {
name: "Time",
categories: waveData.time
},
yAxis: {
title: {
text: 'Wave Height'
},
labels: {
formatter: function () {
return this.value;
}
}
},
tooltip: {
crosshairs: true,
shared: true
},
plotOptions: {
spline: {
marker: {
radius: 4,
lineColor: '#666666',
lineWidth: 1
}
}
},
series: [{
name: 'Wave Height',
marker: {
symbol: 'square'
},
data: waveData.output
}]
}
});
});
wave-waimea.json
[
{"Time":"00:09", "Output":4.40},
{"Time":"00:39", "Output":4.63},
{"Time":"01:09", "Output":4.72},
{"Time":"01:39", "Output":4.69},
{"Time":"02:09", "Output":4.20},
{"Time":"02:39", "Output":4.92},
{"Time":"03:09", "Output":4.89},
{"Time":"03:39", "Output":4.89},
{"Time":"04:09", "Output":5.18},
{"Time":"04:39", "Output":5.18},
{"Time":"05:09", "Output":5.41},
{"Time":"05:39", "Output":5.71},
{"Time":"06:09", "Output":5.91},
{"Time":"06:39", "Output":5.68},
{"Time":"07:09", "Output":6.33},
{"Time":"07:39", "Output":6.53},
{"Time":"08:09", "Output":6.23},
{"Time":"08:39", "Output":6.63},
{"Time":"09:09", "Output":7.58},
{"Time":"09:39", "Output":6.43},
{"Time":"10:09", "Output":6.86},
{"Time":"10:39", "Output":6.89},
{"Time":"11:09", "Output":7.25},
{"Time":"11:39", "Output":7.35},
{"Time":"12:09", "Output":7.12},
{"Time":"12:39", "Output":7.15},
{"Time":"13:09", "Output":6.73},
{"Time":"13:39", "Output":6.89},
{"Time":"14:09", "Output":6.63},
{"Time":"14:39", "Output":7.48}
]
This is a textbook use case of promises. Please see angular docs for details of working with promises in angularjs.
In this case, you have two options and I would recommend the second one as you do have a bit of post-processing after the http response comes through. (I've included the first one mainly to illustrate the most basic way to get an asynchronous $http response back to a controller)
1 - Return the $http promise itself and handle the response in the controller:
WaveChart.factory('waveService', function($http) {
var getWaveDataFunction = function(beach){
return $http.get(waveData[beach]);
};
return {
getWaveData: getWaveDataFunction
};
});
WaveChart.controller('chartCtrl', function ($scope, waveService, $state) {
waveService.getWaveData(currentBeach)
.success(function(data) {
console.log('yay it works');
var Time = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
}
var Output = [];
for (var i = 0; i < data.length; i++) {
Output.push(data[i].Output);
}
//console.log(Time);
//console.log(Output);
$scope.waveData = {
time: Time,
output: Output
};
});
});
2 - create a new promise and resolve it from the $http.success callback
WaveChart.factory('waveService', function($http) {
var getWaveDataFunction = function(beach){
// return then $http.get promise
return $http.get(waveData[beach])
.then(function(data) {
console.log('yay it works');
var Time = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
}
var Output = [];
for (var i = 0; i < data.length; i++) {
Output.push(data[i].Output);
}
//console.log(Time);
//console.log(Output);
// return value here is what the $http.get promise will resolve
return { time: Time, output: Output };
});
}
return {
getWaveData: getWaveDataFunction
};
});
WaveChart.controller('chartCtrl', function ($scope, waveService, $state) {
var currentBeach = $state.current.title.toLowerCase();
// use .then callback to wait for the promise to be resolved
waveService.getWaveData(currentBeach)
.then(function(waveData){
$scope.waveData = waveData;
console.log($scope.waveData);
});
EDIT:
Just noticed you can optimize your result processing by combining the two loops over data into one:
var Time = [];
var Output = [];
for (var i = 0; i < data.length; i++) {
Time.push(data[i].Time);
Output.push(data[i].Output);
}

Show a polygon and polyline on map with multiple lat long accurately

I have added multiple cities with two types of lat long in database.
Type 1. Area
Type 2. Road
Type 1 data use in polygon, and Type 2 data use in polylines. But the polygon and polyline are not show clearly like in image a blue area make through polygon and black line make through using polylines. please let me know how can i draw accurate area(need low opacity but properly fill color area) and a line(only single line)
My code is :
.controller('AllDistrictLayer', function ($scope, $state, $ionicLoading, $stateParams, $localStorage) {
$scope.loading = $ionicLoading.show({
content: 'Getting current location...',
showBackdrop: true
});
var map = null;
var mapDefaults = {
zoom: 8,
center: null,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var mapPosition = new google.maps.LatLng(30.722727472053084, 76.6519546508789);
mapDefaults.center = mapPosition;
map = new google.maps.Map(document.getElementById("map"), mapDefaults);
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var polyline;
var marker;
var array_data = [];
var array_path = [];
var i = 0;
var j = 0;
$(function () {
setTimeout(loadajax, 10000);
});
function loadajax() {
$.ajax({
url: "http://webapi.nuavnu.ca/api/route",
type: 'GET',
data: { type: 1 },
success: function (data) {
$ionicLoading.hide();
console.log(data);
var dbMapPoints = JSON.parse(data.AllrouteofMC);
mapdata(dbMapPoints);
}
});
$.ajax({
url: "http://webapi.nuavnu.ca/api/route",
type: 'GET',
data: { type: 2 },
success: function (data) {
$ionicLoading.hide();
initialize(JSON.parse(data.AllrouteofMC));
}
});
}
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
// ** For Type 1 Area**
function mapdata(dbMapPoints) {
$.each(dbMapPoints, function (key, index) {
var latlng = [];
var mycolor = getRandomColor();
$.when($.each($.grep(dbMapPoints, function (n, i) { return (n.MCId === index.MCId); }), function () {
latlng.push(new google.maps.LatLng(this.GPS_Lat, this.GPS_Long));
mapPoly = new google.maps.Polygon({
paths: latlng,
strokeColor: "#FF8800",
strokeOpacity: 0.00,
strokeWeight: 3,
fillColor: "blue",
fillOpacity: 0.2
});
mapPoly.setMap(map);
})).done(function () {
});
});
}
});
// ** For Type 2 Roads**
function initialize(Mapdata) {
$(function () {
$.each(Mapdata, function (key, index) {
var latlng = [];
$.when($.each($.grep(Mapdata, function (n, i) { return (n.MCId === index.MCId); }), function () {
latlng.push(new google.maps.LatLng(this.GPS_Lat, this.GPS_Long));
var flightPath = new google.maps.Polyline({
path: latlng,
geodesic: true,
strokeColor: '#000000',
strokeOpacity: 1.0,
strokeWeight: 2
});
flightPath.setMap(map);
})).done(function () {
});
})
});
}
});
As Harold mentioned, please share jsFiddle for your code. As far as opacity and color fill of your lines and areas is concerned, it is correctly implemented in your map. From the looks of it, you are drawing multiple intersecting polygons which are adding to layers and reducing the opacity of fillColor. You need to pass all the LatLngs in a single array and plot them together in order to get an accurate area. You can do so by also passing them as an array of unique LatLng co-ordinates as shown here.
But can't comment on the rest without the code. For a small sample, look here:

Angular.js UI-Grid external filtering causes empty grid

When I externally filter data in ui-grid, in my success function, i see the correctly filtered data coming back from my service. But when I apply it, the grid is empty.
Initially, without filters, I get all the results I expect.
Any idea why the data isn't showing up?
app.controller('GridController', ['$scope', '$http', 'uiGridConstants', function ($scope, $http, uiGridConstants) {
var paginationOptions = {
pageNumber: 1,
pageSize: 25,
sort: null
};
$scope.gridOptions = {
enableFiltering: true,
useExternalSorting: false,
paginationPageSizes: [25, 50, 75],
paginationPageSize: 25,
useExternalPagination: true,
columnDefs: Mapping(type, $scope),
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.core.on.filterChanged($scope, function () {
HandleFiltering(this.grid.columns);
});
$scope.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) {
if (sortColumns.length == 0) {
paginationOptions.sort = null;
} else {
paginationOptions.sort = sortColumns[0].sort.direction;
}
Get();
});
gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize;
Get();
});
}
};
var HandleFiltering = function (gridColumns) {
for (var i = 0; i < gridColumns.length; i++)
{
CreateFilterObject(gridColumns[i], $scope);
}
Get();
}
var Get = function () {
debugger;
AjaxStart();
var searchRequest = SearchRequest(paginationOptions.pageNumber,
paginationOptions.pageSize,
$scope.objectFilter);
$.ajax({
type: "Post",
url: Service+ "/api/" + type + "/Search",
data: searchRequest,
success: function (data) {
$scope.gridOptions.totalItems = data[0];
$scope.gridOptions.data = data[1];
var firstRow = (paginationOptions.pageNumber - 1) * paginationOptions.pageSize;
debugger;
$scope.$apply();
AjaxEnd();
},
error: function (event, response, ajaxSettings, thrownError) {
AjaxError(response);
AjaxEnd();
},
});
}
Get();
}]);

set the data from controller into directive

I had created the directive file like this:
angular.module('myApp')
.directive('rGraph', function() {
return {
link: function ( scope, element, attrs ) {
var width = Math.max($("#graph-container").innerWidth(), 400);
var height = Math.max(width, 550);
var rgraph = new $jit.RGraph({
injectInto: 'graphcontainer',
width: width,
height: height,
background: {
CanvasStyles: {
strokeStyle: '#555'
}
},
Navigation: {
enable: true,
panning: true,
zooming: 10
},
Node: {
color: '#ddeeff',
overridable: true
},
Edge: {
color: '#C17878',
lineWidth: 1.0
},
onCreateLabel: function(domElement, node){
domElement.innerHTML = node.name;
domElement.onclick = function(){
rgraph.onClick(node.id, {
onComplete: function() {
Log.write("done");
}
});
};
},
onPlaceLabel: function(domElement, node){
style = domElement.style;
style.display = '';
style.cursor = 'pointer';
if (node._depth <= 1) {
style.fontSize = "0.8em";
style.color = "#ccc";
} else if(node._depth == 2){
style.fontSize = "0.7em";
style.color = "#494949";
} else {
style.display = 'none';
}
var left = parseInt(style.left);
var w = domElement.offsetWidth;
style.left = (left - w / 2) + 'px';
},
onBeforePlotNode: function(node){
if (node.data.type == 'group') {
node.setData('type', 'square');
} else if (node.data.type == 'judge') {
node.setData('type', 'star');
node.setData('dim', '8');
}
}
});
//Here I need to set the data
rgraph.loadJSON();
rgraph.refresh();
// Completing animations on every change was too much
// TODO come up with better way to watch for changes
rgraph.graph.eachNode(function(n) {
var pos = n.getPos();
pos.setc(-200, -200);
});
rgraph.compute('end');
rgraph.fx.animate({
modes:['polar'],
duration: 2000
});
}
};
});
And my controller is like this:
angular.module('myApp').controller('AnalysisCtrl', ['$scope', '$http', '$q', 'SearchService', function($scope, $http, $q, SearchService) {
$scope.graph_data = {
'id': 'judge_id',
'name': judge.name,
'type': 'judge',
'children': filters
}
My view is where I ma calling directive is like this:
<div id="graphcontainer" r-graph="graph_data"></div>
Now i need to add the data get from controller i.e data of $scope.graph_data into to the rgraph.loadJSON(); of directives.So how to do that.
Thanks
Sabbu

Resources