Factory looked so simple, but I have no idea what this error is?!?
When my controller calls ReportData.add I get
Error: [$injector:undef]
app.factory('ReportData', function() {
var factoryData = [];
var factoryService = {};
factoryService.add = function(myData) {
console.log('FACTORY ADD: ' + myData)
factoryData = myData;
};
factoryService.get = function() {
console.log('FACTORY GET: ' + factoryData)
return factoryData;
};
});
app.controller("test", function ($scope, $http, $location, ReportData) {
ReportData.add('SENDING DATA TO FACTORY');
console.log('get it: ' + ReportData.get());
})
You're not returning the object at the end of the function, this is why angular is unable to inject the factory.
When you inject the factory angular look for all the registered factories, then executes the corresponding function (only once) and cache the returning object that is the same object that angular will inject inside your controller.
If you don't return anything inside the function angular is not able to resolve your dependency.
app.factory('ReportData', function() {
var factoryData = [];
var factoryService = {};
factoryService.add = function(myData) {
console.log('FACTORY ADD: ' + myData)
factoryData = myData;
};
factoryService.get = function() {
console.log('FACTORY GET: ' + factoryData)
return factoryData;
};
return factoryService; //you're missing this return statement
});
Related
I'm trying to call a factory method in angular.js from my controller method and it throws an error 'is not a function'
Here's how the factory looks:
function getData($q) {
var getMessages = function(id) {
var deferred = $q.defer();
// deferred.notify('About to greet ' + name + '.');
GTS2_FIN_MU_Dist_Pct_Controller.getUltimates(
id,
function(result, event) {
if (event.status) {
// console.log(result);
var obj = JSON.parse(result);
deferred.resolve(obj);
} else {
deferred.reject("Error Processing the Request : " + event.message);
}
},
{ escape: false }
);
return deferred.promise;
};
return {
getMessages: getMessages,
};
}
app.factory("getData", getData);
The controller looks like:
app.controller("intlMassUpdateDistPctController", function($scope)
{ // define angular controller
$scope.ultimates = new Array; // define empty array to hold ultimate versions from VF remote action
// Calls controller method Remote Action and passes the ultimateId, and handles the result by storing it inside $scope.ultimateVersions
$scope.loadData = function(){
//$j214('#dialogNew').show();
var promise = getData.getMessages(''); //Calling factory method.. This is where U get the error
promise.then(function(obj) {
$scope.selectedForecastLocked = false;
var JSONdata = JSON.parse(obj);
$scope.ultimates = JSONdata.Ultimates;
$scope.gridOptions.api.setRowData($scope.ultimates);
........
}, function(reason) {
alert('Failed: ' + reason);
}, function(update) {
alert('Got notification: ' + update);
});
}
});
I have also defined the app.
var app = angular.module('intlMassUpdateDistPct', ['agGrid','ui.bootstrap']);
And Finally:
<body ng-app="myApp" >
<div ng-controller="intlMassUpdateDistPctController">
Can someone please help me identify what's missing.
Try to inject getData factory in the controller :
app.controller("intlMassUpdateDistPctController", function($scope,getData){
// your code...
})
Using Angular 1.5.9 on frontend and WebAPI 2 on server. Calling a standard $http.get in the service to Get() method on controller. This is returning the ViewModel that I want to populate variables with in angular controller.
var carListController = function ($http, $scope, carService) {
var model = this;
model.carList = carService.getCarsByMake('Bentley', 10);
console.log(model.carList);
model.cars = model.carList[0].cars;
model.totalCars = model.carList[0].totalCars;
model.numberOfPages = model.carList[0].numberOfPages;
};
I get this error:
Cannot read property 'cars' of undefined
As you can see the console.log is showing the model.carList so I know issue is in controller code populating the other variables. What am I missing here? Any help appeciated.
Edit: carService
var cars = [];
var carService = function ($http) {
var getCarsByMake = function (make, size) {
$http.get('http://localhost:50604/api/cars?make=' + make + '&size=' + size)
.then(function (response) {
// Success
angular.copy(response.data, cars);
}, function () {
// Failure
});
return cars;
};
return {
getCarsByMake: getCarsByMake
};
};
You have to wrap your $scope variable population in a promise approach.
Since the model.carList data is not yet loaded when the population is happening, it's normal that the error arrises (Cannot read property 'cars' of undefined; meaning carList is undefined).
In your service carService.getCarsByMake you have to return a promise( $http.get method)
Only when the promise is resolved, you can populate your $scopevariables with this data.
var carListController = function ($http, $scope, carService) {
var model = this;
carService.getCarsByMake('Bentley', 10).then(function(response){
model.carList = response.data;
model.cars = model.carList.cars;
model.totalCars = model.carList.totalCars;
model.numberOfPages = model.carList.numberOfPages;
});
};
Return $http request on the service side :
var cars = [];
var carService = function ($http) {
var getCarsByMake = function (make, size) {
return $http.get('http://localhost:50604/api/cars?make=' + make + '&size=' + size);
};
return {
getCarsByMake: getCarsByMake
};
};
I'm using a controller to call a service that will make an $http request, but right now I've only set my service to return a string because I want to make sure it works and is calling properly.
When I run it, I get the following error:
TypeError: monitorData.requestEvent(...).success is not a function
My code below:
Controller
(function() {
angular
.module('monitorApp')
.controller('eventCtrl', eventCtrl);
eventCtrl.$inject = ['$scope', '$routeParams', 'monitorData'];
function eventCtrl($scope, $routeParams, monitorData) {
var vm = this;
vm.eventid = $routeParams.eventid;
vm.event = {};
vm.getData = function(eventid) {
console.log("getData variable accessed");
monitorData.requestEvent(eventid)
.success(function(data) {
console.log(data);
})
.error(function(e) {
console.log("Error");
});
return false;
};
vm.getData(vm.eventid);
}
})();
Service
(function() {
angular
.module('monitorApp')
.service('monitorData', monitorData);
monitorData.$inject = ['$http'];
function monitorData($http) {
var requestEvent = function(eventid) {
var gas = "Event " + eventid + " requested.."
console.log(gas);
return gas;
};
return {
requestEvent : requestEvent,
};
}
})();
In order to be chained, it should return a settled promise.
monitorData.$inject = ['$http', '$q'];
function monitorData($http, $q) {
var requestEvent = function(eventid) {
var gas = "Event " + eventid + " requested.."
console.log(gas);
return $q.resolve(gas);
};
return {
requestEvent : requestEvent,
};
}
And by the way, success and error are deprecated legacy methods. It is always then and catch now.
success and error are part of the promise and you are not returning promise.
To make it work,you should use defer which resolve to success
and return promise which later chained with .success and .error
monitorData.$inject = ['$http','$q'];
var defer = $q.defer();
function monitorData($http) {
var requestEvent = function(eventid) {
var gas = "Event " + eventid + " requested.."
defer.resolve(gas)
return defer.promise;
};
return {
requestEvent : requestEvent,
};
}
these are my controllers:
.controller('recommendedJobsCtrl', function($q,$scope, $ionicSideMenuDelegate,$window,$http,dataShare) {
$scope.text='hey world';
$scope.post=function(){
dataShare.sendData($scope.text);
console.log('sent: ' + $scope.text);
}
})
.controller('jobsCtrl', function($scope,dataShare) {
$scope.words=dataShare.getData();
})
and this is my factory:
.factory('dataShare',function($rootScope){
var service = {};
service.sendData = function(data){
service=data;
$rootScope.$broadcast('data_shared', service);
},
service.getData = function(){
console.log('this.data is ' + service)
return service;
};
return service;
});
when the console.log prints, service is empty. How do i fix this ?
Factory code is not written correctly and also you should use angular service instead of creating factory since you have to only share data between controllers. Although both are singleton objects.
Lets do it with factory first
.factory('dataShare',function(){
var service = {
sendData: sendData,
getData: getData
};
var serviceData;
function sendData(data){
serviceData = data;
}
function getData(){
console.log('this.data is ' + serviceData);
return serviceData;
}
return service;
});
Lets do it with service
.service('dataShare',function(){
var serviceData;
this.sendData = function(data){
serviceData = data;
}
this.getData = function(){
console.log('this.data is ' + serviceData);
return serviceData;
}
});
To receive data you need to :
$rootScope.$on('data_shared', function(evt, data) {
});
It is async operation, so you cannot invoke it synchronously. If you want to abstract the communication, you need to implement you own observer/subscriber pattern.
I wrote the following factory service in AngularJS, but when I try to call the factory service in my RootController, I got the "undefined is not a function" error in my console.
MyService.js:
(function() {
angular.module('serviceTestApp')
.factory('MyService', ['$resource', '$log', '$q', '$http', MyService]);
function MyService($log, $resource, $http, $q) {
var name = "Tom";
var getName = function() {
return name;
}; //getName
var changeName = function(newName) {
name = newName;
}; //changeName
var getIP = function() {
var deferredObj = $q.defer();
$resource('http://jsonip.com').query().$promise.then(function(result) {
deferredObj.resolve(result);
}, function(errorMsg) {
deferredObj.reject(errorMsg);
});
return deferredObj.promise;
}; //getIP
return {
getName: getName,
changeName: changeName,
getIP: getIP
};
}
}());
in my RootController, I try to call the services, and everything worked until I call the getIP() service - return a promise object. Does anyone see anything wrong?
RootController.js:
(function() {
angular.module('serviceTestApp')
.controller('RootCtrl', ['$http', '$log', '$scope', 'MyService', RootCtrl]);
function RootCtrl($log, $scope, $http, MyService) {
var vm = this;
vm.message = "hello world from RootController";
MyService.changeName("Henry Tudor");
vm.message = "my name is: " + MyService.getName();
MyService.getIP().query().then(function(data) {
$log.info('in the promise, ip is: ' + data.ip);
vm.message = vm.message + ', your IP is ' + data.ip;
}, function(error) {
vm.message = vm.message + ', error: ' + error;
});
}
}());
It may sound stupid, but I've located the cause for the error:
The API used in the $resource() returns a single JSON object:
{"ip":"2601:0:b840:8077:a97f:ee9c:f5b8:1643","about":"/about","Pro!":"http://getjsonip.com"}
however, the query() expects an array, not a JSON object.
After changing to another API that returns an array in JSON format, it works. Sigh, wasted my 2 hours.
thanks everyone
in order to use your service like that
MyService.getName()
that mean you have a service called MyService and returns a function called getName
but in your case it dosen't you have to change
your return to something like that
return {
getName: function() {return getName();},
changeName: function() {return changeName();},
getIP: function() {return getIP();}
};