Confusion between $scope's in controller and its function? - angularjs

I'm new to UI. I do have confusion between $scope's in AngularJS. Please refer below snippet.
var mainApp = angular.module("mainApp", []);
mainApp.controller(['$scope', function($scope) {
$scope.name = "John";
}]);
So, what's the difference between $scope and function($scope)? Also how can we relate both? Is it required to have $scope parameter? Please explain me with an example. I really appreciate that.
Thanks,
John

1.When you apply Minification of Following Angular JS code:
var mainApp = angular.module("mainApp", []);
mainApp.controller(['$scope','$log', function($scope,$log) {
$scope.name = "John";
$log.log("John");
}]);
Minified Version :
var mainApp=angular.module("mainApp",
[]);mainApp.controller(["$scope","$log",function(n,o)
{n.name="John",o.log("John")}]);
2.When you apply Minification of Following Angular JS code:
var mainApp = angular.module("mainApp", []);
mainApp.controller(function($scope,$log) {
$scope.name = "John";
$log.log("John");
});
Minified Version :
var mainApp=angular.module("mainApp",[]);mainApp.controller(function(n,a)
{n.name="John",a.log("John")});
3.When you apply Minification of Following Angular JS code:
var mainApp = angular.module("mainApp", []);
mainApp.controller(function($log,$scope) {
$scope.name = "John";
$log.log("John");
});
Minified Version :
var mainApp=angular.module("mainApp",[]);mainApp.controller(function(n,a)
{n.name="John",a.log("John")});
You will Notice in Ex-2 and Ex-3 that you have interchanged the Dependency place of $scope and $log then also your minified version is the same ,this will give you dependency Injection error ,so we place a String value as String Value can't be minified as you can see in Ex-1.
It is not required to have $scope each time you define your controller but $scope provides important functionality like binding the HTML (view) and the JavaScript (controller). .
https://docs.angularjs.org/guide/scope

what's the difference between $scope and function($scope)?
When you do
mainApp
.controller(
['$scope', //line 1
function($scope) //line 2
{
}
]);
In line 1 it refers to $scope, which is an object that refers to the application model
In line 2 it is the variable (conveniently called $scope too) in which the (mentioned above) $scope object is injected. This variable can have any other name, $scope is used as a way to keep a suggestive reference through the whole code.
For instance, your example would work too if I change its name to myFunnyScope like this:
var mainApp = angular.module("mainApp", []);
mainApp.controller(['$scope', function(myFunnyScope) {
myFunnyScope.name = "John";
}]);
Also how can we relate both?
Taking as reference my previously posted snippet, you can tell the $scope object is being injected in the myFunnyScope variable, it means you use myFunnyScope as if it were $scope itself.
Is it required to have $scope parameter?
As long as you need to get access to all benefits provided by the mentioned $scope object, when you do minification it is required to inject the object ([$scope, ...) into the holder (function($scope) { ...) in order to not get the AngularJS application broken. Otherwise, no, you don't need to inject the object, but then you have to explicitly call it $scope in the function parameter so AngularJS knows it has to inject the $scope object inside it. This rule applies not only to $scope, but to all other AngularJS related services, factories, etc such as $timeout, $window$, $location, etc.
You might want to read about the AngularJS injection mechanism and consider using the controller as syntax for reasons explained here if you do not want to use $scope directly.

Related

Can't change 1 arg in controller in angularjs?

This is my angular code.
angular.module("app", []).controller("ctrl", function($scope){
$scope.name = "Name";
});
but, when I chaged the paramerter thats not working.
angular.module("app", []).controller("ctrl", function($para){
$para.name = "Name";
});
How to make it work and can't we use this in our other function?
Angular uses dependency injection based on the given parameter name. It doesn't know $para, so it won't get injected. You can however use the array notation where you explicitly say the name of the service to inject. The array notation is also necessary if you minimize your javascript code, so that angular still knows what to inject when your variables get renamed to a, b etc:
angular.module("app", []).controller("ctrl", ["$scope", function($para){
// $para is the $scope object
$para.name = "Name";
}]);
If your $para is a service, you have to register it so that angular knows what to inject:
angular.module("app", [])
.service("$para", function() {
//
})
.controller("ctrl", function($para){
$para.name = "Name";
});
The scope is the binding part between the HTML (view) and the JavaScript (controller). It is a special in angular.
Please read this https://www.w3schools.com/angular/angular_scopes.asp
'$scope' is a special service in AngularJS.
You can, however, create your own service '$para' and inject it if you want.
Check this.
Also, if you don't want to use '$scope', you can use the alternative 'controller as' syntax.
Read about it here.

Best way of defining controller in angularJs

I am new to angularJs. I am confused which one is best way to create a controller for ng-app="mainApp". In programming other programming languages that I had worked on suggest to keep relative data together. But in angularJs it's considered best practice to have new module for controllers when we can define controller over main app module. If we create controller on mainApp it will keep controller and bind which is what we want in other languages.
var myapp = angular.module("mainApp", []);
myapp.controller("testController", function($scope)
{
$scope.value = "test";
})
//OR
angular.module("mainApp", ["moduleController"]);
angular.module("moduleController", []).controller("testController", function($scope){
$scope.value = "test";
})
For production environment which one should be used.??
Option 1:
var myapp = angular.module("mainApp",[]);
myapp.controller("testController",function($scope)
{
$scope.value="test";
})
Option 2:
angular.module("mainApp", ["moduleController"]);
angular.module("moduleController",[]).controller("testController",function($scope){
$scope.value="test";
})
Option 2 is better because this will allow you to write your controllers in separate files. As a result your code will be more readable. It'll also help you if you want to reuse your controllers in other AngularJS projects.
For example, you can write the following code in one file e.g app.js:
angular.module('mainApp',['ngRoute', 'appController']);
And you can write the controller in another file e.g controllers.js:
var appController= angular.module('appController', []);
appController.controller('testController', ['$scope',
function($scope) {
$scope.value="test";
}
]);
Now, you can reuse the controllers in another project by just adding the controllers.js file in the project and adding dependency to appController in the app.js file.
Neither, none of them will run in production environment where all script will be minified. Angular's injector subsystem is able to find and resolve $scope, $location, $etc and provide them to the component as requested.
myapp.controller("testController",function($scope)
{
$scope.value="test";
})
However, upon minification, the code above will end up looking something like:
a.controller("testController",function(b)
{
b.value="test";
})
which would cause the dependency injection to fail and result in a runtime error.
You will have to use it as below:
var myapp=angular.module("mainApp",[]);
myapp.controller("testController", ['$scope',function($scope)
{
$scope.value="test";
}]);
In this case, the controller function is initialized inside of an array after a list of each dependency as string literals. This ensure dependency injection is properly maintained, even through minification or uglification.

I need a clarification about dependencies

What is the difference between:
myApp.controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
}]);
And
myApp.controller('GreetingController', function($scope) {
$scope.greeting = 'Hola!';
});
Some of the examples add dependency for scope and some are not.
Thank you.
Both your samples have a scope dependency injected, the difference being the first one uses the array notation which allows you to create custom naming, won't break when minifying, etc... It's the recommended way. For example, this works fine:
myApp.controller('GreetingController', ['$scope', function(myScopeAlias) {
myScopeAlias.greeting = 'Hola!';
}]);
See it in action here:
angular.module('test', [])
.controller('GreetingController', ['$scope', function(myScopeAlias) {
myScopeAlias.greeting = 'Hola!';
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="GreetingController">{{greeting}}</div>
Dependency Annotation
Angular invokes certain functions (like service factories and controllers) via the injector. You need to annotate these functions so that the injector knows what services to inject into the function. 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)
Read more: https://docs.angularjs.org/guide/di#dependency-annotation
I just want to emphasis one point:
Always using the inline array annotation if you project need to do the Uglification(Most real project need a uglification).
Building minification-safe Angular.js applications

Passing variables to angular.js scope from web page

What is correct way of passing variables from web page when initializing $scope?
I currently know 2 possibilities:
ng-init, which looks awful and not recommended (?)
using AJAX request for resource, which requires additional request to server which I do not want.
Is there any other way?
If those variables are able to be injected through ng-init, I'm assuming you have them declared in Javascript.
So you should create a service (constant) to share these variables:
var variablesFromWebPage = ...;
app.constant('initValues', variablesFromWebPage);
With this service, you don't need to add them to the scope in the app start, you can use it from any controller you have, just by injecting it (function MyCtrl(initValues) {}).
Althouhg, if you do require it to be in the scope, then this is one of the main reasons what controllers are meant for, as per the docs:
Use controllers to:
Set up the initial state of a scope object.
Add behavior to the scope object.
Just add this cotroller to your root node:
app.controller('InitCtrl', function($rootScope, initValues) {
$rootScope.variable1 = initValue.someVariable;
$rootScope.variable2 = initValue.anotherVariable;
});
#Cunha: Tnx.
Here some more details how I did it:
In the Webpage:
<script type="text/javascript">
var variablesFromWebPage = {};
variablesFromWebPage.phoneNumber = '#Model.PhoneNumber';
</script>
In the angular application file, registering the service:
var module= angular.module('mymodule', ['ngRoute', 'ngAnimate']);
module.factory('variablesFromWebPage', function () {
return variablesFromWebPage
});
And then the controller:
module.controller('IndexController',
function ($scope, $location, $http, $interval, variablesFromWebPage) {
$scope.phoneNumber = variablesFromWebPage.phoneNumber;
}
);

What is the benefit of defining Angular app?

In some AngularJS tutorials, angular app is defined as:
myApp = angular.module("myApp",[]);
But we can also do without it. The only difference I can see is when we define controller, we can't use idiom:
myApp.controller("myCtrl",function(){ })
but has to use
function myCtrl (){}
Is there any other benefits of defining myApp explicitly, given that I will only create a single app for my site? If I don't define myApp, then where my modules are attached to?
If there is, how I can recreate myApp in testing with Jasmin?
You can define controllers in (at least) 3 ways:
Define the controller as a global var (stored on the window object)
function Ctrl() {}
which is the same as doing:
window.Ctrl = function () {}
Create a module and use the returned instance to create new controllers:
var app = angular.module('app', []);
app.controller('Ctrl', function() {});
Create the controllers directly on the module without storing any references (the same as 2 but without using vars):
angular.module('app', []);
angular.module('app').controller('Ctrl', function() {});
From Angular's point of view, they all do the same, you can even mix them together and they will work. The only difference is that option 1 uses global vars while in options 2 and 3 the controllers are stored inside an Angular's private object.
I understand where you're coming from since the explanation for bootstrapping your Angular is all over the place. Having been playing with Angular only for a month (I'll share what I know anyways), I've seen how you have it defined above. I was also in the same scenario where I only have to define myApp once and not have multiple ones.
As an alternative, you can do something like this below. You'll notice that the Angular app and the controller doesn't have to live by the same namespace. I think that is more for readability and organization than anything.
JS:
window.app = {};
/** Bootstrap on document load and define the document along with
optional modules as I have below.
*/
angular.element(document).ready(function () {
app.ang = angular.bootstrap(document, ['ngResource', 'ngSanitize']);
// OR simply, works similarly.
// angular.bootstrap(document, []);
});
/** Define Angular Controller */
app.myController= function ($scope, $resource, $timeout) {
};
HTML:
<div role="main" ng-controller="app.myController"></div>
you have to define the app with angular.module anyway. myApp.controller and function myCtrl are the same..

Resources