angular controller inline annotation syntax - angularjs

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) {

Related

Which one is correct way for initializing module,controller in angularJS?

Which one is correct way for initializing module,controller in angularJS
var myapp=angular.module('myApp', []);
myapp.controller('Ctrl1', Ctrl1);
myapp.controller('Ctrl2', Ctrl2);
Ctrl1.$inject = ['$scope', '$http'];
Ctrl2.$inject = ['$scope', '$http'];
function Ctrl1($scope, $http) {
}
function Ctrl2($scope, $http) {
}
or this way
var myapp=angular.module('myApp', []);
myapp.controller('Ctrl1', Ctrl1);
Ctrl1.$inject = ['$scope', '$http'];
function Ctrl1($scope, $http) {
}
myapp.controller('Ctrl2', Ctrl2);
Ctrl2.$inject = ['$scope', '$http'];
function Ctrl2($scope, $http) {
}
or doing this way
var myapp=angular.module('myApp', []);
myapp.controller('Ctrl1', ['$scope', '$http', function ($scope, $http) {} ]);
myapp.controller('Ctrl2', ['$scope', '$http', function ($scope, $http) {} ]);
I am confusing which way is correct and can you give give me the cirrect project structure of AngularJS frmawork
Any sample project for that in github always welcome
Some peoples says John Papa style which one correct way i mean most efficient way
The simpliest way is to write:
myapp.controller('Ctrl1', function($scope, $http) {
});
And you should use ngmin to parse your code before minification. It will automatically wrap the controller callback in ['$scope', '$http', function($scope, $http) {}] to avoid minification problem.
If you use gulp, use gulp-ngmin.
The second way should be the ideal way as because
It is easy to read.
Easy to maintain
Protected from minification by the injector.
Anyways all of them are correct.
But second way should be the best.
Also make sure that you wrap the code in the way to protect from variable name clashes:
(function(){
'use strict'; //another best practice
//then your code
})()
Angular's $inject method, we can explicitly declare our dependencies. This one may give problem for every controller injection. Other than you can use.
https://docs.angularjs.org/api/auto/service/$injector

Inline annotation for angular controller (services)

I am using the generator-angular-fullstack for my app and have come into a problem when minifying / uglyfying my code.
Before minifying my code i could use services and they would work fine but afterwards i get the following error:
[$injector:unpr] Unknown provider: aProvider <- a
I read that i need to add inline annotations to my controller like this (to stop the minify process from destroying the service:
app.controller('mainController', ['$scope', '$http', function($scope, $http) {
$scope.message = 'HOORAY!';
}]);
generator-angular-fullstack creates controllers like this:
(function () {
class EmployeesearchComponent {
constructor($scope, $rootScope, $state, $stateParams, elasticservice, $mdDialog) {
$scope.message = 'HOORAY!';
};
}
angular.module('myApp')
.component('employeesearch', {
templateUrl: 'app/employeesearch/employeesearch.html',
controller: EmployeesearchComponent
});
})();
Where am i supposed to add the services as strings?
Thanks,
I needed to add the strings above the constructor field:
static $inject = ['$scope', '$http']
Another solution is to change the controller key to have an array with the parameters' names and the controller class at the end, like so:
[...]
.component('employeesearch', {
controller: ['$scope', '$rootScope', '$state', '$stateParams', 'elasticservice', '$mdDialog', EmployeesearchComponent]
});
But you should really think about adding these annotations during your build process, it would make you code cleaner. If you're using build systems like gulp or grunt there are libraries that allow you to do this just by adding a single extra line to your build script. You can find it as "ng-annotate".

Can't access my service in my controller (undefined)

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.

Why place $scope in the dependencies array on a controller?

I've seen a lot of people, including the Angular docs, declare controllers like so:
app.controller('ExampleController', [$scope, $http, function($scope, $http) {
$scope.name = "Bob";
}]);
Why do we need to put $scope in the dependency array? Is this the syntax of an older version of Angular? Can we instead write it like:
app.controller('ExampleController', [$http, function($scope, $http) {
$scope.name = "Bob";
}]);
Is there a difference between the two? Thank you.
What you've been looking at is actually something like this:
app.controller('ExampleController', ["$scope", "$http", function($scope, $http) {
$scope.name = "Bob";
}]);
The reason this is done is to deal with minification. When minifying the $scope, $http would be crushed into variables like a and b since dependency injection doesn't work through minification. Angulars solution to this is to make the controller an array where you can pass in strings.
See: https://docs.angularjs.org/tutorial/step_05#-prefix-naming-convention

Injecting $http and $scope into function within controller

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

Resources