Angular JS Factory -- undefined is not an object issue - angularjs

I am new to Angular JS.
Here is my issue.
I am trying to create a factory .
But when I am calling factory it gives me an error
-Error undefined is not an object (evaluating: myService.getProjects)
Code:
myApp.factory('myService', function() {
return {
getProjects: function() {
return "Test";
}
};
});
myApp.controller('homeController',['$scope',function($scope,myService)
{
$scope.projects=myService.getProjects();
$scope.message="homeController";
}]);

You forgot to inject your service. Try this:
myApp.controller('homeController', ['$scope', 'myService', function($scope, myService) {
$scope.projects = myService.getProjects();
$scope.message = "homeController";
}]);

Related

Angularjs service undefined

Was building out an angular application, but am getting error undefined with the service or factory. Specifically "can not read property of setName undefined". I have went here to figure out my error. Even changed around my syntax figuring I maybe had something out of place but still throwing an undefined error.
Here is the controller:
(function() {
"use strict";
angular
.module("app", [])
.controller("mainCtrl", ["$scope", mainCtrl]);
function mainCtrl($scope, productService) {
$scope.testService = productService.setName("Data Service");
}
}());
Here is the service script:
(function() {
"use strict";
angular
.module("app")
.service("productService", function() {
var serviceObj = {};
serviceObj.name = '';
serviceObj.setName = function(newName) {
serviceObj.name = newName;
};
return serviceObj;
});
}());
Originally, I had the service as :
(function() {
"use strict";
angular
.module("app")
.service("productService", setName);
function setName(newName) {
var serviceObj = {};
serviceObj.name = '';
serviceObj.setName = function(newName) {
serviceObj.name = newName;
};
return serviceObj;
}
}());
I've had this problem recently and it seems to be that the function must be defined before the controller is created. I would recommend doing it the following way:
(function () {
"use strict";
//function
function mainCtrl($scope, productService) {
$scope.testService = productService.setName("Data Service");
}
//Controller and Module Init
angular
.module("app", [])
.controller("mainCtrl", mainCtrl);
//Inject requirements (This is needed for Minification)
mainCtrl.$inject = ["$scope", "productService"];
}());

Angular $q and $http for data binding not working

I'm trying to make a basic data pulling using a service and print it on screen when I have data, but something is not working.
My service:
mymodule.factory('MyService', function($http, $q) {
var service = {
getData: function() {
var dfd = $q.defer();
$http.get(apiServerPath).success(function (data) {
dfd.resolve(data);
});
return dfd.promise;
}
}
return service
}
My Controller:
mymodule.controller('myCtrl', ['$scope', 'MyService', function($scope, MyService) {
$scope.myvar = MyService.getData();
}
HTML
<div> {{myvar}} </div>
What I can see from the browser console -
The myvar object turn into a promise object
The success function is being called and 'data' has valid data in it
And for my question and issue - the controller's variable does not change when the defer object is resolving - why?
Promises are no longer auto-unwrapped as of Angular 1.2. In your controller do the following:
mymodule.controller('myCtrl', ['$scope', 'MyService', function($scope, MyService) {
MyService.getData().then(function success(data) {
$scope.myvar = data;
});
}

Jasmine unit test for AngularJS controller

I'm trying to unit test a controller in AngularJS using Jasmine. The controller has slightly different syntax than most documentation I can find and I'm getting this error...
http://errors.angularjs.org/1.2.15/$injector/unpr?p0=propertiesProvider%20%3C-%20properties
The controller...
myApp.controller('myController', function($scope, $rootScope, param) {
param.info.get().then(function(example){
//...
});
});
The test js...
describe('myApp', function() {
var $scope, $rootScope, param, createController, properties;
beforeEach(module('myApp'));
debugger; //runs
beforeEach(inject(function($injector) {
debugger; //doesn't run
$rootScope = $injector.get('$rootScope');
properties = $injector.get('properties');
param = $injector.get('param');
$scope = $rootScope.$new();
var $controller = $injector.get('$controller');
createController = function() {
return $controller('myController', {
'$scope': $scope,
'$rootScope':$rootScope,
'properties':properties,
'param':param,
});
};
}));
var a;
it('should pass this basic test no matter what', function() {
a = true;
expect(a).toBe(true);
});
});
Param definition...
myApp.factory("param", function($http) {
return {
info: {
get: function() {
return $http.get(myApp.url("/param/info")).then(function(response) {
return response.data.data;
});
}
}
}
myApp.run...
myApp.run(['$http', '$rootScope', 'properties', function($http, $rootScope, properties){
...
}]);
If you look at the error carefully it says error in propertiesProvider, you are injecting properties in your test , and hence it's looking for propertiesProvider which doesn't exist . so it throws error.
If properties is an angular Service and you are injecting that in your controller , while testing you need not inject that service again to your test, angular mock takes care of that .
I'll suggest you use npm package generator-yosapy to bootstrap your controller test

How to access the $scope where the factory was injected?

Say I have a factory named MyFactory and I inject it into several controllers. How can I access the controllers scope inside the factory?
The only way I currently think of on how to do this is as follows:
app.factory('MyFactory', function() {
return function($scope) {
myPublicFunc: function() {
$scope.$on('$destroy', function() { ... });
}
}
});
app.controller('MyController1', ['$scope', MyFactory', function($scope, Myfactory) {
var factory = new MyFactory($scope);
factory.myPublicFunc();
});
But is there any other way where I can just return { } instead of function($scope) { } in MyFactory and use the factory directly (MyFactory.myPublicFunc) instead of having to create a new instance with the new keyword and still access each controller's $scope?
if you use a .service instead of .factory you will already have a singleton instance in a controller once you inject it via DI
and then you can do for example
module.service('myService', function() {
return {
myPublicFn: function() {}
}
});
and
module.controller('myCtrl', function(myService, $scope) {
$scope.publicFn = myService.myPublicFn;
});

How can I call a scope function inside a controller?

I am trying to call a scope function inside the controller. My aim is to call the function in the load itself.
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$scope.functionname();
$scope.functionname = function() {}
});
You can directly call the function in controller.
app.controller('customersCtrl', function($scope, $http) {
functionname();
function functionname {
//do something.
}
});
If you are looking to reuse the function outside controller then use Service as controllers are not injectable.
Read johnpapa style guide which shows best practices: https://github.com/johnpapa/angular-styleguide
app.controller('customersCtrl', function(someService) {
var vm = this;
activate();
function activate() {
// Do something.. You can get the data from your service
}
});
Then do your $http in services then inject it in your controller/s.
Best way is to use services:
var app = angular.module('myApp', []);
app.service('SomeService', ['$state', function ($state) {
this.someFunction = function() {
return "some value";
};
}]);
app.controller('customersCtrl', function($scope, $http, SomeService) {
SomeService.someFunction();
});

Resources