I asked a similar question earlier when attempting to inject $scope and $http into a controller Cannot call method 'jsonp' of undefined in Angular.js controller. Now I'm attempting to refactor that code slightly by moving the code into a function within the controller. I'm encountering similar issues and can't seem to grasp the mechanics of dependency injection in Angular. Below is my new code. Both $scope and $http are undefined. What I'm attempting to do is make an http request when didSelectLanguage() fires and assign the resulting data to the "image" variable in the $scope from the parent controller. Can someone enlighten me as to how dependency injection is supposed to work in this example?
angular.module('myApp.controllers', []).
controller('ImagesCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.didSelectLanguage=function($scope, $http) {
console.log($scope);
$http.jsonp('http://localhost:3000/image?quantity=1&language='+this.language+'&Flag=&callback=JSON_CALLBACK')
.success(function(data){
$scope.image = data;
});
}
}])
When you create your controller:
angular.module('myApp.controllers', []).
controller('ImagesCtrl', ['$scope', '$http', function ($scope, $http) {
// ...
}]);
The stuff inside the body of the controller function automatically has access to $scope and $http because of closures. Thus, there's no need to specify anything additional for a function on the $scope to have access to these things:
angular.module('myApp.controllers', []).
controller('ImagesCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.didSelectLanguage = function() {
$http.jsonp('http://localhost:3000/image?quantity=1&language=' + this.language + '&Flag=&callback=JSON_CALLBACK');
.success(function(data) {
$scope.$parent.image = data;
});
}
}]);
When didSelectLanguage is run, it sees the references to $http, and reaches out of the function into the outer function to get the value of the reference; the same happens for $scope inside the success callback.
So, in short, there's no need to pass any arguments to your didSelectLanguage function, nor is there in this case any reason to use the $injector.
With the help of Michelle Tilley's comment & article I solved the problem as follows. However, I'm going to keep the question open until someone else answers or until I understand enough to write an accompanying explanation.
controller('ImagesCtrl', ['$scope', '$http', '$injector', function ($scope, $http, $injector) {
$scope.didSelectLanguage=function() {
$http.jsonp('http://localhost:3000/image?quantity=1&language='+this.language+'&Flag=&callback=JSON_CALLBACK')
.success(function(data){
$scope.$parent.image = data;
});
}
}])
Related
OK so I am new to angular and I have been searching for answers all over the web to this problem. I am having an unknown provider error and I am not able to find the right answer I have tried multiple replies from here on stack overflow and alot of other places but it has not helped me find the right answer for it yet.
I have the Module.
var app = angular.module('app', ['ngRoute','app.student']).config(['$httpProvider', '$routeProvider', function ($httpProvider,$routeProvider) {
//Various code
}]);
Here is my Controller
angular.module('app.student', []).controller('StudentCtrl', ['StudentService', '$scope', '$http', function (StudentService, $scope, $http) {
//Code
}]);
And now My service
angular.module('app.student', []).service('StudentService', ['$http', function ($http) {
// Some More Code
}]);
I am still new to this language, I have again tried multiple answers on Stackoverflow and None of the answers are working for me. So I just decided to ask for some help. Thanks
P.S. if you need more of my code just let me know.
You are creating the app.student module twice.
First you create your module (and then you also create a controller):
angular.module('app.student', []).controller('StudentCtrl', ['StudentService', '$scope', '$http', function (StudentService, $scope, $http) {
//Code
}]);
Then once it's created, just retrieve it. Don't pass in an array of dependencies, or you will create it again:
angular.module('app.student').service('StudentService', ['$http', function ($http) {
// Some More Code
}]);
You do not need to have app.student as a dependency,
var app = angular.module('app', ['ngRoute']).config(['$httpProvider', '$routeProvider', function ($httpProvider,$routeProvider) {
//Various code
}]);
your controller code should be,
angular.module('app').controller('StudentCtrl', ['StudentService', '$scope', '$http', function (StudentService, $scope, $http) {
//Code
}]);
and service should be,
angular.module('app').service('StudentService', ['$http', function ($http) {
// Some More Code
}]);
I have two controllers (Main controller and Child controller). I am trying to pass value from Main to Child controller.
Here are the controllers:
.controller('mainController', ['$scope', '$rootScope', '$location', 'CIFactory', function ($scope, $rootScope, $location, CIFactory) {
$scope.moveTool = function (buildServerTool) { //Am calling this moveTool function from View
$scope.tool = buildServerTool.toolname;
$scope.$broadcast('update_parent_controller', $scope.tool);
};
}])
.controller('childController', ['$scope', '$rootScope', '$q', '$timeout', '$log', 'CIFactory', function ($scope, $rootScope, $q, $timeout, $log, CIFactory) {
$scope.$on('update_parent_controller', function (event, tools) {
$scope.tools = tools;
});
}])
When I debug, control is going in moveTool() function, but it is not going inside $on(i.e., value in tools is not assigned to $scope.tools. What am I doing wrong here ?
As Martijn said $broadcast moves down the $scope chain, so it may be best to use $rootScope if the child controller isnt directly inside the parent scope
$rootScope.$broadcast('update_parent_controller', $scope.tool);
See this answer for more information on emit vs broadcast and scopes
Thanks Chris. I have also tried another method and it worked for me. Instead of using $broadcast and $on, I just used following line in child controller,
$scope.tools = $scope.$parent.tool;
So, the above code took the $scope value from parent controller and assigned to new scope $scope.tools, which I have used in corresponding View.
I am trying to create a service to do some AJAX requests.
However, my service keeps getting undefined when I try to do something with it in my controllers. Here is my code.
I have found a lot of examples on here, and I've tried to follow a lot of them but no matter what I do my service keeps getting undefined.
My service:
MyApp.factory('myService', function($http) {
return {
findAll: function() {
return $http.get('/findAll')
.then(function(result) {
return result.data;
});
}
}
});
My Controller:
MyApp.controller('UserController', ['$scope', '$http', 'myService', function($scope, $http, $log, myService) {
// Whatever I do with myService here it gets undefined.
//$scope.test = myService.findAll();
//myService.findAll();
}]);
I assume I don't inject it correctly but I can't see whats wrong. I'm fairly new to Angular so..
Any pointers would be appreciated.
Remove $log from the injection. You are currently "naming" the myService service to $log and therefore myService inside the controller is undefined.
MyApp.controller('UserController', ['$scope', '$http', 'myService',
function($scope, $http, myService) {
// Whatever I do with myService here it gets undefined.
//$scope.test = myService.findAll();
//myService.findAll();
}]);
2nd solution
To avoid having to "name" the services like this it's acceptable to inject them without naming them.
MyApp.controller('UserController', function($scope, $http, myService) {
// Whatever I do with myService here it gets undefined.
//$scope.test = myService.findAll();
//myService.findAll();
});
Just remember to remove the closing bracket aswell.
I have a MyResource service defined like this:
angular.module('resourceApp')
.factory('MyResource', ['$resource', function($resource) {
return $resource('/data');
}]);
And then I have a controller which uses MyResource as a dependancy:
angular.module('resourceApp')
.controller('MainCtrl', ['MyResource', function($scope, MyResource) {
$scope.data = MyResource.get(); // <-- this is where the error occurs
}]);
When I define the dependancy like above, using an Inline Array Annotation, I get an error "MyResource is undefined" at the line marked with the comment.
But if I change the syntax to Implicit Annotation:
angular.module('resourceApp')
.controller('MainCtrl', function($scope, MyResource) {
$scope.data = MyResource.get();
});
I somehow magically get things working!
The question is: what's wrong with the first one? I could leave the implicit annotation, but the documentation says that it won't survive the minification.
You are forgetting the $scope in the first one, it should be:
anguar.module('app').controller('CTRL', ['$scope', 'MyService', function($scope, Service)
Currently you have no scope, and the $scope variable actually points to the service
You forgot to specify the $scope in your array:
.controller('MainCtrl', ['$scope', 'MyResource', function($scope, MyResource) {
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.