I have the following code:
<!doctype html>
<html>
<body>
<div ng-controller="MyController">
Hello {{greetMe}}!
</div>
<script src="http://code.angularjs.org/snapshot/angular.js"></script>
<script>
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
$scope.greetMe = 'World';
}]);
angular.element(function() {
angular.bootstrap(document, ['myApp']);
});
</script>
</body>
</html>
from the website: https://docs.angularjs.org/guide/bootstrap
I really can't understand how the syntax is working, particularly,
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
$scope.greetMe = 'World';
}]);
What does the above ugly syntax mean? What is the role of 'MyController'? what does the array parameter mean? what does $scope mean? Who is calling the "function($scope)"?
How does it work?
angular.bootstrap(document, ['myApp']);
When is the parameter above ['myApp'] injected and how?
The website doesn't explain anything regarding the syntax. Just assumed the reader knows all about it.
Please help.
Angular's dependency injection "stringifies" the function and then extracts the parameter names from the string, and uses that to find the dependant service.
However when you minify your code, those parameters because "g", "e", etc. Since Angular now can't know what service you actually wanted, they provide two different methods of explicitly describing your dependencies.
The first is to supply your function/class as the last parameter in an array, with the elements in the array before it being the original names of the parameters.
The alternative is to pass your original function/class, but to assign a "static" $inject property to the function itself. The property is given the value of an array of strings representing your original parameter names.
And, finally, the first parameter supplied to angular.controller/service/factory/etc is the name that you will be applying to the service you are registering. It is that string that other services will use to declare their dependency on your controller/service.
"myApp", in your sample, is a module. Modules aren't injected as dependencies but are instead a way of packaging up a group of services (controllers, directives). You can't inject a service from a different module without first declaring a dependency on that module by adding the name of the module to the array passed as the second parameter to angular.module. angular.bootstrap allows a module (and it's dependants) to work with a dom node.
May be below explanation give you clear understanding
angular.module('myApp', [])
This line creates variable for module (in this case myApp) which we will using in the HTML page to bootstrap the application from the element specified
Either by manul bootstrapping using below line of code
angular.bootstrap(document, ['myApp']);
or by adding to any element where we want to use angular
$scope is the application object and available for both view and controller which contains model data
ng-controller directive will allow to use controller specified (in this case ng-controller ="MyController")
One module can have multiple controllers and each controller will have its own associated $scope object and constructor function model properties and functions are defined inside that associated scope.
Angular Dependency Injection feature will help to consume the components created separately and thereby make those components reusable, maintainable and testable.
Below article on dependency injection will provide more insight
http://anandmanisankar.com/posts/angularjs-dependency-injection-demystified/
Hope this is helpful for you
Related
I'm trying to add a chart to code created by others.
I understand a bit of angular, only...
I'm using angular-ui, so I don't have access to the HEAD tag where the simple Google instructions say to put the SCRIPT tags. I tried putting it later in the html, with other SCRIPT tags, but it kept saying "google" was undefined.
Finally, it seems to work if I put it inside the onload function:
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
drawCharts = function() {
var is = issue;
... create the chart using data inside $scope.issue
}
// google.charts.load( -- DOESN'T WORK HERE, google is undefined
$(window).load(function () {
// finally, in here, 'google' is defined
google.charts.load('current', {'packages': ['corechart', 'bar']});
google.charts.setOnLoadCallback(drawCharts);
}
PROBLEM: drawCharts() needs to access the $scope, but here there's no access to $scope, so my angular data isn't accessible and drawCharts() fails.
So somewhere I need to connect
google.charts.setOnLoadCallback() and $scope
How?
I found one question where the person had a:
$rootScope
.$on('$viewcontentLoaded', function(...)
But he has it in main.js, and I don't have a main.js.
I tried putting it in my controller for the page, but it doesn't define $rootScope. I tried adding $rootScope to the parameters passed to the first line of my controller:
people.controller("voterIssueCtrl", function ($rootScope, $scope, $http, $cookieStore, $window, ClIENT
And that took care of the undefined $rootScope, but the $viewContentLoaded function was never called (it just contained a console.log() message...)
Perhaps my app.js is his main.js.
But it references the controller by name, so it probably loads it, so it probably can't reference something the controller defines.
Help?
===============
I pulled a google chart directive from the web
added the tag in index.html to pull it in
and added the directive to my module definition.
(Of course I forgot the 2nd one and the code didn't complain...)
Nothing. But no complaint that Google wasn't known...
Putting in sample data helps.
In the grand style of js and angular, it doesn't complain if the data isn't exactly in the form it needs...
If only Angular2 + Typescript had been invented sooner...
What is the difference between these 2:
angular.module('myapp' ,[])
.controller('MyController', function($scope){...});
and
angular.module('myapp' ,[])
.controller('MyController, ['$scope', function($scope){...})];
This is quite complicated for those who new to AngularJS like me. The syntax is too different from Java and C.
Many thanks.
There's nothing difference between them. Both code works same way. But if you use first code and when you minify the code then it will confuse.
Look for an example:
.controller('MyController', function(a){...});//$scope is changed to a
And your code won't work as angularjs code uses $scope variable as it doesn't take first, second, third, and so on parameters.
So, the second code is safer than first as if when you minify the code, it still takes same variable i.e. $scope.
Look for an example:
.controller('MyController', ['$scope', function(a){...})];//a refers to $scope
So, the above code works fine when you minify the code as $scope is injected in place of a. So, if you pass multiple parameters then ordering matters in this example. Look at the following:
.controller('MyController', ['$scope','$timeout', function(s,t){...})]; s is injected as $scope and t is injected as $timeout. So if you change the order of them like ['$timeout','$scope', function(s,t){...})] then s is $timeout and t is $scope. So, ordering matters in this example but in your first example code ordering won't matter as name matters like $scope, $timeout.
There's also another way to inject variables if you use your first example code like below:
MyController.$inject = ['$scope'];
For multiple parameters,
MyController.$inject = ['$scope','$timeout'];
So, there are mainly three kinds of annotation:
Implicit Annotation - your first example code
$inject Property Annotation - the $inject method
Inline Array Annotation - your second example code
The second is minification safe.
Since Angular infers the controller's dependencies from the names of
arguments to the controller's constructor function, if you were to
minify the JavaScript code for PhoneListCtrl controller, all of its
function arguments would be minified as well, and the dependency
injector would not be able to identify services correctly.
Source
I am doing it this way.
Method 1:
var app = angular.module('MyModule', ['ngDialog']);
app.controller('MyController', function ($scope,ngDialog) {
///
});
but i see a lot like the below kind in articles
Method 2:
app.controller('MyController', ['$scope', function ($scope) {
///
}]);
Please help me understand why is $scope mentioned twice in method 2.
Is method 1, a good practice. If not, in what cases will it fail.
Method 2 is used to prevent minification bugs. In Production when you usually minify your JS/CSS files, the variables' names change to reduce bytes and make the files lighter.
AngularJS relies on DI, which means that it knows which service/provider to inject to your controllers/services according to the name. If it sees $httpProvider, it knows to inject $httpProvider. Once minifaction takes place, the naming will change from:
app.controller('MyController', function (a,b) { //a, b is the change
///
});
Or something of that sort.
Using Method 2, you specify the names as strings, and using those strings AngularJS knows what to inject despite the fact that the minification changed the variables' names.
You can read more about this here.
The recommended way of declaring Controllers is using the array notation:
someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) {
...
$scope.aMethod = function() {
...
}
...
}]);
Dependency Annotation
There are three ways of annotating your code with service name information:
Using the inline array annotation (preferred)
Using the $inject property annotation
Implicitly from the function parameter names (has caveats)
Among These three,Using the inline array annotation is preferred approach.And
the last is simplest way to get hold of the dependencies is to assume
that the function parameter names are the names of the dependencies.
Advantage of implicitly from the function parameter names approach is that there's no array of names to keep in sync with the function parameters. You can also freely reorder dependencies.And disadvantage is If you plan to minify your code, your service names will get renamed and break your app.
Source: this
I'm kind of a big angularJS newbie and I'd like some highlights concerning dependency injection.
I've done some research and here is what I understand so far.
I have 2 service files (using factories) :
-mogService.js
angular.module('anglober.services').factory('mogService', ['$http', function($http) {
var mogService = {};
//mogService code here
return mogService;
}]);
-modalService.js
angular.module('anglober.services').factory('modalService', ['$modal',
function ($modal) {
//modalService code here
}]);
One controller file :
-mogCtrl.js
angular.module('anglober.controllers').controller('mogCtrl', ['$scope', 'mogService','modalService', function ($scope, mogService, modalService) {
//code using mogService and modalService parameters
}]);
As I understand it, the dependency injection is done by passing my services as parameters of the function parameter in my controller declaration, the array of string is here so that after minification, angular still knows which variable is what.
However, the modalService variable is undefined when I test my code. The mogService is recognized alright though (only if I remove any call to the modalService variable).
What am I doing wrong ?
I've read things about using $inject, which is the better practice and why ?
I'm declaring modules in the app.js as follows :
angular.module('anglober.services', ['ui.bootstrap']);
angular.module('anglober.controllers', []);
var app = angular.module('anglober', ['anglober.controllers', 'anglober.services', 'anglober.directives']);
Is this good practice ? Declaring modules and their respective dependencies in one file then only use "getters" without the dependencies array parameter in module files ?
Thanks for your time.
Three steps that work for me (plunkr):
1. Be sure you define a module's dependencies only once.
Indeed, check that angular.module('anglober.services', [...]); is indeed called only once with the second argument.
At the same time, be sure to call these lines before the actual services/controllers /... definitons.
2. Wire every dependency
You should add 'anglober.services' dependency to 'anglober.controllers': the last requires modalService which requires $modal, it may help angular anyway.
3. Add possible missing lib requirements, in the right order
First jQuery, then angular, bootstrap and eventually bootstrap.ui and your modules.
I am new to angularJS. I have been reading many code examples and I often see controllers defined as:
function MyController($scope) {
//code here
};
I however am using the method below to define my controller, as I wasn't aware there was any other way to do it.
angular.module("csApp.controllers", [])
.controller("main", function ($scope) {
//code here
};
How does the first method work? Is there some sort of naming convention I am missing here?
Are people using the first method simply adding these functions as global variables by placing them in in script files after angular loads?
How would you connect a global variable to a route if the controller is not registered with angularJS?
Thanks!
The AngularJS Dependency Injection framework can always find controller constructor function in global scope as they are global by nature. Even the ng-controller directive has this in its documentation
Name of a globally accessible constructor function or an expression
that on the current scope evaluates to a constructor function.
When using $routeProvider you can provide the route definition a Controller class or a quoted controller name which has been registered using the module api. These two are valid
route :{controller:MainCtrl,...}
route :{controller:'main',...}
The module based approach is preferable because it stops one from polluting the JS global namespace.
You just need to initialize your module, then you can declare your controllers with the two methods.
The first method make it easier and more readable when you have for instance 5 controllers, or if you want to split them in differents files. But they do the same job. All you need to do is keeping track your controller name.
function MainCtrl($scope) {
// do your stuff
}
<!-- Using the function name here -->
<ANY ng-controller="MainCtrl">
<!-- your HTML data -->
</ANY>
More info in the API Doc.