You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The official AngularJS introduction describes AngularJS as a:
client-side technology, written entirely in JavaScript. It works with the long-established technologies of the web (HTML, CSS, and JavaScript) to make the development of web apps easier and faster than ever before.
It is a framework that is primarily used to build single-page web applications.
AngularJS augments HTML to give it native Model-View-Controller (MVC) capabilities.
Data Binding and Your First AngularJS Web Application
The chapter starts off by writing a hello world application to show off data binding.
AngularJS creates live templates as a view. Individual components of the views are dynamically interpolated live.
Basic Setup
Include https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.js in the HTML.
Set the ng-app attribute on an element in the DOM.
The ng-app attribute declares that everything inside of it belongs to the Angular app. The only components that will be affected by Angular are the DOM elements that are declared inside of the one with the ng-app attribute.
Automatic data binding gives us the ability to consider the view to be a projection of the model state. Any time the model is changed in the client-side model, the view reflects these changes without writing any custom code. It just works.
When Angular thinks that the value could change, it will call $digest() on the value to check whether the value is "dirty". This process is called dirty checking. The dirty check is done inside its event loop to ensure everything is consistent.
What we did was to bind the "name" attribute to the input field using the ng-model directive on the containing model object ($scope). This means that whatever value is placed in the input field will be reflected in the model object.
Miscellaneous
The model object refers to the $scope object. The $scope object is a JavaScript object whose properties are all available to the view and with which the controller can interact.
Bi-directional in Angular means that if the view changes the value, the model observes the change through dirty checking, and if the model changes the value, the view updates with the change.
Declaring ng-controller attribute on a DOM element says that all of the elements inside of it belong to the controller.
It's considered a best-practice in Angular to bind references in the views by an attribute on an object, rather than the raw object itself.
A core of any Angular app. The scopes of the application refer to the application model. Scopes are the execution context for expressions. The $scope object is where we define the business functionality of the application, the methods in our controllers, and properties in the views.
Scopes serve as the glue between the controller and the view.
Before our app renders the view to the user
The view template links to the $scope
And the app sets up the DOM to notify Angular for property changes
Scopes are the source of truth for the application state. Because of live binding, we can rely on the $scope to update immediately when the view modifies it, and we can rely on the view to update when the $scope changes.
$scope in angularJS are arranged in a hierarchical structure that mimics the DOM and thus are nestable: We can reference properties on parent $scopes.
Scopes provides the ability to watch for model changes. They give the developer the ability to propagate model changes throughout the application by using the apply mechanism available on the scope. We define and execute expressions in the context of a scope; it is also from here that we can propagate events to other controllers and parts of the application.
The $scope View of the World
Angular starts to run
It generates the view
It creates a binding from the root ng-app element to the $rootScope
The $rootScope eventually becomes the parent of all $scope objects
The $rootScope object is the closest object we have to the global context in an Angular app. It's a bad idea to attach too much logic to this global context, in the same way that it's not a good idea to dirty the JavaScript global scope.
The $scope object is a plain old JavaScript object
The $scope object is the data model in Angular
All properties found on the $scope object are automatically accessible to the view.
Through Angular, we can use different types of markup in a template. These include:
Directive: the attributes or elements that augment the existing DOM element into a reusable DOM component
Value bindings: the template syntax {{ }} binds expressions to the view
Form controls: user input validation controls
Scopes have the following basic functions:
They provide observers to watch for model changes
They provide the ability to propagate model changes through the application as well as outside the system to other components
They can be nested such that they can isolate functionality and model properties
They provide an execution environment in which expressions are evaluated
You can think of scopes as view models.
$scope Lifecycle
When the browser receives a JavaScript callback that executes inside of the Angular execution context the $scope will be made aware of the model mutation. If the callback executes outside of the Angular context, we can force the $scope to have knowledge of the change using the $apply method.
After the scope expression is evaluated and the $digest loop runs, the $scope's watch expressions will run dirty checking.
Creation
When we create a controller or directive, Angular creates a new scope with the $injector and passes this new scope for the controller or directive at runtime.
Linking
When the $scope is linked to the view, all directives that create $scopes will register their watches on the parent scope. These watches watch for and propagate model changes from the view to the directive.
Updating
During the $digest cycle, which executes on the $rootScope, all of the children scopes will perform dirty digest checking. All of the watching expressions are checked for any changes, and the scope calls the listener callback when they are changed.
Destruction
When a $scope is no longer needed, the child scope creator will need to call scope.$destroy() to clean up the child scope. Note that when a scope is destroyed, the $destroy event will be broadcasted.
Controllers exist to augment the view of an AngularJS application. The controller adds additional functionality to the scope of the view. We use it to set up an initial state and to add custom behavior to the scope object.
When we create a new controller on the page, Angular passes it a new $scope. This new $scope is where we can set up the initial state of the scope on our controller. Since Angular takes care of handling the controller for us, we only need to write the constructor function.
Setting up an initial controller looks like this:
function FirstController($scope) {
$scope.message = "hello";
}
Best Practice: Name controllers as [Name]Controller rather than [Name]Ctrl.
Angular will call the controller method when it creates the scope.
Best Practice: Namespace controllers by first creating a module and then creating the controller within the module.
var app = angular.module('app', []);
app.controller('FirstController', function ($scope) {
$scope.message = "hello";
});
Using controllers allows us to contain the logic of a single view in a single container.
Best Practice: Keep slim controllers.
The controller is not the appropriate place to do any DOM manipulation, formatting, data manipulation, or state maintenance beyond holding the model data.
Controller Hierarchy (Scopes Within Scopes)
Every part of an AngularJS application has a parent scope. At the ng-app level this scope is called $rootScope.
One exception: A scope created inside of a directive is called the isolate scope.
With the exception of isolate scopes, all scopes are created with prototypal inheritance (i.e. they have access to their parent scopes).
How it works
For any property that AngularJS cannot find on a local scope, AngularJS will crawl up to the containing (parent) scope and look for the property or method there. If AngularJS can't find the property there, it will walk to that scope's parent and so on and so forth until it reaches the $rootScope. If it doesn't find it on the $rootScope, then it moves on and is unable to update the view.
Expression are roughly the result of an eval(javascript). Properties include:
All expressions are executed in the context of the scope and have access to local $scope variables.
An expression doesn't throw errors if it results in a TypeError or a ReferenceError.
They do not allow for any control flow functions (conditionals; e.g., if/else).
They can accept a filter and/or filter chains.
N.B. Expressions all operate on the containing scope within which they are called.
Parsing an Angular Expression
Although your Angular app will run parse for you automatically when running the $digest loop, sometimes it's useful to parse an Angular expression manually.
Angular evaluates expressions by an internal service (called the $parse service) that has knowledge of the current scope.
To manually parse an expression, we can inject the $parse service into a controller and call the service to do the parsing for us.
Interpolating a String
Although it's uncommon to need to manually interpolate a string template in Angular, we do have the ability to manually run the template compilation. Interpolation allows us to live update a string of text based upon conditions of a scope, for instance.
To run an interpolation on a string template, we need to inject the $interpolate service in our object.
A filter provides a way to format the data we display to the user. Filters are invoked in HTML with the | (pipe) character inside the template binding characters {{ }}. For e.g. to use the uppercase filter,
{{ name | uppercase }}
We can also use filters from within JavaScript by using the $filter service. For e.g. to use the lowercase filter,
To pass an argument to a filter in the HTML form, we pass it with a colon after the filter name (for multiple arguments, we can simply append a colon after each argument). For e.g. the number filter allows us to limit the number of decimal places a number can show.
AngularJS supports form validation with a mix of the HTML5 form validation inputs as well as with its own validation directives. It makes it pretty easy for us to handle client-side form validations without adding a lot of extra effort.
To use form validations:
Ensure that the form has a name associated with it
Use the novalidate attribute on the form element, as it prevents the browser from natively validating the form
<formname="form" novalidate><!-- ... --></form>
Control Variables in Forms
AngularJS makes properties available to us (in the format formName.inputFieldName.property) on the containing $scope object available to us as a result of setting a form inside the DOM. These properties enable us to react to the form in real time.
formName.inputFieldName.$pristine is a boolean property that tells us whether the user has modified the form. It is true if the user hasn't touched the form, and false if they have.
formName.inputFieldName.$dirty is a boolean property that tells us if and only if the user has actually modified the form. It is set regardless of validations on the form.
formName.inputFieldName.$valid is a boolean property that tells us whether or not the form is valid. If the form is currently valid, then it would be true.
formName.inputFieldName.$invalid is a boolean property that tells us whether or not the form is invalid. If the form is currently invalid, then it would be true.
formName.inputFieldName.$error contains all of the validations on a particular form and a record of whether they are valid or invalid. If a validation fails, then this property will be true; if it is false, then the value has passed the input field.
When AngularJS is handling a form, it adds specific classes to the form based upon the current state of the form (i.e. if it's currently valid, unchanged, etc.). These classes are named similarly to the properties that we can check, as well.
These classes are:
ng-pristine
ng-dirty
ng-valid
ng-invalid
There are some really good examples in this section of the book. Consult the book to find out more.
If you're looking at how to structure your apps, just look at how any yo generator does it, I use the MeanJS one and it's quite solid although a bit intimidating for a beginner at first sight.
If you're looking at how to structure your apps, just look at how any yo generator does it, I use the MeanJS one and it's quite solid although a bit intimidating for a beginner at first sight.