Angularjs - cannot pass data from factory to controller - angularjs

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);
}

Related

When open a modal on page load but modal open two times

I want to develop a angularjs web application where I need when url has a query string id then open a modal against the id. The modal open successfully but problem is the modal open twitch time. So Please suggest me how to prevent to open modal two times and ensure that the modal open only one time when query string has a id. My code is below:
myApp.controller('othersObjectiveListController', ['$scope', '$uibModal', 'EmployeeObjectiveService', '$routeParams', function ($scope, $uibModal, EmployeeObjectiveService, $routeParams) {
var items = [];
for (i = 0; i < 100; i++) {
items[i] = i;
}
$scope.test = items;
$scope.StatusBy = [{ id: 1, value: true, label: 'Approve' }, { id: 2, value: false, label: 'Pending' }];
//Angular Code for Multiple column show and hide
$scope.dropConfig = {
scrollable: true,
scrollableHeight: '340px',
showCheckAll: false,
showUncheckAll: false
}
EmployeeObjectiveService.getOtherObjectiveColumnList().then(function (response) { $scope.AllColumn = response.data });
EmployeeObjectiveService.getOtherSelectedColumn().then(function (response) { $scope.SelectedColumn = response.data });
EmployeeObjectiveService.getOtherObjectiveSelected().then(function (response) { $scope.SelectCol = response.data });
function changeColumnViewShow(item) {
if (item.id == 1) {
$scope.SelectCol.EmployeeID = !$scope.SelectCol.EmployeeID;
} else if (item.id == 2) {
$scope.SelectCol.EmployeeName = !$scope.SelectCol.EmployeeName;
} else if (item.id == 3) {
$scope.SelectCol.Code = !$scope.SelectCol.Code;
} else if (item.id == 4) {
$scope.SelectCol.Title = !$scope.SelectCol.Title;
} else if (item.id == 5) {
$scope.SelectCol.KPI = !$scope.SelectCol.KPI;
} else if (item.id == 6) {
$scope.SelectCol.Target = !$scope.SelectCol.Target;
} else if (item.id == 7) {
$scope.SelectCol.Weight = !$scope.SelectCol.Weight;
} else if (item.id == 8) {
$scope.SelectCol.Note = !$scope.SelectCol.Note;
} else if (item.id == 9) {
$scope.SelectCol.Status = !$scope.SelectCol.Status;
}
}
$scope.changeEvents = {
onItemSelect: function (item) {
changeColumnViewShow(item);
},
onItemDeselect: function (item) {
changeColumnViewShow(item);
}
};
//End Column hide show function
// This Section for Pagination for Pending List
$scope.ViewItems = [{ value: 10, id: 10 }, { value: 20, id: 20 }, { value: 50, id: 50 }, { value: 100, id: 100 }];
$scope.selectItem = $scope.ViewItems[0];
$scope.ViewPerPage = 10;
$scope.setitemsPerPage = function (num) {
$scope.ViewPerPage = num.value;
}
//This Section for Modal
$scope.viewObjectives = function (data) {
var modalInstance = $uibModal.open({
templateUrl: '/View/Modal View/OtherObjective.html',
scope: $scope,
size: 'lg',
});
}
function ViewObjective($uibModalInstance, code) {
$scope.id = code;
}
$scope.initial = function () {
var id = $routeParams.id;
if(id!=null)
$scope.viewObjectives(id);
}
$scope.initial();
//PDF Create
$scope.CreatePDF = function () {
$('#objectivelist').tableExport({
type: 'pdf',
fileName: 'ObjectiveList',
jspdf: {
orientation: 'l',
format: 'a4',
margins: { left: 10, right: 10, top: 20, bottom: 20 },
autotable: {
styles: {
fontSize: 10,
fillColor: 'inherit',
textColor: 'inherit'
},
tableWidth: 'auto'
}
}
});
}
}])

data.result.response.airport.pluginData.schedule.arrivals.data[i].flight.airport[i] is undefined

hi again am build app for schedule airport information for data flight airport arr and dep , i have many arrays and am confused to use i try to use this way to coding but not working .
json array
enter image description here
error : http://www.3rbz.com/uploads/49fe2aa262501.png
(function() {
var app = angular.module('starter.bgw', ['ionic']);
app.controller('myctlr', function($scope, $http) {
var service_url = "/airport.json?code=bgw";
$http.get(service_url)
.success(
function(data) {
$scope.city= data.result.response.airport.pluginData.details.name;
console.log(data);
bord = [];
for(i=0; i<36; i++) {
var arr = data.result.response.airport.pluginData.schedule.arrivals.data[i].flight.airport[i].origin[i].name;
bord.push({ arr: arr });
}
})
})
})();
json
{
"result": {
"response": {
"airport": {
"pluginData": {
"schedule": {
"arrivals": {
"page": {
"current": 1,
"total": 2
},
"data": [
{
"flight": {
"airport": {
"origin": {
"name": "Bahrain International Airport"
}
}
}
}
]
}
}
}
}
}
}
}
get error Error: data.result.response.airport.pluginData.schedule.arrivals.data[i].flight.airport[i] is undefined
airport[i] isn't an array (also origin) but an object in your json example:
{
"flight": {
"airport": {
"origin": {
"name": "Bahrain International Airport"
}
}
}
}
Then you can get name value with this line:
data.result.response.airport.pluginData.schedule.arrivals.data[i].flight.airport.origin.name;
data obviously has to have 36 elements for this loop: for(var i=0; i<36; i++)
Try this.
As per your json, only data is array (I assume you have atleast 36 objects in data array)
(function() {
var app = angular.module('starter.bgw', ['ionic']);
app.controller('myctlr', function($scope, $http) {
var service_url = "/airport.json?code=bgw";
$http.get(service_url)
.success(
function(data) {
$scope.city= data.result.response.airport.pluginData.details.name;
console.log(data);
bord = [];
for(var i=0; i<36; i++) {
var arr = data.result.response.airport.pluginData.schedule.arrivals.data[i].flight.airport.origin.name;
bord.push({ arr: arr });
console.log(arr);
}
})
})
})();

Template using in Angularjs

i'm using ng-duallist template. I got it here : https://github.com/tushariscoolster/ng-duallist
I want to use twice in the same html controller. I have created new variable for it but content is always same so how can I separate it?
I want to add vm2 to other data content but always same value added two duallist
hmtl code
directives code
var existingEntries = [];
var vm = this;
vm.property = 'controller';
activate();
function activate() {
vm.leftValue = [];
vm.rightValue = [];
vm.addValue = [];
vm.removeValue = [];
function loadMoreLeft() {
for (var i = 0; i < $scope.reasonOfLack.length; i++) {
vm.leftValue.push({
'name': $scope.reasonOfLack[i]
});
}
};
function loadMoreRight() {
}
vm.options = {
leftContainerScrollEnd: function () {
},
rightContainerScrollEnd: function () {
},
leftContainerSearch: function (text) {
console.log(text)
vm.leftValue = $filter('filter')(leftValue, {
'name': text
})
},
rightContainerSearch: function (text) {
vm.rightValue = $filter('filter')(rightValue, {
'name': text
})
},
leftContainerLabel: 'Uygunsuzluk Sebepleri',
rightContainerLabel: 'Seçilen Uyunsuzluk Sebepleri',
onMoveRight: function () {
console.log('right');
console.log(vm.addValue);
},
onMoveLeft: function () {
console.log('left');
console.log(vm.removeValue);
}
};
loadMoreLeft();
var leftValue = angular.copy(vm.leftValue)
var rightValue = angular.copy(vm.rightValue)
}

How to redraw flot chart in 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.

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