Service injection into controller with AngularJS - angularjs

I have written a service in AngularJS, but I can't get it to work with the angular-seed way of doing things.
The controller code is as follows:
/*function PhotoCtrl($scope, Photo) {
$scope.photos = Photo.query();
}*/
angular.module('myApp.controllers', []).
controller('PhotoCtrl', [function($scope,Photo) {
$scope.photos = Photo.query();
}])
.controller('MyCtrl2', [function() {
}]);
Note that the commented out section works fine, but I would like to handle it somewhat like the (recommended) second way.
The error I get is that Photo is undefined, so my guess would be my method of passing (injecting) it is wrong, but I can't find out how to do it correctly

You need to define the Photo service:
angular.module('myApp.controllers', [])
.service('Photo', ['$log', function ($log) {
return {
query: function() {
// the query code here.
}
};
}])
.controller('PhotoCtrl', ['$scope', 'Photo', function ($scope, Photo) {
$scope.photos = Photo.query();
}])
.controller('MyCtrl2', [function() {
}]);
A couple of references:
http://docs.angularjs.org/api/angular.Module
http://docs.angularjs.org/api/AUTO.$provide#service
In the above sample code I used parameters aliasing, which I suggest in order to avoid issues when minifying your code.
See also an example here:
AngularJS multiple uses of Controller and rootScope
And a Plunker here:
http://plnkr.co/edit/Bzjruq

Related

Unable to send data to another controller AngularJS

UPDATE PLEASE HELP:
Tried what you suggested, the problem is when i try to pass the value to another "Module". Tried creating a service but the function didn't work, maybe i missed something.
Made Example Using rootScope:
var informes = angular.module('informes', ['angular-drupal', 'ui.bootstrap']);
informes.controller('InformesCtrl', ['drupal', '$rootScope', '$scope', '$http', 'InformesFtry', function(drupal, $rootScope, $scope, $http, InformesFtry) {
$rootScope.nodeID = function(item){
var item = "hi";
console.log(item);
}
}]);
Console hi
It works in first module, but...
In my other Module with different Page...
var nodeInformes = angular.module('node-informes', ['informes']);
nodeInformes.controller('NodeInformesCtrl', ['drupal', '$rootScope', '$scope', '$http', 'InformesFtry', function(drupal, $rootScope, $scope, $http, InformesFtry) {
$scope.nodeID2 = $rootScope.nodeID(item);
console.log($scope.nodeID2);
}]);
Console: item is Undefined
I'm trying to figure out of how can i pass a function to another module, but it seems that it is impossible. I didn't try to use same module, but it works if the controller is child from the first controller.
I really apprecaite any help you can provide me to pass a function with parameter to another module with another controller. I'm trying to learn with this. Thanks!!!
EDIT: If i add the firstcontroller as a dependency it gives me Unknown Provider... Sorry for my mistake.
In Angular JS there are three ways for controllers to communicate with other controllers, and any other method is asking for trouble:
Use a service:
Use a service as an intermediary between controllers:
function MyService() {
this.MyObject = {};
}
function ctrl1(MyService) {
Myservice.MyObject = {
someData: "someValue"
};
}
function ctrl2(MyService) {
$scope.someValue = MyService.MyObject.someData;
}
Use the event system
function ctrl1($rootScope) {
$rootScope.$broadcast("my-event", {someData: "someValue"});
}
function ctrl2($scope) {
$scope.$on("my-event", function(event, params) {
$scope.someData = params.someData;
});
}
Scope inheritence
<div ng-controller="ctrl1">
<div ng-controller="ctrl2">
</div>
</div>
function ctrl1($scope) {
$scope.someData = "someValue";
}
function ctrl2($scope) {
console.log($scope.$parent.someData); //"someValue"
}

Advantage of using $injector vs explicit DI declaration AngularJS

Just wondering if there's difference between:
angular.module('app', [])
.controller('myctrl', ['$scope', 'customService',
function($scope, customService) {
// use customService
}
]);
and using $injector
angular.module('app', [])
.controller('myctrl', ['$scope', '$injector',
function($scope, $injector) {
// get customService via injector and use it
$injector.get('customService');
}
]);
Sometimes I need to inject quite a few dependencies and my parameter list ends up to be lengthy. That's why I'm thinking the latter approach may be better for my scenario.
Does the difference affect testing or minification or any other reason?
You are on the right track. Look at John Papa's Style Guide. You will do the injection before the controller function.
/* recommended */
angular
.module('app')
.controller('Dashboard', Dashboard);
Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice'];
function Dashboard($location, $routeParams, common, dataservice) {
}
Basically there is not much different, until you first encounter your circular dependency error while loading your module.
Simple Fiddle that demonstrates circular dependency.
Code (from fiddle):
angular.module('app', [])
.service('serviceA', function (serviceB) {
return {};
})
.service('serviceB', function (serviceA) {
return {};
})
.controller('myCtrl', function (serviceA, serviceB) {
});
Using $injector helps prevent that scenario because when you use it inside the Controller/Factory/Service/etc instead of injecting the first way, you are delaying the dependency and therefore solving the problem.
And a simple Fiddle that demonstrates how that problem is solved.
Code (from fiddle):
angular.module('app', [])
.service('serviceA', function (serviceB) {
return {
test: "it works!"
};
})
.service('serviceB', function ($injector) {
return {
test: function() {
var serviceA = $injector.get("serviceA");
return serviceA.test;
}
};
})
.controller('myCtrl', function ($scope, serviceA, serviceB) {
$scope.test = serviceB.test();
});

How to setup Angularjs controllers? anonymous functions vs $scope.init() vs view ng-init

Assume we have a controller: ProjectsNewCtrl
What is the difference between:
Setting up the controller without an init() function
App.controller('ProjectsNewCtrl', ['$scope', '$location', 'API'
function ($scope, $location, API) {
API.Project.query().$promise
.then(function (projects) {
$scope.projects = projects
})
}])
AND
Setting up the controller with an init() function
App.controller('ProjectsNewCtrl', ['$scope', '$location', 'API'
function ($scope, $location, API) {
$scope.init = function(){
API.Project.query().$promise
.then(function (projects) {
$scope.projects = projects
})
}
$scope.init()
}])
AND finally:
Setting up the controller via:
<div ng-controller="projectsNewCtrl" ng-init="init()">...</div>
App.controller('ProjectsNewCtrl', ['$scope', '$location', 'API'
function ($scope, $location, API) {
$scope.init = function(){
API.Project.query().$promise
.then(function (projects) {
$scope.projects = projects
})
}
}])
There is no real reason why you would want to use ngInit in this way. In your second example, you are calling a function(ngInit) to call a function($scope.init), instead of the first example where you only call one function on initialization. The logic maybe the same, but it adds unnecessary complexity.
As an aside, you should try no to use ngInit as little as possible, coming from the documentation:
The only appropriate use of ngInit is for aliasing special properties of ngRepeat, as seen in the demo below. Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
Preference. Your last 2 examples are essentially the same, the logic that should be ran on initialization is within the init method - one is called from the view and the other the controller. IMO - it's all about readability, choose what you like.

AngularJs $scope undefined when controllers are inside a module

I'm trying to use the angular-seed template with the default settings. In controllers.js I use
angular.module('myApp.controllers', []).
controller('MyCtrl1', [function($scope) {
$scope.test = 'scope found!';
}])
.controller('MyCtrl2', [function() {
}]);
There the $scope is always undefined.
When I take the controller out of the module and register it globally it works fine. As here:
function MyCtrl1($scope) {
$scope.test = "scope found!";
}
MyCtrl1.$inject = ['$scope'];
Could someone explain to me why this is?
You cannot mix things like that. You need to decide on one of the two possibilities:
app = angular.module('test', []);
// possibility 1 - this is not safe for minification because changing the name
// of $scope will break Angular's dependency injection
app.controller('MyController1', function($scope) {
// ...
});
// possibility 2 - safe for minification, uses 'sc' as an alias for $scope
app.controller('MyController1', ['$scope', function(sc) {
// ...
}]);
I would not advise using the other syntax which declares Controller directly. Sooner or later with the growth of you app it will become hard to maintain and keep track. But if you must, there are 3 possibilities:
function myController1 = function($scope) {
// not safe for minification
}
function myController2 = ['$scope', function(sc) {
// safe for minification, you could even rename scope
}]
var myController3 = function(sc) {
// safe for minification, but might be hard
// to read if controller code gets longer
}
myController3.$inject = ['$scope'];
This is the proper way:
angular.module('myApp.controllers', []);
angular.module('myApp.controllers').controller('MyCtrl1', ['$scope', function($scope) {
}]);
I was also searching for that one, it seems that you need to type '$scope' before the function, as below:
angular.module('myApp.controllers', []).
controller('MyCtrl1', ['$scope', function($scope) {
$scope.test = 'scope found!';
}])
.controller('MyCtrl2', ['$scope',function() {
}]);
It kinda makes sense, I think it should be more clear though..
You can simply remove '[' and ']' when You are using $scope.
angular.module('myApp.controllers', []).
controller('MyCtrl1', function($scope) {
$scope.test = 'scope found!';
})
.controller('MyCtrl2', [
function() {
}
]);

AngularJs ReferenceError: $http is not defined

I have the following Angular function:
$scope.updateStatus = function(user) {
$http({
url: user.update_path,
method: "POST",
data: {user_id: user.id, draft: true}
});
};
But whenever this function is called, I am getting ReferenceError: $http is not defined in my console. Can someone help me understanding what I am doing wrong here?
Probably you haven't injected $http service to your controller. There are several ways of doing that.
Please read this reference about DI. Then it gets very simple:
function MyController($scope, $http) {
// ... your code
}
I have gone through the same problem when I was using
myApp.controller('mainController', ['$scope', function($scope,) {
//$http was not working in this
}]);
I have changed the above code to given below. Remember to include $http(2 times) as given below.
myApp.controller('mainController', ['$scope','$http', function($scope,$http) {
//$http is working in this
}]);
and It has worked well.
Just to complete Amit Garg answer, there are several ways to inject dependencies in AngularJS.
You can also use $inject to add a dependency:
var MyController = function($scope, $http) {
// ...
}
MyController.$inject = ['$scope', '$http'];

Resources