fix(guide): simplify directory structure

This commit is contained in:
Mrugesh Mohapatra
2018-10-16 21:26:13 +05:30
parent f989c28c52
commit da0df12ab7
35752 changed files with 0 additions and 317652 deletions

View File

@ -0,0 +1,45 @@
---
title: Angular Resources
---
A collection of helpful Angular resources
## Angular 1.x
### General Pages
* <a href='https://angularjs.org/' target='_blank' rel='nofollow'>Angular JS</a> - The Angular JS Homepage
* <a href='https://github.com/johnpapa/angular-styleguide/tree/master/a1' target='_blank' rel='nofollow'>AngularJS Style Guide</a> - Detailed best practices for Angular Development
### Videos
* <a href='https://www.youtube.com/watch?v=5uhZCc0j9RY' target='_blank' rel='nofollow'>Routing in Angular JS</a> - Client Side Routing in 15 minutes
* <a href='https://www.youtube.com/watch?v=WuiHuZq_cg4' target='_blank' rel='nofollow'>Angular ToDo App</a> - An Angular ToDo app in 12 minutes
### Courses
* <a href='https://egghead.io/browse/frameworks/angularjs' target='_blank' rel='nofollow'>Egghead.io AngularJS Courses ($)</a>
## Angular 2.x+
### General Pages
* <a href='https://angular.io/' target='_blank' rel='nofollow'>Angular</a> - The Angular Homepage
* <a href='https://angular.io/guide/styleguide' target='_blank' rel='nofollow'>Angular Style Guide</a> - Detailed best practices for Angular Development
### Specific-topic Pages
* <a href='http://www.sitepoint.com/practical-guide-angularjs-directives/' target='_blank' rel='nofollow'>Directives</a> - Excellent guide going into detail on Angular Directives (Part 1)
### Courses
* <a href='https://egghead.io/browse/frameworks/angular' target='_blank' rel='nofollow'>Egghead.io Angular Courses ($)</a>
* <a href='https://frontendmasters.com/courses/building-apps-angular' target='_blank' rel='nofollow'>FrontendMasters - Building Awesomer Apps with Angular</a>
* <a href='https://ultimateangular.com/' target='_blank' rel='nofollow'>Ultimate Angular - Todd Motto</a>
* <a href='https://www.udemy.com/the-complete-guide-to-angular-2/' target='_blank' rel='nofollow'>Angular 6 (formerly Angular 2) - The Complete Guide($) Maximilian Schwarzmüller </a>
## Blogs
* <a href='https://alligator.io/angular/' target='_blank' rel='nofollow'>Alligator.io</a>
* <a href='https://blog.angularindepth.com/tagged/angular' target='_blank' rel='nofollow'>Angular In Depth</a>

View File

@ -0,0 +1,289 @@
---
title: Animations
---
# Animations
#### Motivation
Modern web components frequently use animations. Cascading Style-sheets (CSS) arms developers with the tools to create impressive animations. Property transitions, uniquely named animations, multi-part keyframes are possible with CSS. The animatable possibilities are endless thanks to CSS.
In a modern web application, animation focuses the users attention. Good animations seek to guide the users attention in a satisfying, productive manner. Animations should not prove annoying to the user.
Animations offer feedback in the form of movement. They show the user that the application is actively handling their requests. Something as simple as a visible button press or a loader when the application must load engages the user's attention.
Animations continue to grow more and more relevant in Angulars case. Google develops Angular while promoting the Material Design philosophy. It encourages concise user interfaces (UI) supplemented with animated user feedback. It makes web applications feel somewhat alive and fun to use.
The Angular community develops a core widget library called [Material2](https://github.com/angular/material2). This project adds a variety of widget modules to Angular. Most of them feature animations. To understand how they work, this article recommends studying CSS animations before reading on.
Angular animations is the framework's streamlined version of what CSS natively provides. CSS is the core technology for Angular animations occurring within the web browser. CSS is beyond the scope of this article though. Its time to tackle Angular animations head-on.
#### Setting up Animations
Before animating, the `BrowserAnimationsModule` must include into the root modules imports array. It is available from `@angular/platform-browser/animations`. This NgModule ensures animations work for the given platform. This article assumes the standard web browser for each example.
Angular animations declare within the `@Component` metadata. `@Component` decorates a class to distinguish it as a component to Angular. Its metadata contains component configurations including the `animations: []` field. Each array element from this field represents an animation trigger (`AnimationTriggerMetadata`).
Animations are exclusive to their host component via the decorator's metadata. Animations can only be used in the host components template. Animations do not inherit to the component's children. There is an easy work-around for this.
You could always create a separate file that exports an array. Any component class can import that array from the top of its host file. The imported array token then goes into the animations metadata of the component. Repeat this process for any other components requiring the same array in their animations metadata.
Content projection lets you apply animations to component A's content DOM (Document Object Model). Component B wrapping this content DOM can project the contents into its own template. Once it does, the animations of component A do not negate. Component B incorporates A's animations through content projection.
OK. You know how to setup animations and where to declare them. Implementation is the next step.
#### Animation Methods
Angular animations use a series of method calls importable from `@angular/animations`. Each element of the `@Component` animations array begins as a single method. Its arguments unravel as a sequence of higher-order method calls. The following list shows some of the methods used to build Angular animations.
* `trigger(selector: string, AnimationMetadata[])`
returns `AnimationTriggerMetadata`
* `state(data: string, AnimationStyleMetadata, options?: object)`
returns `AnimationStateMetadata`
* `style(CSSKeyValues: object)`
returns `AnimationStyleMetadata`
* `animate(timing: string|number, AnimationStyleMetadata|KeyframesMetadata)`
returns `AnimationAnimateMetadata`
* `transition(stateChange: string, AnimationMetadata|AnimationMetadata[], options?: object)`
returns `AnimationTransitionMetadata`
While there are certainly [more methods](https://angular.io/api/animations) to pick from, these five methods handle the basics. Trying to understand these core methods as a list does not help very much. Bullet-by-bullet explanations followed by an example will make better sense of it.
##### trigger(selector: string, AnimationMetadata[])
The `trigger(...)` method encapsulates a single element of animation inside the animations array.
The methods first argument `selector: string` matches the `[@selector]` member attribute. It acts like an attribute directive in the component template. It essentially connects the animation element to the template through an attribute selector.
The second argument is an array containing a list of applicable animation methods. The `trigger(...)` keeps it altogether in a single array.
##### state(data: string, AnimationStyleMetadata, options?: object)
The `state(...)` method defines the final state of the animation. It applies a list of CSS properties to the target element after an animation concludes. This is so the animated elements CSS matches the animations resolution.
The first argument matches the value of the data bound to the animation binding. That is, the value bound to `[@selector]` in the template matches against first argument of a `state(...)`. The data's value determines the final state. The changing of the value determines the means of animation (see `transition(...)`).
The second argument hosts the CSS styles that apply to an element post-animation. Styles get passed in by invoking `style(...)` and passing into its argument the desired styles as an object.
A list of options optionally occupies the third argument. The default `state(...)` options should remain unchanged unless reasoned otherwise.
##### style(CSSKeyValues: object)
You may have noticed `AnimationStyleMetadata` several times in the previous list. The `style(...)` component returns this exact type of metadata. Wherever CSS styles apply, the `style(...)` method must invoke. An object containing CSS styles stands-in for its argument.
Of course, styles animatable in CSS carry over into the Angular `style(...)` method. Granted, nothing impossible for CSS becomes suddenly possible with Angular animations.
##### animate(timing: string|number, AnimationStyleMetadata|AnimationKeyframesMetadata)
The `animate(...)` function accepts a timing expression as its first argument. This argument times, paces, and/or delays the method's animation. This argument accepts either a number or string expression. The formatting is explained [here](https://angular.io/api/animations/animate#usage).
The second argument of `animate(...)` is the CSS property warranting the animation. This takes the form of the `style(...)` method which returns `AnimationStyleMetadata`. Think of `animate(...)` as the method that initiates the animation.
A series of keyframes can also apply to the second argument. Keyframes is a more advanced option that this article explains later on. Keyframes distinguish various sections of the animation.
`animate(...)` may not receive a second argument. In that case, the method's animation timing only applies to the CSS reflected in the `state(...)` methods. Property changes in the trigger's `state(...)` methods will animate.
##### transition(changExpr: string, AnimationMetadata|AnimationMetadata[], options?: object)
`animate(...)` initiates an animation while `transition(...)` determines which animation initiates.
The first argument consists of a unique form of micro-syntax. It denotes a change in state (or change in data) taking place. The data bound to the template animation binding (`[selector]="value"`) determines this expression. The upcoming section titled “Animation State” explains this concept a bit further.
The second argument of `transition(...)` comprises `AnimationMetadata` (returned by `animate(...)`). The argument accepts either an array of `AnimationMetadata` or a single instance.
The first argument's value matches against the value of the data bound in the template (`[selector]="value"`) . If a perfect match occurs, the argument evaluates successfully. The second argument then initiates an animation in response to the success of the first.
A list of options optionally occupies the third argument. The default `transition(...)` options should remain unchanged unless reasoned otherwise.
##### Animation Example
```typescript
import { Component, OnInit } from '@angular/core';
import { trigger, state, style, animate, transition } from '@angular/animations';
@Component({
selector: 'app-example',
template: `
<h3>Click the button to change its color!</h3>
<button (click)="toggleIsCorrect()" // event binding
[@toggleClick]="isGreen">Toggle Me!</button> // animation binding
`,
animations: [ // metadata array
trigger('toggleClick', [ // trigger block
state('true', style({ // final CSS following animation
backgroundColor: 'green'
})),
state('false', style({
backgroundColor: 'red'
})),
transition('true => false', animate('1000ms linear')), // animation timing
transition('false => true', animate('1000ms linear'))
])
] // end of trigger block
})
export class ExampleComponent {
isGreen: string = 'true';
toggleIsCorrect() {
this.isGreen = this.isGreen === 'true' ? 'false' : 'true'; // change in data-bound value
}
}
```
The above example performs a very simple color swap with each button click. Of course, the color transitions quickly in a linear fade as per `animate('1000ms linear')`. The animation binds to the button by matching the first argument of `trigger(...)` to the `[@toggleClick]` animation binding.
The binding binds to the value of `isGreen` from the component class. This value determines the resulting color as set by the two `style(...)` methods inside the `trigger(...)` block. The animation binding is one-way so that changes to `isGreen` in the component class notify the template binding. That is, the animation binding `[@toggleClick]`.
The button element in the template also has a `click` event bound to it. Clicking the button causes `isGreen` to toggle values. This changes the component class data. The animation binding picks up on this and invokes its matching `trigger(...)` method. The `trigger(...)` lies within the animations array of the component's metadata. Two things occur upon the triggers invocation.
The first occurrence concerns the two `state(...)` methods. The new value of `isGreen` matches against a `state(...)` methods first argument. Once it matches, the CSS styles of `style(...)` apply to the final state of the animation bindings host element. `The final state takes effect following all animation.
Now for the second occurrence. The data change that invoked the animation binding compares across the two `transition(...)` methods. One of them matches the change in data to their first argument. The first button click caused `isGreen` to go from true to false (true => false). That means the first `transition(...)` method activates its second argument.
The `animate(...)` function corresponding the successfully evaluated `transition(...)` method initiates. This method sets the duration of the animated color fade along with the fade's pacing. The animation executes and the button fades to red.
This process can happen any number of times following a button click. The `backgroundColor` of the button will cycle between green and red in a linear fade.
#### Animation State
The `transition(...)` micro-syntax is worth addressing in detail. Angular determines animations and their timing by evaluating this syntax. There exists the following state transitions. They model a changes in data bound to an animation binding.
* `someValue => anotherValue`
An animation trigger where the bound data changes from someValue to anotherValue.
* `anotherValue => someValue`
An animation trigger where the bound data changes from anotherValue to someValue.
* `someValue <=> anotherValue`
Data changes from someValue` to anotherValue or vice versa.
There also exists `void` and `*` states. `void` indicates that the component is either entering or leaving the DOM. This is perfect for entry and exit animations.
* `someValue => void` : host component of bound data is *leaving* the DOM
* `void => someValue` : host component of bound data is *entering* the DOM
`*` denotes a wildcard state. Wildcard states can interpret to “any state”. This includes `void` plus any other change to the bound data.
#### Keyframes
This article touched on the basics for animating Angular applications. Advanced animation techniques exist alongside these basics. Grouping together keyframes is one such technique. Its inspired from the `@keyframes` CSS rule. If you have worked with CSS `@keyframes`, you already understand how keyframes in Angular work. It becomes just a matter of syntax
The `keyframes(...)` method imports from `@angular/animations`. It passes into the second argument of `animate(...)` instead of the typical `AnimationStyleMetadata`. The `keyframes(...)` method accepts one argument as an array of `AnimationStyleMetadata`. This can also be referred to as an array of `style(...)` methods.
Each keyframe of the animation goes inside the `keyframes(...)` array. These keyframe elements are `style(...)` methods supporting the `offset` property. `offset` indicates a point in the animations duration where its accompanying style properties should apply. Its value spans from 0 (animation start) to 1 (animation end).
```typescript
import { Component } from '@angular/core';
import { trigger, state, style, animate, transition, keyframes } from '@angular/animations';
@Component({
selector: 'app-example',
styles: [
`.ball {
position: relative;
background-color: black;
border-radius: 50%;
top: 200px;
height: 25px;
width: 25px;
}`
],
template: `
<h3>Arcing Ball Animation</h3>
<button (click)="toggleBounce()">Arc the Ball!</button>
<div [@animateArc]="arc" class="ball"></div>
`,
animations: [
trigger('animateArc', [
state('true', style({
left: '400px',
top: '200px'
})),
state('false', style({
left: '0',
top: '200px'
})),
transition('false => true', animate('1000ms linear', keyframes([
style({ left: '0', top: '200px', offset: 0 }),
style({ left: '200px', top: '100px', offset: 0.50 }),
style({ left: '400px', top: '200px', offset: 1 })
]))),
transition('true => false', animate('1000ms linear', keyframes([
style({ left: '400px', top: '200px', offset: 0 }),
style({ left: '200px', top: '100px', offset: 0.50 }),
style({ left: '0', top: '200px', offset: 1 })
])))
])
]
})
export class ExampleComponent {
arc: string = 'false';
toggleBounce(){
this.arc = this.arc === 'false' ? 'true' : 'false';
}
}
```
The main difference of the above example compared to the other example is the second argument of `animate(...)`. It now contains a `keyframes(...)` method hosting an array of animation keyframes. While the animation itself is also different, the technique to animate is similar.
Clicking the button causes the button to arc across the screen. The arc moves as per the `keyframes(...)` methods array elements (keyframes). At the animations mid-point (`offset: 0.50`), the ball changes trajectory. It descends to its original height as it continues across the screen. Clicking the button again reverses the animation.
`left` and `top` are animatable properties after setting `position: relative;` for the element. The `transform` property can perform similar movement-based animations. `transform` is an expansive yet fully animatable property.
Any number of keyframes can existing between offset 0 and 1. Intricate animation sequences take the form of keyframes. They are one of many advanced techniques in Angular animations.
### Animations With Host Binding
You will undoubtedly come across the situation where you want to attach an animation to the HTML element of a component itself, instead of an element in the component's template. This requires a little more effort since you can't just go into the template HTML and attach the animation there. Instead, you'll have to import `HostBinding` and utilize that.
The minimal code for this scenario is shown below. I'll re-use the same animation condition for the code above for consistency and I don't show any of the actual animation code since you can easily find that above.
```typescript
import { Component, HostBinding } from '@angular/core';
@Component({
...
})
export class ExampleComponent {
@HostBinding('@animateArc') get arcAnimation() {
return this.arc;
}
}
```
The idea behind animating the host component is pretty much the same as animating a element from the template with the only difference being your lack of access to the element you are animating. You still have to pass the name of the animation (`@animateArc`) when declaring the `HostBinding` and you still have to return the current state of the animation (`this.arc`). The name of the function doesn't actual matter, so `arcAnimation` could have been changed to anything, as long as it doesn't clash with existing property names on the component, and it would work perfectly fine.
#### Conclusion
This covers the basics of animating with Angular. Angular makes setting up animations very easy using the Angular CLI. Getting started with your first animation only requires a single component class. Remember, animations scope to the components template. Export your transitions array from a separate file if you plan to use it across multiple components.
Every animation utility/method exports from `@angular/animations`. They all work together to provide a robust system of animation inspired from CSS. There are more methods beyond what this article could cover.
Now that you know the basics, feel free to explore the links below for more on Angular animations.
## Sources
- [Angular Team. “Animations”. *Google*. Accessed 7 June 2018.](https://angular.io/guide/animations)
- [Angular Team. “Animations Package”. *Google*. Accessed 7 June 2018.](https://angular.io/api/animations)
## Resources
- [Angular Documentation](https://angular.io/guide)
- [Angular Animations Tutorial](https://angular.io/guide/animations)
- [Angular Animations API](https://angular.io/api/animations )
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Angular CLI](https://cli.angular.io)

View File

@ -0,0 +1,136 @@
---
title: Command-line Interface
---
## Command-line Interface
#### Motivation
Angular is closely associated with its command-line interface (CLI). The CLI streamlines generation of the Angular file system. It deals with most of the configuration behind the scenes so developers can start coding. The CLI also has a low learning curve recommendable for any newcomer wanting to jump right in. Heck, even experienced Angular developers rely on the CLI!
#### Installation
The Angular CLI requires [Node.js and Node Packet Manager (NPM)](https://nodejs.org/en/). You can check for these programs with the terminal command: `node -v; npm -v`. Once installed, open a terminal and install the Angular CLI with this command: `npm install -g @angular/cli` or `pm install -g @angular/cli@latest` to install the latest version of angular cli. This can executed from anywhere on your system. The CLI is configured for global use with the `-g` flag.
Verify the CLI is there with the command: `ng -v`. This outputs several lines of information about the angular cli installed in your machine. One of these lines state the version of the installed CLI.
Recognize that `ng` is the basic building block of the CLI. All your commands will begin with `ng`. Time to take a look at four of the most common commands prefixed with `ng`.
#### Key Commands
* ng new
* ng serve
* ng generate
* ng build
* ng update
The key terms for each of these are quite telling. Together, they comprise what you will need to hit the ground running with Angular. Of course, there are many more. All commands are outlined in the [CLI's GitHub Documentation<sup>1</sup>](https://github.com/angular/angular-cli/wiki#additional-commands). You will likely find that the commands listed above will cover the necessary bases.
#### ng new
`ng new` creates a *new* Angular file system. This is a surreal process. Please navigate to a file location desirable for *new* application generation. Type this command as follows, replacing `[name-of-app]` with whatever you want: `ng new [name-of-app]`. For Example `ng new myapp` here `myapp` the name which I've given to my app. Which will generate your app with a default folder structure. There wil be a lot of generated files, Don't consider every file. You'll be mostly working with the src folder.
But Feel free to explore other files within. Try to not make any changes yet. All of what you need to run your first Angular application comes packaged together in this generated file system.
#### ng serve
To get the application running, the `ng serve` command must execute within the `[name-of-app]` folder. Anywhere within the folder will do. The Angular CLI must recognize that it is within an environment generated with `ng new`. It will run provided this one condition. Go ahead and try it: `ng serve`.
The application runs on port 4200 by default. You can view the Angular application by navigating to `localhost:4200` in any web browser. Angular works across all browsers. Unless you are using an old version of Internet Explorer, the application will pop up. It displays the official Angular logo alongside a list of helpful links.
Ok, the application runs. It hopefully functions, but you need to know what is going on under the hood. Refer back to the `[name-of-app]` file system. Navigate `[name-of-app] -> src -> app`. Therein lies the files responsible for what you saw on `localhost:4200`.
Okay, What if you are running 2 Angular app which runs on PORT 4200 by default or let me say that the PORT 4200 has been busy? You can change your default PORT by using a cli commang `ng serve --port 4000` here 4000 is the PORT that I want to run. You can change it to a PORT that ypu wnat to run your app.
#### ng generate
The `.component` files define an Angular component including its logic (`.ts`), style (`.css`), layout (`.html`), and testing (`.spec.ts`). The `app.module.ts` particularly stands out. Together, these two groups of files work together as `component` and `module`. Both `component` and `module` are two separate examples of Angular schematics. Schematics classify the different purpose-driven blocks of code *generatable* with `ng generate`.
For the sake of this article, understand that a `module` exports and imports assets to and from an underlying component tree. A `component` concerns itself with one section of the user interface. That unit's logic, style, layout, and testing stays encapsulated within the various `.component` files.
As for `ng generate`, this command can generate skeletons for each of the available [Angular schematics<sup>2</sup>](https://github.com/angular/angular-cli/wiki/generate#available-schematics). Navigate to `[name-of-app -> src -> app]`. Try generating a new `component` by executing: `ng generate component [name-of-component]`. Replace `[name-of-component]` with whatever you would like. A new file `[name-of-component]` will pop up along with its necessary `component` files.
You can see that `ng generate`expedites Angulars [boilerplate code](https://en.wikipedia.org/wiki/Boilerplate_code). `ng generate` also wires things up. Schematics created within context of an Angular file system connect with the systems root module. In this case, that would be `app.module.ts` file inside `[name-of-app -> src -> app]`.
#### ng build
Angular is a front end tool. The CLI performs its operations on behalf of the front end. `ng serve` takes care of the back end server setup. This keeps development entirely focused on the front end. That said, connecting your own back end to the Angular application must also be possible.
`ng build` fulfills this need. Before trying it out inside of the file system. Navigate to `[name-of-app] -> angular.json`. Look for this single line of code: `"outputPath": "dist/my-app"`.
This one line of configuration determines where `ng build` dumps its results. The results being the entire Angular application compiled into one folder `dist/my-app`. Inside of that folder, there exists `index.html`. The whole Angular application can run with `index.html`. No `ng serve` is necessary from here. With this file, you can easily wire up your back end.
Give it a go: `ng build`. Again, this must execute within the Angular file system. Based of the key value of `“outputPath:”` in `angular.json`. A file will generate wherein the original application is fully compiled. If you kept `“outputPath:”` the same, the compiled application will be in: `[name-of-app] -> dist -> [name-of-app]`.
#### ng update
In angular cli ng update do automatic updation on all the angular and npm packages to latest versions.
Here is the syntax and options can be used with `ng update`.
`ng update [package]`
**Options**
- dry-run
`--dry-run (alias: -d)`
Run through without making any changes.
- force
`--force`
If false, will error out if installed packages are incompatible with the update.
- all
`--all`
Whether to update all packages in package.json.
- next
`--next`
Use the largest version, including beta and RCs.
- migrate-only
`--migrate-only`
Only perform a migration, does not update the installed version.
- from
`--from`
Version from which to migrate from. Only available with a single package being updated, and only on migration only.
- to
`--to`
Version up to which to apply migrations. Only available with a single package being updated, and only on migrations only. Requires from to be specified. Default to the installed version detected.
- registry
`--registry`
The NPM registry to use.
#### Conclusion
These commands fulfill the basics. Angulars CLI is an incredible convenience that expedites application generation, configuration, and expansion. It does all this while maintaining flexibility, allowing the developer to make necessary changes.
Please check out those links on `localhost:4200` if you have not already. Do not forget to run `ng serve` before opening it up. With a better understanding of the CLI, you are now ready to learn more about what is generated by its most essential commands.
### Sources
1. [Google. “angular/angular-cli/wiki#additional-commands.” GitHub.](https://github.com/angular/angular-cli/wiki#additional-commands)
2. [Google. “angular/angular-cli/wiki/generate#available-schematics.” GitHub.](https://github.com/angular/angular-cli/wiki/generate#available-schematics)
### Resources
- [Angular CLI Website](https://cli.angular.io)
- [Angular CLI README](https://github.com/angular/angular-cli#angular-cli)
- [Angular CLI Documentation](https://github.com/angular/angular-cli/wiki)

View File

@ -0,0 +1,267 @@
---
title: Components
---
# Components
#### Motivation
Angular contains many *schematics* for building applications. Components are one such schematic. They encompass a single unit of logic concerned with a single part of the application. Components often partner with other schematics to operate more effectively.
Among all schematics, components tend to consume more than provide. While other schematics like directives, pipes, and services offer utility, components utilize. They are responsible for the application interface so it makes sense why the consume utility.
Components simplify the application. Funneling logic into a single section of the visible interface is their primary goal. To build applications step-by-step, you must build component-by-component. Components act as Angular's building blocks after all.
#### Components Introduction
As mentioned, components consume utility (services/resources). They stand between business logic and presentation to produce a cohesive unit. Angular attaches various mechanisms to each component. These attachments identify a class as a component and define its standard capabilities.
Angular must recognize components when it comes across them. To do this, `@Component` must decorate every class intended to be a component. Decorators indicate to Angular what the class' is.
In the case of a component, it must know how to interact with its injector, connect with a template, pull from a list of styles, encapsulate its styles, and so on. Angular takes care of most of the low-level requirements. Developers still need to configure a component's behavior, import its dependencies, and extend its logic.
For all such things, we have the component's class. The class keeps everything relatively uniform. It encapsulates the component's business logic.
#### Component Class and Metadata
Go ahead and install the [Angular command-line interface (CLI)](https://cli.angular.io). You can learn more about it from [this article](https://guide.freecodecamp.org/angular/command-line-interface). The CLI command `ng generate component [name-of-component]` yields the following.
```typescript
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {
constructor() { }
ngOnInit() { }
}
```
This is the basic skeleton from which all great components originate. The `@Component` decorator is the most important part. Without it, the above example becomes a generic class. Angular relies on decorators to discern a class' schematic type.
`@Component` receives metadata as a single object. Decorators are just JavaScript functions under the hood. They take in arguments as with the metadata object. The metadata object configures a component's basic dependencies. Each fields plays a role.
* `selector:` tells Angular to associate the component with a certain element in the applications template HTML.
* `templateUrl:` accepts the file location of the components template HTML (this is where data gets displayed to).
* `styleUrls:` accepts an array of style-sheet file locations (strings). These style-sheets target the components assigned template.
Think of metadata as a big blob of configuration. The decorator takes it so that it can generate the data specific to the component. The decorator *decorates* the underlying class with data necessary for its class' behavior. A *component* class that is.
The class' signature exports by default so that the component can be imported. `ngOnInit` also gets implemented. `implements` tells the class to define certain methods per the interface's definition. `ngOnInit` is a lifecycle hook.
#### Component Lifecycle and Change Detection
Components use all sorts of tools, services, and feature. One key feature available to components is lifecycle hooks. An explanation for each hook exists [on this article](https://guide.freecodecamp.org/angular/lifecycle-hooks).
There are a eight in total and they all serve as timing functions. They execute conditionally as the component transitions from state-to-state via [change detection](https://blog.angularindepth.com/everything-you-need-to-know-about-change-detection-in-angular-8006c51d206f). This process happens constantly across the component tree. It searches for changes in data which merit a re-rendering of the template.
Time to move on. Please refer to the aforementioned articles for more information on the component lifecycle. It deserves much more explanation.
#### Component Data
Data drives everything. Components are no exception. Components encapsulate all their data. To receive data externally, a component must explicitly declare it. This form of privacy keeps information from clashing across the component tree.
Data determines what gets displayed from the component class to its template. Any updates to the class data will (or at least should) update the template display.
Components will often initialize a set of members (or variables) that store data. They are used throughout the component class logic for convenience. This information fuels the logic resulting in the template and its behavior. See the following example.
```typescript
// ./components/example/example.component.ts
import { Component, OnInit } from '@angular/core';
import { Post, DATA } from '../../data/posts.data';
@Component({
selector: 'app-example',
templateUrl: './example.component.html'
})
export class ExampleComponent implements OnInit {
username: string;
totalPosts: number;
allPosts: Post[];
deletePost(index: number): void {
this.allPosts.splice(index, 1);
this.totalPosts = this.allPosts.length;
}
ngOnInit(): void {
this.username = DATA.author;
this.totalPosts = DATA.thePosts.length;
this.allPosts = DATA.thePosts;
}
}
```
```html
<!-- ./components/example/example.component.html -->
<h1>{{ username }}</h1>
<span>Change Name: </span><input [(ngModel)]="username">
<h3>Posts: {{ totalPosts }}</h3>
<ul>
<hr/>
<div *ngFor="let post of allPosts; let i=index">
<button (click)="deletePost(i)">DELETE</button>
<h6>{{ post.title }}</h6>
<p>{{ post.body }}</p>
<hr/>
</div>
</ul>
```
Note the ways the component interacts with its data. It first fetches it from `../../data/posts.data` before it begins to forward it to the template for display.
The data shows up throughout the template. Inside the double curly braces, a variables value is mapped from the component class into the braces. The `*ngFor` loops across the `allPosts` class array. Clicking on the button removes a specific element from `allPosts` by its index. You can even change the topmost `username` by typing into the input box.
The above interactions alter the component class' data which in turn updates the component's template HTML. Components provide the backbone logic that facilitates the flow of data. The template HTML makes that data readable to the user.
#### Component Template
The previous examples template HTML featured an interesting syntax. The syntax was not actual HTML. It was Angulars template HTML. Some often refer to it has HTML *Plus* recognizable only by Angular's compiler. The compiler supports a syntax resulting in the dynamic manipulation of HTML. This article will often refer to it as 'template HTML' or 'template'.
The syntax lets components inject data directly into the template HTML. The injection is dynamic. Meaning, data can iterate and display itself as HTML without needing external assistance. The Angular compiler compiles it into real HTML by the time it reaches the web browser.
To learn more about some of the ways data binds to the template, read about [data binding in Angular](https://guide.freecodecamp.org/angular/data-binding). A few examples of data binding occurred in the previous example (`{{ ... }}`). For this article, it is enough to recognize data interactions were happening between the component class and its template.
#### Querying the Template
Data managing the state of the template imperatively works OK. Yet, pure data does not always fulfill an application's intended design. Interacting more directly with the Document Object Model (DOM) may be required.
To do that, the component must have reference to the template elements. When the data changes, the component can manipulate the DOM explicitly. This is a more declarative approach.
Components can grab references using a web browsers DOM application programming interface (API). Bad idea though. Angular prefers cross-platform compatibility. For a component to function outside of the web browser, it needs to use Angulars API instead of the DOM's.
Components can query their templates using the `@ViewChild` and `ContentChild` decorators. They grab references to template elements on behalf of the component class.
```typescript
import { Component, ViewChild, ContentChild, ElementRef, Renderer2, AfterContentChecked, AfterViewChecked } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="toggleEnlarge()">Toggle Enlarge</button>
<ng-content></ng-content>
`
})
export class ChildComponent implements AfterContentChecked {
@ContentChild("pReference", { read: ElementRef }) pElement: ElementRef;
textEnlarge: boolean = false;
constructor(private renderer: Renderer2) { }
toggleEnlarge() {
this.textEnlarge = !this.textEnlarge;
}
ngAfterContentChecked() {
if (this.textEnlarge)
this.renderer.setStyle(this.pElement.nativeElement, 'font-size', '25px');
else
this.renderer.setStyle(this.pElement.nativeElement, 'font-size', 'initial');
}
}
@Component({
selector: 'app-parent',
template: `
<button (click)="toggleHighlight()">Toggle Highlight</button>
<h1 #hOneRefereance>View Child</h1>
<app-child>
<p #pReference>Content Child</p>
</app-child>
`
})
export class ParentComponent implements AfterViewChecked {
@ViewChild("hOneRefereance", { read: ElementRef }) hOneElement: ElementRef;
textHighlight: boolean = false;
constructor(private renderer: Renderer2) { }
toggleHighlight() {
this.textHighlight = !this.textHighlight;
}
ngAfterViewChecked() {
if (this.textHighlight)
this.renderer.setStyle(this.hOneElement.nativeElement, 'background-color', 'yellow');
else
this.renderer.setStyle(this.hOneElement.nativeElement, 'background-color', 'initial');
}
}
```
The above example contains two buttons that toggle a certain style for each element. Clicking the buttons toggles the true/false values unique to each component. These booleans determine if the custom styles apply. Instead of these values causing changes imperatively, the lifecycle hooks (`ngAfterViewChecked` and `ngAfterContentChecked`) declaratively alter the DOM.
The declarative approach explicitly changes the style through the elements reference. In imperative programming, changes to the DOM based off data are implicit. Check out this article on [imperative and declarative programming](https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2) to learn more.
The main thing to notice is how these references get pulled from the template. In the example, there are two sections of the template queried using two decorators: `@ViewChild` and `@ContentChild`.
They differ in where they look for an elements reference whether it be in the content DOM or view DOM. These two DOMs exist in ParentComponents template. Differentiating between them is important because they finish rendering at separate times.
This is why `@ViewChild` and `@ContentChild` both exist. They work together with their companion lifecycle hooks `ngAfterViewChecked` and `ngAfterContentChecked`. These lifecycle hooks wait for their respective queries to resolve before executing.
Once resolved, `@ViewChild` and `@ContentChild` provide references to two elements. Both exist in separate parts of the DOM. The boolean data still determines the outcome. How that outcome translates to the DOM is the key difference from before. The DOM updates via`Renderer2`'s direct manipulation of it.
#### Content Projection
The content DOM exists in the innerHTML of ChildComponents `<app-child></app-child>` element. It is all positioned within ParentComponents template. The innerHTML of `app-child` *projects* onto ChildComponents template through `<ng-content></ng-content>`.
This exemplifies content projection. Displaying content from `one` component to another using the innerHTML of `another`s tags in `one`s template so that `another` component can pull that innerHTML into its own template via `<ng-content></ng-content>`. *Thank you for reading that sentence.*
Hence why ChildComponent references its `<p></p>` element using `@ContentChild`. Content contained within `<app-child></app-child>` in ParentComponent's template makes up the content DOM. ChildComponent references the element with an `@ContentChild` query.
ParentComponent's view DOM consists of everything accessible from within the components view. This does not necessarily include the entire template given the innerHTML of `<app-child></app-child>`. Again, this part of the DOM is queried from ChildComponent using `@ContentChild`. Everything else gets queried using `@ViewChild` from the ParentComponent class.
This is a great way for components to exchange content and query its own content regardless of its DOM type. Components can communicate with itself and others using data binding as well. Read more about it from [this article](https://guide.freecodecamp.org/angular/data-binding).
#### Component Styles
Styles are critical to a components readability and interactivity. Each component encapsulates its style-sheet dependencies. That way they only apply to the component's template HTML. A special technique introduced by HTMLs shadow DOM makes this possible.
A shadow DOM branch may exist on any element. This part of the DOM cannot be seen from the HTML's source code. Standard HTML elements leverage the shadow DOM to provide their trademark appearances. A shadow DOM branch must anchor itself to a visible component so that it can style and customize it.
The unique aspect about a shadow DOM branch is its encapsulation. Everything used to style a shadow DOM branchs root element is private to it. No other element can access it.
Angular embraces this form of encapsulation with components. The style-sheet and template of a component encapsulate together. No other components have access to them. Style-sheet clashes cannot occur.
Angular does not use the shadow DOM by default. It uses an emulation system that mimics the behavior of the shadow DOM. This is a temporary measure since some web browsers do not yet support the shadow DOM API.
The `@Component` metadata contains the `encapsulation` field. This lets developers toggle in-between emulated shadow DOM, real shadow DOM, or neither. Here are the options in their respective order:
* `ViewEncapsulation.Emulated` - fake shadow DOM (default)
* `ViewEncapsulation.Native` - real shadow DOM (now deprecated since Angular 6.0.8)
* `ViewEncapsulation.None` - neither
`ViewEncapsulation.None` means the component's style-sheets elevate to the global scope. Not recommended considering components should form their own private unit (encapsulation). Angular still provides it as an escape hatch for extreme situations.
#### Conclusion
Components build applications. They are privately scoped and separately uniform of each other unless configured otherwise. Applications tend to begin from the root module. Past that, components form an elongated tree defining the rest of the application.
A components covers a designated unit of the application interface. This includes its styles, logic, and layout. Other schematics such as pipes, services, and directives see frequent use in component code. You can learn more about these interactions in some of the other Angular guide articles.
Do not forget that components must [bootstrap](https://angular.io/guide/bootstrapping). This can happen in the root module or the components metadata. This is so Angular recognizes the component wherever it appears in the application.
You can always learn more by exploring the below links leading. Component carry far more depth than that what this article could convey.
## Sources
- [Angular Team. “Angular Docs”. *Google*. Accessed 3 June 2018](https://angular.io/guide)
- [Mozilla MDN Community. “Using Shadow DOM”. *Mozilla*, updated 30 May 2018. Accessed 3 June 2018](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)
- [Mundy, Ian. “Declarative vs Imperative Programming”. *codeburst.io*, 20 Feb. 2017. Accessed 3 June 2018](https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2)
## Resources
- [Angular Documentation](https://angular.io/guide)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Intro to Components](https://angular.io/guide/architecture-components)
- [Components in Depth](https://angular.io/guide/displaying-data)
- [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)

View File

@ -0,0 +1,195 @@
---
title: Data Binding
---
# Data Binding
#### Motivation
Data often defines the look of an application. Interpreting that data into the user interface involves class logic (`.component.html`) and a template view (`.component.ts`) . Angular connects them through data binding. Think of data binding as a tool for component interaction.
#### Component and Template
The component stores most of its logic and data inside of its class decorated with `@Component`. This decorator defines the class as a component with template HTML. The template of the component represents the class within the application. The focus here needs to be between the component's class and the template HTML.
This is where data binding occurs. Element properties and events get assigned values. These values, defined by the component class, serve either one of two roles. One is to produce data that the template then receives. The other handles events emitted by the template element.
![Code Example](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image4.png)
Try to use this picture as a mental model for the next section.
#### Directions of Binding
There are two ways in which data is bound: unidirectional and bidirectional. Angular technically only uses unidirectional data flow. Bidirectional flow is ultimately unidirectional. It happens in two applications of unidirectional flow, once for each direction. More on that later.
Unidirectional flow defines one-way interaction. Either the component sends data to the template or the template emits an event to the component logic. Data changes within scope of the template are not percolate to the component class. Event emitting is a one-way transaction beginning from the template's elements.
Bidirectional constitutes both directions. This means changes to the data in the class logic or template HTML persist across each other. The scope of the changes are the component's view. The view comprises the component's class and template together.
#### Element Properties
To recognize data-bound element properties, Angular uses a special bracket syntax.
```typescript
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
value:type = /* some value of type */;
}
```
```html
<!-- my.component.html -->
<any-element [property]=“value>innerHTML</any-element>
```
Bear with me on this one.
`[property]` mirrors the property in the Domain Object Model (DOM) element's object node. Do not confuse object properties with a DOM element's attributes. Properties and attributes often share the same name and do the same thing. There is one clear distinction however.
Remember that `attr` (attributes) is a single property of the underlying DOM object. It gets declared at the DOMs instantiation with attribute values matching the element's definition. It maintains the same value after that. Properties each have their own key-value field in a DOM object node. These properties are mutable post-instantiation.
Know the difference between attributes and properties. It will lead to a better understanding of how Angular binds data to properties (property binding). Angular will hardly ever bind data to an elements attributes. Exceptions to this are very rare. One last time: Angular binds component data to properties, not attributes!
Referring back to the example, the `[ … ]` in the element's property assignment have special meaning. The brackets show that `property` is bound to `“value”` on the right of the assignment.
`value` also has special meaning within context of the brackets. `value` by itself is a string literal. Angular reads it and matches its value against component class members. Angular will substitute the value of the matching member attribute. This of course refers to the same component class that hosts the template HTML.
The unidirectional flow of data from component to template is complete. The member matched against right assignment of the bracketed property provides the `value`. Note that changes to the member's value in the component class percolate down to the template. That is Angular's change detection at work. Changes within the template's scope have no effect on the component class member.
Key take-away: the component class provides the data while the template displays it.
I failed to mention that data values can also show up in a components `innerHTML`. This last example implements double curly braces. Angular recognizes these braces and interpolates the matching component class data into the `innerHTML` of the `div`.
```html
<div>The value of the component class member value is {{value}}.</div>
```
#### Event Handling
If the component supplies data, then the template supplies events.
```typescript
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
handler(event):void {
// function does stuff
}
}
```
```html
// my.component.html
<any-element (event)=“handler($event)”>innerHTML</any-element>
```
This works similarly to property binding.
The `(event)` pertains to any valid event type. For example, one of the most common event types is `click`. It emits when you *click* your mouse. Regardless of the type, `event` is bound to `“handler”` in the example. Event handlers are usually member functions of the component class.
The `( … )` are special to Angular. Parenthesis tell Angular an event is bounded to the right assignment of `handler`. The event itself originates from the host element.
When the event does emit, it passes the Event object in the form of `$event`. The `handler` maps to the identically named `handler` function of the component class. The unidirectional exchange from the event-bound element to the component class is complete.
Emitting events from the handler, while possible, do not impact the template element. The binding is unidirectional after all.
#### Bidirectional Binding
Input forms provide a great example of why bidirectional binding is necessary. Bidirectional data bindings are more costly than event or property bindings.
Bidirectional data binding has its own module. Before taking a look at that, consider the following example.
```typescript
// my.component.ts
@Component({
templateUrl: './my.component.html'
})
export class MyComponent {
inputValue:string = "";
handler(event) {
this.inputValue = event.target.value;
}
}
```
```html
<!-- my.component.html -->
<input (input)=“handler($event)” [value]=“inputValue>
```
Time to break this down.
This example combines the previous two. That explains why it is more costly. Following the logic, assume the user types something into the input element. The element emits an `input` event to the `handler` of the templates component class. The handler assigns the class member `inputValue` to the value of the emitted event. This concludes the event handling/binding.
Now onto the property binding. The `inputValue` was assigned a new value. Since `inputValue` is bound to the input element's `value`, its change in data percolates down into the input element's `value` property. The input elements `value` matches up with `inputValue`. This concludes the property binding.
There you have it. Bidirectional data binding happens with both applications of unidirectional binding applied consecutively. The syntax is a bit messy though.
Thankfully, Angular provides `NgModel` to simplify the syntax. The below example is synonymous to the above.
```typescript
// my.component.ts
@Component({
templateUrl: ./my.component.html
})
export class MyComponent {
inputValue:string = "";
}
```
```html
<!-- my.component.html -->
<input [(ngModel)]=“inputValue>
```
`ngModel` is a nice convenience. You have to import the FormsModule in your application's root before using it. With that squared away, bidirectional data binding becomes much easier to work with.
To reinforce all you have learned, check out this picture from the official [Angular Documentation<sup>1</sup>](https://angular.io/guide/architecture-components#data-binding).
![Data Flow Diagram](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image2.png)
You can visually summarize everything up until this point with this picture. Angular's Documentation has plenty of other pictures worth seeing. This one should suffice given the scope of this article.
#### Component to Component
To bind data and events across different components, you must use the @Input and @Output decorators. Angular components are privately scoped. None of a components members are accessible from anywhere outside of its native view.
The @Input decorator indicates a member's value is sourced from the parent function. This requires visualization to better understand.
![Code Example](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image3_.png)
Notice the passing of the parents `value` member into the childs `property` member. This would not be possible if `property` had no @Input decorator. The Angular compiler depends upon it.
Another example for @Output shows how an event travels from child to parent. Keep in mind that @Output almost always pertains to custom event bindings.
![Code Example](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image1.png)
Make sure you import `EventEmitter`, `@Input`, and `@Output` from `@angular/common` if you intend to replicate either of these examples.
#### Conclusion
This is a good place to stop. Data binding spans a wide array of use cases. This topic is worth exploring further on [Angular's website](https://angular.io). These are not the only ways that you can manipulate data in Angular. See the links under Resources for more information.
### Sources
1. [Angular Team. Intro to Components. Google. Accessed 26 May 2018](https://angular.io/guide/architecture-components#data-binding)
### Resources
- [Angular Documentation](https://angular.io/docs)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [More on Components and Templates in Angular](https://angular.io/guide/displaying-data)

View File

@ -0,0 +1,276 @@
---
title: Dependency Injection
---
# Dependency Injection
#### Motivation
Dependency Injection is often more simply referred to as DI. The paradigm exists throughout Angular. It keeps code flexible, testable, and mutable. Classes can inherit external logic without knowing how to create it. Any consumers of those classes also do not need to know anything.
DI saves classes and consumers alike from having to know more than necessary. Yet the code is as modular as it was before thanks to the mechanisms supporting DI in Angular.
Services are a key benefactor of DI. They rely on the paradigm for *injection* into various consumers. Those consumers can then take advantage of that service provides and/or forward it elsewhere.
Service are not alone. Directives, pipes, components, and so on: every schematic in Angular benefits from DI in some way or another.
#### Injectors
Injectors are data structures that store instructions detailing where and how services form. They act as intermediaries within the Angular DI system.
Module, directive, and component classes contain metadata specific to injectors. A new injector instance accompanies every one of these classes. In this way, the application tree mirrors its hierarchy of injectors.
The `providers: []` metadata accepts services that then register with the class injector. This provider field adds the instructions necessary for an injector to function. A class (assuming it has dependencies) instantiates a service by taking on its class as its data type. The injector aligns this type a creates an instance of that service on the class' behalf.
Of course, the class can only instantiate what the injector has instructions for. If the class own injector does not have the service registered, then it queries its parent. So on and so forth until either reaching an injector with the service or the application root.
Services can register at any injector within the application. Services go in the `providers: []` metadata field of class modules, directives, or components. The class' children can instantiate a service registered in the class injector. Child injectors fallback on parent injectors after all.
#### Dependency Injection
Take a look at the skeletons for each class: service, module, directive, and component.
```typescript
// service
import { Injectable } from '@angular/core';
@Injectable({
providedIn: /* injector goes here */
})
export class TemplateService {
constructor() { }
}
```
```typescript
// module
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
imports: [
CommonModule
],
declarations: [],
providers: [ /* services go here */ ]
})
export class TemplateModule { }
```
```typescript
// directive
import { Directive } from '@angular/core';
@Directive({
selector: '[appTemplate]',
providers: [ /* services go here */ ]
})
export class TemplateDirective {
constructor() { }
}
```
```typescript
//component
import { Component } from '@angular/core';
@Component({
selector: 'app-template',
templateUrl: './template.component.html',
styleUrls: ['./template.component.css'],
providers: [ /* services go here */ ]
})
export class TemplateComponent {
// class logic ...
}
```
Each skeleton can register services to an injector. In fact, TemplateService *is* a service. As of Angular 6, services can now register with injectors using `@Injectable` metadata.
##### In Any Case
Notice the `providedIn: string` (`@Injectable`) and `providers: []` (`@Directive`, `@Componet` and `@Module`) metadata. They tell injectors where and how to create a service. Otherwise, injectors would not know how to instantiate.
What if a service has dependencies? Where would the results go? Providers answers those question so that injectors can instantiate properly.
Injectors form the backbone of the DI framework. They store instructions to instantiate services so consumers do not have to. They receive service instances without needing to know anything about the source dependency!
I should also note that other schematics without injectors can still utilize dependency injection. They cannot register additional services but they can still instantiate from injectors.
##### Service
The `providedIn: string` metadata of `@Injectable` specifies which injector to register with. Using this method, and depending on if the service gets used, the service may or may not register with the injector. Angular calls this *tree-shaking*.
By default the value is set to `root`. This translates to the root injector of the application. Basically, setting the field to `root` makes the service available anywhere.
##### Quick Note
As previously mentioned, child injectors fallback on their parents. This fallback strategy ensures parents do not have to re-register for every injector. Refer to this article on [Services and Injectors](https://guide.freecodecamp.org/angular/services-and-injectors) for an illustration of this concept.
Registered services are *singletons*. Meaning, the instructions to instantiate the service exists on only one injector. This assumes it has not been explicitly registered elsewhere.
##### Module, Directive, and Component
Modules and components each have their own injector instance. This is evident given the `providers: []` metadata field. This field takes an array of services and registers them with the injector of the module or component class. This approach happens in the `@NgModule`, `@Directive`, or `@Component` decorators.
This strategy omits *tree-shaking*, or the optional removal of unused services from injectors. Service instances live on their injectors for the life of the module or component.
#### Instantiating References
References to the DOM can instantiate from any class. Keep in mind that references are still services. They differ from traditional services in representing the state of something else. These services include functions to interact with their reference.
Directives are in constant need of DOM references. Directives perform mutations on their host elements through these references. See the following example. The directive's injector instantiates a reference of the host element into the class' constructor.
```typescript
// directives/highlight.directive.ts
import { Directive, ElementRef, Renderer2, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(
private renderer: Renderer2,
private host: ElementRef
) { }
@Input() set appHighlight (color: string) {
this.renderer.setStyle(this.host.nativeElement, 'background-color', color);
}
}
```
```html
// app.component.html
<p [appHighlight]="'yellow'">Highlighted Text!</p>
```
`Renderer2` also gets instantiated. Which injector do these services come from? Well, each service's source code comes from `@angular/core`. These services must then register with the applications root injector.
```typescript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { HighlightDirective } from './directives/highlight.directive';
@NgModule({
declarations: [
AppComponent,
HighlightDirective
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [
AppComponent
]
})
export class AppModule { }
```
An empty providers array!? Not to fear. Angular registers many services with the root injector automatically. This includes `ElementRef` and `Renderer2`. In this example, we are managing the host element through its interface stemming from the instantiation of `ElementRef`. `Renderer2` lets us update the DOM through Angulars view model.
You can read more about views from [this article](https://guide.freecodecamp.org/angular/views). They are the preferred method for DOM/view updates in Angular applications.
It is important recognize the role that injectors play in the above example. By declaring variable types in the constructor, the class obtains valuable services. Each parameter's data type maps to a set of instructions within the injector. If the injector has that type, it returns an instance of said type.
#### Instantiating Services
The [Services and Injectors](https://guide.freecodecamp.org/angular/services-and-injectors) article explains this section to an extent. Though, this section rehashes the previous section or the most part. Services will often provide references to something else. They may just as well provide an interface extending a class capabilities.
The next example will define a logging service that gets added to a components injector via its `providers: []` metadata.
```typescript
// services/logger.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class LoggerService {
callStack: string[] = [];
addLog(message: string): void {
this.callStack = [message].concat(this.callStack);
this.printHead();
}
clear(): void {
this.printLog();
this.callStack = [];
console.log(DELETED LOG);
}
private printHead(): void {
console.log(this.callStack[0] || null);
}
private printLog(): void {
this.callStack.reverse().forEach((log) => console.log(message));
}
}
```
```typescript
// app.component.ts
import { Component } from '@angular/core';
import { LoggerService } from './services/logger.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
providers: [LoggerService]
})
export class AppComponent {
constructor(private logger: LoggerService) { }
logMessage(event: any, message: string): void {
event.preventDefault();
this.logger.addLog(`Message: ${message}`);
}
clearLog(): void {
this.logger.clear();
}
}
```
```html
// app.component.html
<h1>Log Example</h1>
<form (submit)="logMessage($event, userInput.value)">
<input #userInput placeholder="Type a message...">
<button type="submit">SUBMIT</button>
</form>
<h3>Delete Logged Messages</h3>
<button type="button" (click)="clearLog()">CLEAR</button>
```
Focus on the AppComponent constructor and metadata. The component injector receives instructions from the provider's metadata field containing LoggerService. The injector then knows what to instantiate LoggerService from requested in the constructor.
The constructor parameter `loggerService` has the type `LoggerService` which the injector recognizes. The injector follows through with the instantiation as mentioned.
#### Conclusion
Dependency injection (DI) is a paradigm. The way it works in Angular is through a hierarchy of injectors. A class receives its resources without having to create or know about them. Injectors receive instruction and instantiate a service depending on which one was requested.
DI shows up a lot in Angular. The official Angular documentation explains why the paradigm is so prevalent. They also go on to describe the numerous use-cases for DI in Angular way beyond what was discussed in this article. Check it out by clicking below!
## Sources
- [Angular Team. “Dependency Injection Pattern”. *Google*. Accessed 1 June 2018](https://angular.io/guide/dependency-injection-pattern)
- [Zuev, Alexey. “What you always wanted to know about Angular Dependency Injection tree”. *Angular In Depth*, 21 Mar 2018. Accessed 1 June 2018](https://blog.angularindepth.com/angular-dependency-injection-and-tree-shakeable-tokens-4588a8f70d5d)
## Resources
- [Angular Documentation](https://angular.io/guide/pipes)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Intro to Dependency Injection](https://angular.io/guide/architecture-services)
- [Advanced Dependency Injection](https://angular.io/guide/dependency-injection-pattern)

View File

@ -0,0 +1,318 @@
---
title: Directives
---
# Directives
#### Motivation
Directives are core to Angular's template HTML. Components are the most significant example. Every component view renders below a root component view. This can result in a tree of views defining a single application. A view constitutes a class (`component.ts`) and its template (`component.html`).
Other directives, while not as critical, provide much-needed flexibility. A directive positioned on an element has complete control over it. Using `<ng-template></ng-template>` allows for the dynamic creation and removal of HTML content. Microsyntax gives developers the freedom to further customize directive behavior.
#### The Directive
Directives are component elements and attributes created and recognized by Angular. Angular associates the element or attribute with its corresponding class definition. `@Directive` or `@Component` decorates these classes. Both are indicative to Angular that the class performs as a directive.
Some directives modify the style of the host element. Other directives display views or insert into existing ones as embedded views. On other words, they alter the HTML layout.
In any case, directives signal the Angular compiler. They mark components for modification depending on the class logic of the directive.
#### Component Directive
Component directives differ fundamentally from the other directive types. They are usually just referred to as components. They form their own unique HTML tag. For every component, there is some amount of template HTML. This is unlike the other two directives. Their classes are pure logic operating on what is pre-defined in the template HTML.
#### Component Creation
Create a component with `ng generate component [name-of-component]`; replace `[name-of-component]` with a preferable name. The command yields four different files that all pertain to one component.
The `component.css` and `component.spec.ts` are beyond the scope of this article. The *directive* aspect of the component involves the other two files. Take a look at the generated `component.ts` and `component.html`.
```typescript
// example.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './example.component.html'
})
export class ExampleComponent {
constructor() { }
}
```
A couple of irrelevant details were cut from the default generation of `component.ts`. That way the focus is on the component itself.
```html
<!-- example.component.html -->
<p>example works!</p>
```
Inserting ExampleComponent as the child of another component would look like the following.
```html
<!-- another.component.html -->
<h1>Welcome to AnotherComponent.</h1>
<h3>Check out ExampleComponent!</h3>
<!-- Outputs “<p>example works!</p>” -->
<app-example></app-example>
<h6>This is the end of the AnotherComponent template HTML.</h6>
```
Pay attention to `<app-example></app-example>`. The `app-example` matches up with the selector from ExampleComponent's `@Component` decorator. This is a component directive. Angular recognizes `app-example` and *directs* its rendering to the ExampleComponent class.
#### Structural Directive
Think about `if` statements, `for` loops, and `switch` statements in programming logic. These logical constructs determine code execution. Will the code execute (`if`), how many times will it execute (`for`), and which block of code executes (`switch`).
This pattern continues to structural directives. They determine the resulting HTML structure of a template. They always involve some usage of `ng-template` under the hood. `ng-template` provides a mechanism for creating conditionally rendered HTML.
Here are three examples of structural directives. Each one has a logical counterpart (`if`, `for`, and `switch`).
* *ngIf
* *ngFor
* *ngSwitchCase and *ngSwitchDefault
**Important note:** all three are available through the `CommonModule` import. It is available from `@angular/common` for importation within the application's root module.
##### *ngIf
`*ngIf` tests a given value to see if it is *truthy* or *falsy* based off general boolean evaluation in JavaScript. If truthy, the element and its innerHTML show up. Otherwise, they never render to the Domain Object Model (DOM).
```html
<!-- renders “<h1>Hello!</h1>” -->
<div *ngIf="true">
<h1>Hello!</h1>
</div>
<!-- does not render -->
<div *ngIf="false">
<h1>Hi!</h1>
</div>
```
This is a contrived example. Any member value from the template's component class can be substituted in for `true` or `false`.
NOTE: You also can do following thing with *ngIf to get access to observalbe value
```html
<div *ngIf="observable$ | async as anyNameYouWant">
{{ anyNameYouWant }}
</div>
```
##### *ngFor
`*ngFor` loops based off a right-assigned, *microsyntactic* expression. Microsyntax moves beyond the scope of this article. Know that microsyntax is a short form of logical expression. It occurs as a single string capable of referencing class member values. It can loop iterable values which makes it useful for `*ngFor`.
```html
<ul>
<li *ngFor=“let potato of [Russet, Sweet, Laura]; let i=index”>
Potato {{ i + 1 }}: {{ potato }}
</li>
<!-- Outputs
<li>
Potato 1: Russet
</li>
<li>
Potato 2: Sweet
</li>
<li>
Potato 3: Laura
</li>
-->
</ul>
```
`[Russet, Sweet, Laura]` is an iterable value. Arrays are one of the most common iterables. The `*ngFor` spits out a new `<li></li>` per array element. Each array element is assigned the variable `potato`. This is all done utilizing microsyntax. The `*ngFor` defines the structural content of the `ul` element. That is characteristic of a structural directive.
NOTE: You can also do following thing with *ngFor directive to get access to observalbe value (hacky)
```html
<div *ngFor="let anyNameYouWant of [(observable$ | async)]">
{{ anyNameYouWant }}
</div>
```
##### *ngSwitchCase and *ngSwitchDefault
These two structural directives work together to provide `switch` functionality to template HTML.
```html
<div [ngSwitch]=“potato>
<h1 *ngSwitchCase=Russet>{{ potato }} is a Russet Potato.</h1>
<h1 *ngSwitchCase=Sweet>{{ potato }} is a Sweet Potato.</h1>
<h1 *ngSwitchCase=Laura>{{ potato }} is a Laura Potato.</h1>
<h1 *ngSwitchDefault>{{ potato }} is not a Russet, Sweet, nor Laura Potato.</h1>
</div>
```
Only one of the `*ngSwitch…` expressions renders. Notice the `[ngSwitch]` attribute inside of the `div` element wrapping the switch. This passes the value of `potato` along the `*ngSwitch...` chain. This chain of structural directives determine which `h1` element renders.
As such, `[ngSwitch]` is not a structural directive unlike the `*ngSwitch…` statements. It passes the value along whereas the switch block determines the final layout of HTML.
Remember that stylization and value passing are not the responsibility of structural directives. That concerns attribute directives. Structural directives determine only the layout.
#### Structural Directive Creation[<sup>1</sup>](https://angular.io/guide/structural-directives)
There is something important to understand about the previous examples. They are all shorthand by the beginning asterisk (`*`). `ng-template` is used under the hood with each application of the asterisk.
`ng-template` defines structural directives. It explains how they can configure template HTML to produce actual HTML. Begin by creating a directive with `ng generate directive [name-of-directive]`. Replace `[name-of-directive]` with a preferable name. The command yields the following.
```typescript
import { Directive } from '@angular/core';
@Directive({
selector: '[appExample]'
})
export class ExampleDirective {
constructor() { }
}
```
This directive skeleton is pretty bare. It does not yet know whether we are building a structural or attribute directive. The `selector: [appExample]` tells Angular what attribute the directive maps to. Since you are creating a structural directive, modify the skeleton as follows.
```typescript
Import { Directive, Input, TemplateRef, ViewContainerRef } from @angular/core;
@Directive({
selector: '[appExample]'
})
export class ExampleDirective {
@Input() set appExample(booleanValue: boolean) {
if (booleanValue) {
this.ngTemplate.createEmbeddedView(this.innerHTMLOfTemplateScope);
}
else {
this.ngTemplate.clear();
}
}
constructor(
private innerHTMLOfTemplateScope:TemplateRef<any>,
private ngTemplate:ViewContainerRef
) { }
}
```
Including an arbitrary element with the `appExample` attribute serves as a good example.
```html
<div *appExample=“value”>innerHTML content</div>
<!-- This is shorthand for:
<ng-template>
<div>innerHTML content</div>
</ng-template>
-->
```
This is a lot to take in. `@Input() set ...` is a setter member declaration. It executes whenever the `appExample` attribute appears within an element and is assigned a boolean value.. The setter function receives that boolean value as its parameter for execution.
`TemplateRef<any>` references the innerHTML of `<ng-template></ng-template>`. The asterisk used in prior examples is shorthand for the comment in the above code block. `ng-template` acts as the *secret sauce* to it structural directives.
`ViewContainerRef` references the encapsulating scope of `<ng-template></ng-template>`. `ng-template` is not an actual element. It is a marker to the Angular compiler that eventually gets commented out.
`ViewContainerRef` has two methods: `clear()` and `createEmbeddedView()`. You can think of embedded views as the HTML scoped within an `ng-template` element.
`clear()` removes any existing HTML scoped within `ng-template` from the HTML display. `createEmbeddedView()` targets the HTML within `ng-template` as displayable HTML.
If understand the latest code example, then you have a solid grasp `*ngIf`, `*ngFor`, `*ngSwitchCase`, and `*ngSwitchDefault`. They all determine the layout with reference to the `TemplateRef<any>` and `ViewContainerRef`.
In fact, the ExampleDirective above mimics the functionality of `*ngIf`!
```html
<!-- renders “<h1>Hello!</h1>” -->
<div *ngExample="true">
<h1>Hello!</h1>
</div>
<!-- does not render -->
<div *appExample="false">
<h1>Hi!</h1>
</div>
```
Never forget the asterisk (`*`). It is shorthand for the `ng-template` element that our directive class references.
#### Attribute Directive
Attribute directives are similar to structural. Except, attribute directives have zero effect on the HTML layout. They do not implement `<ng-template></ng-template>`. They are attributes that reference their host element for stylistic changes.
An example best explains their purpose.
#### Attribute Directive Creation[<sup>2</sup>](https://angular.io/guide/attribute-directives)
Generate another directive: `ng generate directive [name-of-directive]`. Replace `[name-of-directive]` with a preferable name.
```typescript
import { Directive } from '@angular/core';
@Directive({
selector: '[appExample]'
})
export class ExampleDirective {
constructor() { }
}
```
Attribute and structural directives both begin with the same skeleton. A few more additions will distinguish the attribute directive.
```typescript
import { Directive, Input, ElementRef } from '@angular/core';
@Directive({
selector: '[appExample]'
})
export class ExampleDirective {
@Input() set appExample(color:string) {
this.host.nativeElement.style.color = color;
}
constructor(private host:ElementRef) { }
}
```
A few elements to test with will help.
```html
<!-- the intended results are self-explanatory -->
<div appExample=“purple”>This text is purple!</div>
<div appExample=“blue”>This text is blue!</div>
<div appExample=“red”>This text is red!</div>
```
`ElementRef` provides a direct reference to host element. `ElementRef.nativeElement` grabs the DOM node. With the node, styling the component is as simple as `this.host.nativeElement.style.color = color`.
`@Input() set ...` is another setter function that reads the value it is assigned upon its implementation as an attribute. It reassigns the color property of each elements stylesheet.
#### Conclusion
Directives are a powerful tool available in Angulars template HTML. They are how components connect across each other. Within each component they provide a means of style and layout.
There are many other options for building out each type of directive. Unfortunately, covering each one is too much for one article. Having a basic understanding of directives is enough to move forward with more advanced resources.
Check out the below resources to dive deeper. There are links for each type of directive. Each link is a part of the same documentation, so no need to return here after visiting the first link!
## Sources
1. [Angular Team. *Structural Directives*. Google. Accessed 28 May 2018](https://angular.io/guide/structural-directives)
2. [Angular Team. *Attribute Directives*. Google. Accessed 28 May 2018](https://angular.io/guide/attribute-directives)
## Resources
- [Angular Documentation](https://angular.io/guide/pipes)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Angular Components](https://angular.io/guide/architecture-components)
- [Angular Structural Directives](https://angular.io/guide/structural-directives)
- [Angular Attribute Directives](https://angular.io/guide/attribute-directives)
- [Angular CLI](https://cli.angular.io)

View File

@ -0,0 +1,58 @@
---
title: Angular
---
## Angular
AngularJS (versions 1.x) is a JavaScript based open source Framework. It is cross platform and used to develop Single Page Web Application (SPWA). AngularJS implements the MVC pattern to separate the logic , presentation and data components. It also uses dependency injection to make use of server-side services in client side applications.
Angular(versions 2.x and up) is a Typescript based open source framework to develop front-end Web application. Angular has following features like generics, static-typing and also some ES6 features.
## Version History
Google released the initial version of AngularJS on October 20,2010. Stable release of AngularJS was on December 18, 2017 of version 1.6.8. Angular 2.0 release took place on Sep-22 2014 at ng-Europe conference. One of the feature of Angular 2.0 is dynamic loading.
After some modifications, Angular 4.0 was released on Dec-2016. Angular 4 is backward compatible with Angular 2.0. HttpClient library is one of the feature of Angular 4.0. Angular 5 release was on November 1, 2017. Support for Progressive web apps was one of the improvement in the Angular 4.0. Angular 6 release was in May 2018. The latest stable version is [6.1.9](https://blog.angular.io/angular-v6-1-now-available-typescript-2-9-scroll-positioning-and-more-9f1c03007bb6)
**Install**:
We can add Angular either by referencing the sources available or downloading the framework.
**Link To Source**:
AngularJS: We can add AngularJS(Angular 1.x versions) by referencing the Content Delivery Network from Google.
```html
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
```
Download/install: We can download the framework with npm, Bower or composer
**Angular 1.x**:
npm
```shell
npm install angular
```
Then add a `<script>` to your `index.html`:
```html
<script src="/node_modules/angular/angular.js"></script>
```
bower
```shell
bower install angular
```
Then add a `<script>` to your `index.html`:
```html
<script src="/bower_components/angular/angular.js"></script>
```
For more information regarding the documentation, refer to the official site of [AngularJS](https://docs.angularjs.org/api)
You can install **Angular 2.x** and other versions by following the steps from the official documentation of [Angular](https://angular.io/guide/quickstart)
*Note : Please refer the Angular documentation for the updated information.*

View File

@ -0,0 +1,455 @@
---
title: Lifecycle Hooks
---
# Lifecycle Hooks
#### Motivation
Modern front-end frameworks move the application from state to state. Data fuels these updates. These technologies interact with the data which in turn transitions the state. With every state change, there many specific moments where certain assets become available.
At one instance the template might be ready, in another data will have finished uploading. Coding for each instance requires a means of detection. Lifecycle hooks answer this need. Modern front-end frameworks package themselves with a variety of lifecycle hooks. Angular is no exception
#### Lifecycle Hooks Explained
Lifecycle hooks are timed methods. They differ in when and why they execute. Change detection triggers these methods. They execute depending on the conditions of the current cycle. Angular runs change detection constantly on its data. Lifecycle hooks help manage its effects.
An important aspect of these hooks is their order of execution. It never deviates. They execute based off a predictable series of load events produced from a detection cycle. This makes them predictable. Some assets are only available after a certain hook executes. Of course, a hook only execute under certain conditions set in the current change detection cycle.
This article presents the lifecycle hooks in order of their execution (if they all execute). Certain conditions merit a hook's activation. There are a few who only execute once after component initialization.
All lifecycle methods are available from `@angular/core`. Although not required, Angular [recommends implementing every hook](https://angular.io/guide/lifecycle-hooks#interfaces-are-optional-technically). This practice leads to better error messages regarding the component.
### In Order of their Execution…
#### ngOnChanges
`ngOnChanges` triggers following the modification of `@Input` bound class members. Data bound by the `@Input()` decorator come from an external source. When the external source alters that data in a detectable manner, it passes through the `@Input` property again.
With this update, `ngOnChanges` immediately fires. It also fires upon initialization of input data. The hook receives one optional parameter of type `SimpleChanges`. This value contains information on the changed input-bound properties.
```typescript
import { Component, Input, OnChanges } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<h3>Child Component</h3>
<p>TICKS: {{ lifecycleTicks }}</p>
<p>DATA: {{ data }}</p>
`
})
export class ChildComponent implements OnChanges {
@Input() data: string;
lifecycleTicks: number = 0;
ngOnChanges() {
this.lifecycleTicks++;
}
}
@Component({
selector: 'app-parent',
template: `
<h1>ngOnChanges Example</h1>
<app-child [data]="arbitraryData"></app-child>
`
})
export class ParentComponent {
arbitraryData: string = 'initial';
constructor() {
setTimeout(() => {
this.arbitraryData = 'final';
}, 5000);
}
}
```
**Summary:** ParentComponent binds input data to the ChildComponent. The component receives this data through its `@Input` property. `ngOnChanges` fires. After five seconds, the `setTimeout` callback triggers. ParentComponent mutates the data source of ChildComponent's input-bound property. The new data flows through the input property. `ngOnChanges` fires yet again.
#### ngOnInit
`ngOnInit` fires once upon initialization of a components input-bound (`@Input`) properties. The next example will look similar to the last one. The hook does not fire as ChildComponent receives the input data. Rather, it fires right after the data renders to the ChildComponent template.
```typescript
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<h3>Child Component</h3>
<p>TICKS: {{ lifecycleTicks }}</p>
<p>DATA: {{ data }}</p>
`
})
export class ChildComponent implements OnInit {
@Input() data: string;
lifecycleTicks: number = 0;
ngOnInit() {
this.lifecycleTicks++;
}
}
@Component({
selector: 'app-parent',
template: `
<h1>ngOnInit Example</h1>
<app-child [data]="arbitraryData"></app-child>
`
})
export class ParentComponent {
arbitraryData: string = 'initial';
constructor() {
setTimeout(() => {
this.arbitraryData = 'final';
}, 5000);
}
}
```
**Summary:** ParentComponent binds input data to the ChildComponent. ChildComponent receives this data through its `@Input` property. The data renders to the template. `ngOnInit` fires. After five seconds, the `setTimeout` callback triggers. ParentComponent mutates the data source of ChildComponent's input-bound property. ngOnInit **DOES NOT FIRE**.
`ngOnInit` is a one-and-done hook. Initialization is its only concern.
#### ngDoCheck
`ngDoCheck` fires with every change detection cycle. Angular runs change detection frequently. Performing any action will cause it to cycle. `ngDoCheck` fires with these cycles. Use it with caution. It can create performance issues when implemented incorrectly.
`ngDoCheck` lets developers check their data manually. They can trigger a new application date conditionally. In conjunction with `ChangeDetectorRef`, developers can create their own checks for change detection.
```typescript
import { Component, DoCheck, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-example',
template: `
<h1>ngDoCheck Example</h1>
<p>DATA: {{ data[data.length - 1] }}</p>
`
})
export class ExampleComponent implements DoCheck {
lifecycleTicks: number = 0;
oldTheData: string;
data: string[] = ['initial'];
constructor(private changeDetector: ChangeDetectorRef) {
this.changeDetector.detach(); // lets the class perform its own change detection
setTimeout(() => {
this.oldTheData = 'final'; // intentional error
this.data.push('intermediate');
}, 3000);
setTimeout(() => {
this.data.push('final');
this.changeDetector.markForCheck();
}, 6000);
}
ngDoCheck() {
console.log(++this.lifecycleTicks);
if (this.data[this.data.length - 1] !== this.oldTheData) {
this.changeDetector.detectChanges();
}
}
}
```
Pay attention to the console versus the display. The data progress up to intermediate before freezing. Three rounds of change detection occur over this period as indicated in the console. One more round of change detection occurs as final gets pushed to the end of `this.data`. One last round of change detection then occurs. The evaluation of the if statement determines no updates to the view are necessary.
**Summary:** Class instantiates after two rounds of change detection. Class constructor initiates `setTimeout` twice. After three seconds, the first `setTimeout` triggers change detection. `ngDoCheck` marks the display for an update. Three seconds later, the second `setTimeout` triggers change detection. No view updates needed according to the evaluation of `ngDoCheck`.
##### Warning
Before proceeding, learn the difference between the content DOM and view DOM (DOM stands for Document Object Model).
The content DOM defines the innerHTML of directive elements. Conversely, the view DOM is a components template excluding any template HTML nested within a directive. For a better understanding, refer to [this blog post](http://blog.mgechev.com/2016/01/23/angular2-viewchildren-contentchildren-difference-viewproviders).
#### ngAfterContentInit
`ngAfterContentInit` fires after the component's content DOM initializes (loads for the first time). Waiting on `@ContentChild(ren)` queries is the hook's primary use-case.
`@ContentChild(ren)` queries yield element references for the content DOM. As such, they are not available until after the content DOM loads. Hence why `ngAfterContentInit` and its counterpart `ngAfterContentChecked` are used.
```typescript
import { Component, ContentChild, AfterContentInit, ElementRef, Renderer2 } from '@angular/core';
@Component({
selector: 'app-c',
template: `
<p>I am C.</p>
<p>Hello World!</p>
`
})
export class CComponent { }
@Component({
selector: 'app-b',
template: `
<p>I am B.</p>
<ng-content></ng-content>
`
})
export class BComponent implements AfterContentInit {
@ContentChild("BHeader", { read: ElementRef }) hRef: ElementRef;
@ContentChild(CComponent, { read: ElementRef }) cRef: ElementRef;
constructor(private renderer: Renderer2) { }
ngAfterContentInit() {
this.renderer.setStyle(this.hRef.nativeElement, 'background-color', 'yellow')
this.renderer.setStyle(this.cRef.nativeElement.children.item(0), 'background-color', 'pink');
this.renderer.setStyle(this.cRef.nativeElement.children.item(1), 'background-color', 'red');
}
}
@Component({
selector: 'app-a',
template: `
<h1>ngAfterContentInit Example</h1>
<p>I am A.</p>
<app-b>
<h3 #BHeader>BComponent Content DOM</h3>
<app-c></app-c>
</app-b>
`
})
export class AComponent { }
```
The `@ContentChild` query results are available from `ngAfterContentInit`. `Renderer2` updates the content DOM of BComponent containing a `h3` tag and CComponent. This is a common example of [content projection](https://alligator.io/angular/content-projection-angular).
**Summary:** Rendering starts with AComponent. For it to finish, AComponent must render BComponent. BComponent projects content nested in its element through the `<ng-content></ng-content>` element. CComponent is part of the projected content. The projected content finishes rendering. `ngAfterContentInit` fires. BComponent finishes rendering. AComponent finishes rendering. `ngAfterContentInit` will not fire again.
#### ngAfterContentChecked
`ngAfterContentChecked` fires after every cycle of change detection targeting the content DOM. This lets developers facilitate how the content DOM reacts to change detection. `ngAfterContentChecked` can fire frequently and cause performance issues if poorly implemented.
`ngAfterContentChecked` fires during a components initialization stages too. It comes right after `ngAfterContentInit`.
```typescript
import { Component, ContentChild, AfterContentChecked, ElementRef, Renderer2 } from '@angular/core';
@Component({
selector: 'app-c',
template: `
<p>I am C.</p>
<p>Hello World!</p>
`
})
export class CComponent { }
@Component({
selector: 'app-b',
template: `
<p>I am B.</p>
<button (click)="$event">CLICK</button>
<ng-content></ng-content>
`
})
export class BComponent implements AfterContentChecked {
@ContentChild("BHeader", { read: ElementRef }) hRef: ElementRef;
@ContentChild(CComponent, { read: ElementRef }) cRef: ElementRef;
constructor(private renderer: Renderer2) { }
randomRGB(): string {
return `rgb(${Math.floor(Math.random() * 256)},
${Math.floor(Math.random() * 256)},
${Math.floor(Math.random() * 256)})`;
}
ngAfterContentChecked() {
this.renderer.setStyle(this.hRef.nativeElement, 'background-color', this.randomRGB());
this.renderer.setStyle(this.cRef.nativeElement.children.item(0), 'background-color', this.randomRGB());
this.renderer.setStyle(this.cRef.nativeElement.children.item(1), 'background-color', this.randomRGB());
}
}
@Component({
selector: 'app-a',
template: `
<h1>ngAfterContentChecked Example</h1>
<p>I am A.</p>
<app-b>
<h3 #BHeader>BComponent Content DOM</h3>
<app-c></app-c>
</app-b>
`
})
export class AComponent { }
```
This hardly differs from `ngAfterContentInit`. A mere `<button></button>` was added to BComponent. Clicking it causes a change detection loop. This activates the hook as indicated by the randomization of `background-color`.
**Summary:** Rendering starts with AComponent. For it to finish, AComponent must render BComponent. BComponent projects content nested in its element through the `<ng-content></ng-content>` element. CComponent is part of the projected content. The projected content finishes rendering. `ngAfterContentChecked` fires. BComponent finishes rendering. AComponent finishes rendering. `ngAfterContentChecked` may fire again through change detection.
#### ngAfterViewInit
`ngAfterViewInit` fires once after the view DOM finishes initializing. The view always loads right after the content. `ngAfterViewInit` waits on `@ViewChild(ren)` queries to resolve. These elements are queried from within the same view of the component.
In the example below, BComponents `h3` header is queried. `ngAfterViewInit` executes as soon as the query's results are available.
```typescript
import { Component, ViewChild, AfterViewInit, ElementRef, Renderer2 } from '@angular/core';
@Component({
selector: 'app-c',
template: `
<p>I am C.</p>
<p>Hello World!</p>
`
})
export class CComponent { }
@Component({
selector: 'app-b',
template: `
<p #BStatement>I am B.</p>
<ng-content></ng-content>
`
})
export class BComponent implements AfterViewInit {
@ViewChild("BStatement", { read: ElementRef }) pStmt: ElementRef;
constructor(private renderer: Renderer2) { }
ngAfterViewInit() {
this.renderer.setStyle(this.pStmt.nativeElement, 'background-color', 'yellow');
}
}
@Component({
selector: 'app-a',
template: `
<h1>ngAfterViewInit Example</h1>
<p>I am A.</p>
<app-b>
<h3>BComponent Content DOM</h3>
<app-c></app-c>
</app-b>
`
})
export class AComponent { }
```
`Renderer2` changes the background color of BComponent's header. This indicates the view element was successfully queried thanks to `ngAfterViewInit`.
**Summary:** Rendering starts with AComponent. For it to finish, AComponent must render BComponent. BComponent projects content nested in its element through the `<ng-content></ng-content>` element. CComponent is part of the projected content. The projected content finishes rendering. BComponent finishes rendering. `ngAfterViewInit` fires. AComponent finishes rendering. `ngAfterViewInit` will not fire again.
#### ngAfterViewChecked
`ngAfterViewChecked` fires after any change detection cycle targeting the components view. The `ngAfterViewChecked` hook lets developers facilitate how change detection affects the view DOM.
```typescript
import { Component, ViewChild, AfterViewChecked, ElementRef, Renderer2 } from '@angular/core';
@Component({
selector: 'app-c',
template: `
<p>I am C.</p>
<p>Hello World!</p>
`
})
export class CComponent { }
@Component({
selector: 'app-b',
template: `
<p #BStatement>I am B.</p>
<button (click)="$event">CLICK</button>
<ng-content></ng-content>
`
})
export class BComponent implements AfterViewChecked {
@ViewChild("BStatement", { read: ElementRef }) pStmt: ElementRef;
constructor(private renderer: Renderer2) { }
randomRGB(): string {
return `rgb(${Math.floor(Math.random() * 256)},
${Math.floor(Math.random() * 256)},
${Math.floor(Math.random() * 256)})`;
}
ngAfterViewChecked() {
this.renderer.setStyle(this.pStmt.nativeElement, 'background-color', this.randomRGB());
}
}
@Component({
selector: 'app-a',
template: `
<h1>ngAfterViewChecked Example</h1>
<p>I am A.</p>
<app-b>
<h3>BComponent Content DOM</h3>
<app-c></app-c>
</app-b>
`
})
export class AComponent { }
```
**Summary:** Rendering starts with AComponent. For it to finish, AComponent must render BComponent. BComponent projects content nested in its element through the `<ng-content></ng-content>` element. CComponent is part of the projected content. The projected content finishes rendering. BComponent finishes rendering. `ngAfterViewChecked` fires. AComponent finishes rendering. `ngAfterViewChecked` may fire again through change detection.
Clicking the `<button></button>` element initiates a round of change detection. `ngAfterContentChecked` fires and randomizes the `background-color` of the queried elements each button click.
#### ngOnDestroy
`ngOnDestroy` fires upon a components removal from the view and subsequent DOM. This hook provides a chance to clean up any loose ends before a component's deletion.
```typescript
import { Directive, Component, OnDestroy } from '@angular/core';
@Directive({
selector: '[appDestroyListener]'
})
export class DestroyListenerDirective implements OnDestroy {
ngOnDestroy() {
console.log("Goodbye World!");
}
}
@Component({
selector: 'app-example',
template: `
<h1>ngOnDestroy Example</h1>
<button (click)="toggleDestroy()">TOGGLE DESTROY</button>
<p appDestroyListener *ngIf="destroy">I can be destroyed!</p>
`
})
export class ExampleComponent {
destroy: boolean = true;
toggleDestroy() {
this.destroy = !this.destroy;
}
}
```
**Summary:** The button is clicked. ExampleComponent's `destroy` member toggles false. The structural directive `*ngIf` evaluates to false. `ngOnDestroy` fires. `*ngIf` removes its host `<p></p>`. This process repeats any number of times clicking the button to toggle `destroy` to false.
#### Conclusion
Remember that certain conditions must be met for each hook. They will always execute in order of each other regardless. This makes hooks predictable enough to work with even if some do not execute.
With lifecycle hooks, timing the execution of a class is easy. They let developers track where change detection is occurring and how the application should react. They stall for code that requires load-based dependencies available only after sometime.
The component lifecycle characterizes modern front end frameworks. Angular lays out its lifecycle by providing the aforementioned hooks.
## Sources
- [Angular Team. “Lifecycle Hooks”. *Google*. Accessed 2 June 2018](https://angular.io/guide/lifecycle-hooks)
- [Gechev, Minko. “ViewChildren and ContentChildren in Angular”. Accessed 2 June 2018](http://blog.mgechev.com/2016/01/23/angular2-viewchildren-contentchildren-difference-viewproviders)
## Resources
- [Angular Documentation](https://angular.io/docs)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Lifecycle Hooks in Depth](https://angular.io/guide/lifecycle-hooks)

View File

@ -0,0 +1,370 @@
---
title: NgModules
---
# NgModules
#### Motivation
Angular applications begin from the root NgModule. Angular manages an applications dependencies through its module system comprised of NgModules. Alongside plain JavaScript modules, NgModules ensure code modularity and encapsulation.
Modules also provide a top-most level of organizing code. Each NgModule sections off its own chunk of code as the root. This module provides top-to-bottom encapsulation for its code. The entire block of code can then export to any other module. In this sense, NgModules act like gatekeepers to their own code blocks.
Angular's documented utilities come from NgModules authored by Angular. No utility is available unless the NgModule that declares it gets included into the root. These utilities must also export from their host module so that importers can use them. This form of encapsulation empowers the developer to produce his or her own NgModules within the same file-system.
Plus, it makes sense to know why the Angular CLI (command-line interface) imports `BrowserModule` from `@angular/core`. This happens whenever a new app generates using the CLI command: `ng new [name-of-app]`.
Understanding the point of the implementation may suffice in most cases. However, understanding how the implementation wires itself to the root is even better. It all happens automatically by importing `BrowserModule` into the root.
#### NgModule Decorator
Angular defines its modules by decorating a generic class. The `@NgModule` decorator indicates the class modular purpose to Angular. An NgModule class consolidates root dependencies accessible/instantiable from the module's scope. 'Scope' meaning anything originating from the modules metadata.
```typescript
import { NgModule } from '@angular/core';
@NgModule({
// … metadata …
})
export class AppModule { }
```
#### NgModule Metadata
The CLI generated root NgModule includes the following metadata fields. These fields provide configuration to the code block upon which the NgModule presides.
* `declarations: []`
* `imports: []`
* `providers: []`
* `bootstrap: []`
##### Declarations
The declarations array includes all components, directives, or pipes hosted by an NgModule. They are private to the module unless explicitly exported inside its metadata. Given this use-case, components, directives, and pipes are nicknamed declarables. An NgModule must declare a declarable uniquely. The declarable cannot declare twice in separate NgModules. An error gets thrown otherwise. See the below example.
```typescript
import { NgModule } from '@angular/core';
import { TwoComponent } from './components/two.component.ts';
@NgModule({
declarations: [ TwoComponent ]
})
export class TwoModule { }
@NgModule({
imports: [ TwoModule ],
declarations: [ TwoComponent ]
})
export class OneModule { }
```
Angular throws an error for the sake of NgModule encapsulation. Declarables are private to the NgModule that declares them by default. If multiple NgModules need a certain declarable, they should import the declaring NgModule. This NgModule must then export the desired declarable so that the other NgModules can use it.
```typescript
import { NgModule } from '@angular/core';
import { TwoComponent } from './components/two.component.ts';
@NgModule({
declarations: [ TwoComponent ],
exports: [ TwoComponent ]
})
export class TwoModule { }
@NgModule({
imports: [ TwoModule ] // this module can now use TwoComponent
})
export class OneModule { }
```
The above example will not throw an error. TwoComponent has been uniquely declared between the two NgModules. OneModule also has access to TwoComponent since it imports TwoModule. TwoModule in turn exports the TwoComponent for external use.
##### Imports
The imports array only accepts NgModules. This array does not accept declarables, services, or anything else besides other NgModules. Importing a module provides access to what declarable the module publicizes.
This explains why importing `BrowserModule` provides access to its various utilities. Each declarable utility declared in `BrowserModule` exports from its metadata. Upon importing `BrowserModule`, those exported declarables become available to the importing NgModule. Services do not export at all since they lack the same encapsulation.
##### Providers
The lack of service encapsulation might seem odd given the encapsulation of declarables. Remember that services go into the providers array separate from declarations or exports.
When Angular compiles, it flattens the root NgModule and its imports into one module. Services group together in a single providers array hosted by the merged NgModule. Declarables maintain their encapsulation through a set of compile-time flags.
If NgModule providers contain matching token values, the importing root module takes precedence. Past that, the last NgModule imported takes precedence. See the next example. Pay special attention to the NgModule importing the other two. Recognize how that affects the precedence of the provided service.
```typescript
import { NgModule } from '@angular/core';
@NgModule({
providers: [ AwesomeService ], // 1st precedence + importing module
imports: [
BModule,
CModule
]
})
export class AModule { }
@NgModule({
providers: [ AwesomeService ] // 3rd precedence + first import
})
export class BModule { }
@NgModule({
providers: [ AwesomeService ] // 2nd precedence + last import
})
export class CModule { }
```
Instantiating AwesomeService from within AModule's scope results in an AwesomeService instance as provided in AModules metadata. If AModule's providers omitted this service, the AwesomeService of CModule would take precedence. So and so forth for BModule if CModules providers omitted AwesomeService.
##### Bootstrap
The bootstrap array accepts components. For each component of the Array, Angular inserts the component as its own root of the `index.html` file. The CLI-generated root NgModule of an application will always have this field.
```typescript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [ AppComponent ],
imports: [ BrowserModule ],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule { }
```
AppComponents element will inject into the base-level HTML of the app (`index.html`). The rest of the component tree unfolds from there. The scope of the overarching NgModule covers this entire tree plus any others injected from the bootstrap array. The array usually contains only one element. This one component represents the module as a single element and its underlying tree.
#### NgModules vs JavaScript Modules
You have seen Angular and JavaScript modules working together in the previous examples. The top-most `import..from` statements constitute the JavaScript module system. The file locations of each statement's target must export a class, variable, or function matching the request. `import { TARGET } from './path/to/exported/target'`.
In JavaScript, modules are file-separated. Files import using the `import..from` keywords as just mentioned. NgModules, on the other hand, are class-separated and decorated with `@NgModule`. And so, many Angular modules can exist in a single file. This cannot happen with JavaScript since a file defines a module.
Granted, conventions say that each `@NgModule` decorated class should have its own file. Even so, know that files do not constitute their own modules in Angular. Classes decorated with `@NgModule` create that distinction.
JavaScript modules provide token references to `@NgModule` metadata. This happens at the top of a file hosting a NgModule class. NgModule uses these tokens inside of its metadata fields (declarables, imports, providers, etc). The only reason `@NgModule` can decorate a class in the first place is because JavaScript imports it from the top of the file.
```typescript
// JavaScript module system provides tokens
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppService } from './app.service';
// Javascript module system is strict about where it imports. It can only import at the top of files.
// Angular NgModule uses those tokens in its metadata settings
@NgModule({ // import { NgModule } from '@angular/core';
declarations: [
AppComponent // import { AppComponent } from './app.component';
],
imports: [
BrowserModule // import { BrowserModule } from '@angular/platform-browser';
],
providers: [
AppService // import { AppService } from './app.service';
],
bootstrap: [
AppComponent // import { AppComponent } from './app.component';
]
})
export class AppModule { }
// JavaScript module system exports the class. Other modules can now import AppModule.
```
The above example does not introduce anything new. The focus here is on the comments explaining how the two modular systems work together. JavaScript provides token references while NgModule uses those token to encapsulate and configure its underlying block of code.
#### Feature Modules
Applications grow overtime. Scaling them properly requires application organization. A solid system for this will make further development much easier.
In Angular, schematics ensure purpose-driven sections of code remain distinguishable. Beyond the sub-NgModule schematics, there are the NgModules themselves. They are a type of schematic too. They stand above the rest in the list of schematics excluding the application itself.
The root module should not stand alone once an application starts to scale. Feature modules include any NgModule used alongside the root NgModule. You can think of the root module as having the `bootstrap: []` metadata field. Feature application ensure the root module does not oversaturate its metadata.
Feature modules isolate a section of code on behalf of any importing module. They can handle whole application sections independently. This means it could be used in any application whose root module imports the feature module. This tactic saves developers time and effort over the course of multiple applications! It keeps the application's root NgModule lean as well.
In the root NgModule of an app, adding a feature modules token into the root's `imports` array does the trick. Whatever the feature module exports or provides becomes available to the root.
```typescript
// ./awesome.module.ts
import { NgModule } from '@angular/core';
import { AwesomePipe } from './awesome/pipes/awesome.pipe';
import { AwesomeComponent } from './awesome/components/awesome.component';
import { AwesomeDirective } from './awesome/directives/awesome.directive';
@NgModule({
exports: [
AwesomePipe,
AwesomeComponent,
AwesomeDirective
]
declarations: [
AwesomePipe,
AwesomeComponent,
AwesomeDirective
]
})
export class AwesomeModule { }
```
```typescript
// ./app.module.ts
import { AwesomeModule } from './awesome.module';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
AwesomeModule,
BrowserModule
],
providers: [],
bootstrap: [
AppComponent
]
})
export class AppModule { }
```
```typescript
// ./app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<!-- AwesomeDirective -->
<h1 appAwesome>This element mutates as per the directive logic of appAwesome.</h1>
<!-- AwesomePipe -->
<p>Generic output: {{ componentData | awesome }}</p>
<section>
<!-- AwesomeComponent -->
<app-awesome></app-awesome>
</section>
`
})
export class AppComponent {
componentData: string = "Lots of transformable data!";
}
```
`<app-awesome></app-awesome>` (component), `awesome` (pipe), and `appAwesome` (directive) are exclusive to AwesomeModule. Had it not exported these declarables or AppModule neglected to add AwesomeModule to its imports, then AwesomeModule's declarables would not have been usable by AppComponents template. AwesomeModule is a feature module to the root NgModule AppModule.
Angular provides some its own modules that supplement the root upon their importation. This is due to these feature modules exporting what they create.
#### Static module methods
Sometimes modules provide the option to be configured with a custom config object. This is achieved by leveraging static methods inside the module class.
An example of this approach is the `RoutingModule` which provides a `.forRoot(...)` method directly on the module.
To define your own static module method you add it to the module class using the `static` keyword. The return type has to be `ModuleWithProviders`.
```ts
// configureable.module.ts
import { AwesomeModule } from './awesome.module';
import { ConfigureableService, CUSTOM_CONFIG_TOKEN, Config } from './configurable.service';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
@NgModule({
imports: [
AwesomeModule,
BrowserModule
],
providers: [
ConfigureableService
]
})
export class ConfigureableModule {
static forRoot(config: Config): ModuleWithProviders {
return {
ngModule: ConfigureableModule,
providers: [
ConfigureableService,
{
provide: CUSTOM_CONFIG_TOKEN,
useValue: config
}
]
};
}
}
```
```ts
// configureable.service.ts
import { Inject, Injectable, InjectionToken } from '@angular/core';
export const CUSTOM_CONFIG_TOKEN: InjectionToken<string> = new InjectionToken('customConfig');
export interface Config {
url: string
}
@Injectable()
export class ConfigureableService {
constructor(
@Inject(CUSTOM_CONFIG_TOKEN) private config: Config
)
}
```
Notice that the object the `forRoot(...)` method returns is almost identical to the `NgModule` config.
The `forRoot(...)` method accepts a custom config object that the user can provide when importing the module.
```ts
imports: [
...
ConfigureableModule.forRoot({ url: 'http://localhost' }),
...
]
```
The config is then provided using a custom `InjectionToken` called `CUSTOM_CONFIG_TOKEN` and injected in the `ConfigureableService`. The `ConfigureableModule` should be imported only once using the `forRoot(...)` method. This provides the `CUSTOM_CONFIG_TOKEN` with the custom config. All other modules should import the `ConfigureableModule` without the `forRoot(...)` method.
#### NgModule Examples from Angular
Angular provides a variety of modules importable from `@angular`. Two of the most commonly imported modules are `CommonModule` and `HttpClientModule`.
`CommonModule` is actually a subset of `BrowserModule`. Both provide access to the `*ngIf` and `*ngFor` structural directives. `BrowserModule` includes a platform-specific installation for the web browser. `CommonModule` omits this installation. The `BrowserModule` should import into the root NgModule of a web application. `CommonModule` provides `*ngIf` and `*ngFor` to feature modules not requiring a platform installation.
`HttpClientModule` provides the `HttpClient` service. Remember that services go in the providers array of the `@NgModule` metadata. They are not declarable. During compilation, every NgModule gets consolidated into one single module. Services are not encapsulated unlike declarables. They are all instantiable through the root injector located alongside the merged NgModule.
Back to the point. Like any other service, `HttpClient` instantiates into a class through its constructor via dependency injection (DI). Using DI, the root injector injects an instance of `HttpClient` into the constructor. This service lets developers make HTTP requests with the service's implementation.
The `HttpClient` implementation includes into the `HttpClientModule` providers array. As long as the root NgModule imports `HttpClientModule`, `HttpClient` will instantiate from inside the root's scope as expected.
#### Conclusion
Chances are you may have already taken advantage of Angulars NgModules. Angular makes it very easy to throw a module into the root NgModules imports array. Utilities are often exported from the imported module's metadata. Hence why its utilities suddenly become available upon importation within the root NgModule.
NgModules work closely with plain JavaScript modules. One provides token while one uses them for configuration. Their teamwork results in a robust, modular system unique to the Angular framework. It provides a new layer of organization above all other schematics excluding the application.
Hopefully this article furthers your understanding of NgModules. Angular can leverage this system even further for some of the more exotic use-cases. This article covers the basics so that you can learn more using the below links.
## Sources
- [Angular Team. “NgModules”. *Google*. Accessed 6 June 2018.](https://angular.io/guide/ngmodules)
- [Koretskyi, Maxim. “Avoiding common confusions with modules in Angular”. *Angular In Depth*, 10 Aug. 2017. Accessed 6 June 2018.](https://blog.angularindepth.com/avoiding-common-confusions-with-modules-in-angular-ada070e6891f)
## Resources
- [Angular Documentation](https://angular.io/guide)
- [Angular In Depth](https://blog.angularindepth.com)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Angular CLI](https://cli.angular.io)

View File

@ -0,0 +1,161 @@
---
title: Pipes
---
# Pipes
#### Motivation
Output data transformations. They ensure data is in a desirable format by the time it loads onto the users screen. Normally data transforms behind the scenes. With pipes, transforming data can take place in the template HTML. Pipes transform template data directly.
Pipes look nice and are convenient. They help keep the components class lean of basic transformations. To put it technically, pipes encapsulate data transformation logic.
#### Output Transformation
As mentioned in the prior section, pipes transform data inline. The syntax of pipes correlate shell scripting. In many scripts, the output of one part of the command gets *piped* as output into the next part as input. That same trend characterizes Angular pipes.
In Angular, there exists many ways to interact with data in the template HTML. Pipes can apply anywhere data gets parsed into the template HTML. They can occur within microsyntax logic and innerHTML variable interpolations. Pipes account for all transformations without adding onto the component class.
Pipes are also *chainable*. You can integrate pipes one after the other to perform increasingly complex transformations. As specialized data transformers, pipes are hardly trivial.
#### Use Cases
Angular comes prepackaged with a basic set of pipes. Working with a couple of them will develop the intuition to handle the rest. The following list provides two examples.
* AsyncPipe
* DatePipe
These two perform simple tasks. Their simplicity is massively beneficial.
##### AsyncPipe
This sections requires a basic understanding of Promises or Observables to fully appreciate. The AsyncPipe operates on either of the two. AsyncPipe extracts data from Promises/Observables as output for whatever comes next.
In the case of Obervables, AsyncPipe subscribes automatically to the data source. Regardless of where the data comes from, the AsyncPipe subscribes to the source observable. `async` is the syntactical name of AsyncPipe as shown below.
```html
<ul *ngFor=“let potato of (potatoSack$ | async); let i=index”>
<li>Potatoe {{i + 1}}: {{potato}}</li>
</ul>
```
In the example, `potatoSack$` is an Observable pending an upload of potatoes. Once the potatoes arrive, either synchronously or asynchronously, the AsyncPipe receives them as an *iterable* array. The list element then fills up with potatoes.
##### DatePipe
Formatting date strings takes a fair bit of hacking with the JavaScript `Date` object. The DatePipe provides a powerful way to format dates assuming the given input is a valid time format.
```typescript
// example.component.ts
@Component({
templateUrl: './example.component.html'
})
export class ExampleComponent {
timestamp:string = 2018-05-24T19:38:11.103Z;
}
```
```html
<!-- example.component.html -->
<div>Current Time: {{timestamp | date:short}}</div>
```
The format of the above `timestamp` is [ISO 8601<sup>1</sup>](https://en.wikipedia.org/wiki/ISO_8601)—not the easiest to read. The DatePipe (`date`) transforms the ISO date format into a more conventional `mm/dd/yy, hh:mm AM|PM`. There are many other formatting options. All these options are in the [official documentation](https://angular.io/api/common/DatePipe).
#### Creating Pipes
While Angular only has a set number of pipes, the `@Pipe` decorator lets developers create their own. The process begins with `ng generate pipe [name-of-pipe]`, replacing `[name-of-pipe]` with a preferable filename. This is an [Angular CLI](https://cli.angular.io) command. It yields the following.
```typescript
import { Pipe, PipeTransform } from @angular/core;
@Pipe({
name: 'example'
})
export class ExamplePipe implements PipeTransform {
transform(value: any, args?: any): any {
return null;
}
}
```
This pipe template simplifies custom pipe creation. The `@Pipe` decorator tells Angular the class is a pipe. The value of `name: example`, in this case being `example`, is the value Angular recognizes when scanning template HTML for custom pipes.
On to the class logic. The `PipeTransform` implementation provides the instructions for the `transform` function. This function has special meaning within context of the `@Pipe` decorator. It receives two parameters by default.
`value: any` is the output that the pipe receives. Think of `<div>{{ someValue | example }}</div>`. The value of someValue gets passed to the `transform` functions `value: any` parameter. This is the same `transform` function defined in the ExamplePipe class.
`args?: any` is any argument that the pipe optionally receives. Think of `<div>{{ someValue | example:[some-argument] }}</div>`. `[some-argument]` can be replace by any one value. This value gets passed to the `transform` functions `args?: any` parameter. That is, the `transform` function defined in ExamplePipe's class.
Whatever the function returns (`return null;`) becomes the output of the pipe operation. Take a look at the next example to see a complete example of ExamplePipe. Depending on the variable the pipe receives, it either uppercases or lowercases the input as new output. An invalid or nonexistent argument will cause the pipe to return the same input as output.
```typescript
// example.pipe.ts
@Pipe({
name: 'example'
})
export class ExamplePipe implements PipeTransform {
transform(value:string, args?:string): any {
switch(args || null) {
case 'uppercase':
return value.toUpperCase();
case 'lowercase':
return value.toLowerCase();
default:
return value;
}
}
}
```
```typescript
// app.component.ts
@Component({
templateUrl: 'app.component.html'
})
export class AppComponent {
someValue:string = "HeLlO WoRlD!";
}
```
```html
<!-- app.component.html -->
<!-- Outputs “HeLlO WoRlD!” -->
<h6>{{ someValue | example }}</h6>
<!-- Outputs “HELLO WORLD!” -->
<h6>{{ someValue | example:uppercase }}</h6>
<!-- Outputs “hello world!” -->
<h6>{{ someValue | example:lowercase }}</h6>
```
Understanding the above example means you understand Angular pipes. There is only one more topic left to discuss.
#### Pure and Impure Pipes
Everything you have seen so far has been a *pure* pipe. `pure: true` is set by default in the `@Pipe` decorator's metadata. The difference between the two constitutes Angulars change detection.
Pure pipes update automatically whenever the value of its derived input changes. The pipe will re-execute to produce new output upon a detectable change in the input value. Detectable changes are determined by Angulars change detection loop.
Impure pipes update automatically whenever a change detection cycle occurs. Angulars change detection happens quite often. It signals if changes have occurred in the component class member data. If so, the template HTML updates with the updated data. Otherwise, nothing will happen.
In the case of an impure pipe, it will update regardless of whether there is a detectable change or not. An impure pipe updates whenever change detection loops. Impure pipes usually consume lots of resources and are generally ill-advised. That said, they operate more as an escape hatch. If you ever need a detection-sensitive pipe, toggle `pure: false` in the `@Pipe` decorators metadata.
#### Conclusion
That covers pipes. Pipes have plenty of potential beyond the scope of this article. Pipes contribute succinct data transformations to your components template HTML. They are good practice in situations where data must undergo small transformations.
## Sources
1. [Wiki Community. *ISO 8601*. Wikipedia. Accessed 27 May 2018](https://en.wikipedia.org/wiki/ISO_8601)
## Resources
- [Angular Documentation](https://angular.io/guide/pipes)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [List of Pipes Pre-packaged with Angular](https://angular.io/api?query=pipe)
- [Angular CLI](https://cli.angular.io)

View File

@ -0,0 +1,346 @@
---
title: Reactive Extensions
---
# Reactive Extensions in Angular
#### Motivation
Reactive extensions for JavaScript (RxJS) is a library for *observable* data streams. RxJS installs with Angular upon command-line execution of `ng new [name-of-application]`. This uses the Angular command-line interface (CLI). RxJS supplements how data streamlines through an `Observable`. The `Observable` object facilitates the flow of *iterable* data.
Streams of data are not the primary use-case. After all, data streams parallel event streams. Events emit so an application knows when data arrives. While event streams form the core of what RxJS supplements, this article refers to them as data streams too.
Streams execute either synchronously (immediate) or asynchronously (overtime). RxJS handles both cases with ease via the `Observable` data stream. Strict asynchronicity is toggleable though. Working with in-memory, *iterable* data happens immediately while external data fetching takes time. Angular supports the RxJS library so that it may handle both use-cases with data streams.
#### Reactive Programming
Before diving in, its important to understand the paradigm backing the RxJS library. As mentioned, it works through the `Observable` object which streamlines event-emitting data.
RxJS functions around the base `Observable`. Its whole library supplements what it can do. RxJS even includes other objects including `Subject`, `Subscription`, and `Observer`. Each is its own custom variant of the base `Observable`.
RxJS arose from the Reactive Programming paradigm. This paradigm introduced the *observable* pattern. In it there exists this key idea: a single `Observable` emits while all its `Observer`s get notified. `Observer`s *subscribe* to `Observable`s so that they receive notification. This notification can mean several things.
It might indicate data change or data arrival as commonly stated in this article. It could signal a change in some part of the application that affects the `Observer`s.
This *observable* pattern also strives to decouple concepts. An `Observable` should be able function without any `Observer`s and vice versa. This usually means they can stand-alone rather than fully function without each other.
If curious, you can learn more about the foundations of Reactive Programming by reading [this Wikipedia article](https://en.wikipedia.org/wiki/Reactive_programming). This section covers what is necessary for the rest of the article.
#### Observables
To quickly reiterate, `Observable`s can be *observed*. This so that one `Observable` provides feedback to its dependencies based on a stream of data. In RxJS, the `Observable` is its own factory function used to create `Observable` objects. Their basic blueprint is as follows.
```typescript
import { Observable } from 'rxjs';
const observable = Observable.create((source) => {
source.next(data);
});
```
`.next` passes data while emitting an event to its observers. An `Observable` emits data from inside its `.create` callback using `.next`. It accepts one argument representing the data to emit. The `Observable` has not been implemented into JavaScript yet. RxJS provides an replacement from its library.
The next step is the observers. To tell a function or object to *observe* an `Observable`, the following syntax is used: `observable.subscribe(observer)`. Another way to look at it is `producer.subscribe(consumer)`. Observables *produce* data by calling `.next`. Consumers are then notified while receiving the data.
```typescript
import { Observable } from 'rxjs';
const observable = Observable.create((source) => {
source.next("Hello");
source.next("World!");
});
observable.subscribe((word) => console.log(word));
// console output
/*
Hello
World!
*/
```
Two invocations of `.next` occur from within the `Observable`'s `.create` callback (data producer). This results in two separate console outputs from the observer (data consumer).
The two invocations of `.next` represent a synchronous stream of data. Streams conceptualize data as a linear, in-order flow. It either resolves synchronously or asynchronously depending on the datas availability.
If data comprising a stream is readily available, it executes synchronously. Otherwise, the stream resolves asynchronously overtime. The order of the data in either case is always the same depending on the invocation of `.next` within the observable.
An `Observable` operates like a queue. Calling `.next` on a piece of data pushes it to the back of the queue. Data pops from the front once resolved.
`Observable` data streams hold huge appeal. They are deterministic in their order and execute sensibly depending on data availability. Plus, any number of observers can *observe* the data source `Observable`. This means data can produce once and emit anywhere all in one operation.
Callback functions are not the only way to consume data. Observables can chain into each other as producers and consumers.
```typescript
const observableI = Observable.create((source) => {
source.next("Hello World!");
});
const observableII = new Observable().subscribe((v) => console.log(v));
observableI.subscribe(observableII);
// console output
/*
Hello World!
*/
```
`.subscribe` is on the `Observable` object. You can call it with an `Observable` as its source (producer) and another observable as it argument (consumer). Data can flow (emit) through any number of observables.
#### Reactive Extensions for JavaScript (RxJS)
Streaming data is nice, but what is the point if observables cannot edit the stream? This where the RxJS library comes into play. It provides operators that perform various mutations on the data stream.
Angular leverages these operators to transform incoming data. Developers can trim off any unnecessary data from an incoming stream using RxJS operators. This saves memory and alleviates the need for additional transformation logic.
RxJS offers deviations from the standard `Observable` like `Subject`, `Subscription`, and `Observer`. Think of these deviations as special flavors of the traditional `Observable`. They are not necessary to make use of the library. That said, variants like `Subject` have incredible use-cases that surpass the standard `Observable`.
This article sticks with the standard `Observable`. All the data stream operators from RxJS work through the `Observable`.
Many core RxJS operators originated from JavaScript's Array Extras. The Array object's prototype contains many parallels to the RxJS library. These are otherwise known as 'Extras'. Arrays are stream-like structures similar to observable data steams.
To better understand RxJS operators, this article will briefly address JavaScript's Array Extras. Each on functions almost identically to its RxJS counterpart. The difference is simply the format of the data (iterable array vs iterable stream).
#### Array Extras
Arrays contain lots of utility methods. These methods are called Array Extras. They all exist on the Array objects prototype. The list below contains five Extras with RxJS parallels.
* `.reduce`
* `.filter`
* `.map`
* `.every`
* `.forEach`
For each example, the array iterates over itself to produce a final result.
`.reduce` minimizes an array into a single value. `.filter` trims an array with boolean evaluation. `.map` transforms an array element-by-element. `.every` evaluates true or false for the entire array depending on a boolean condition. `.forEach` iterates through an arrays elements.
Arrays model streams. The are in-order of each other and iterate one-by-one. Observables streamline data elements to their observers in a similar fashion. This is why RxJS includes a logical counterpart to each Array Extra in its library. Granted, RxJS provides way more of its own operators than there are Array Extras.
#### Basic RxJS Operators
There is literally an entire librarys worth of RxJS operators. This article focuses on those listed below which the Array Extras inspired.
* `.reduce`
* `.filter`
* `.map`
* `.every`
* `.forEach`
Nothing has changed from previous list. Your understanding of Array Extras applies to RxJS operators. The only catch to this is a function called `.pipe` which will see much use in the next few examples. `.pipe` chains RxJS operators together. Results from the previous operator segue into the next up until the final operator. The resulting data then emits from the observable stream.
Note the standard example below. Use it for comparison for each operators impact on the emitted data stream.
```typescript
import { Observable, from } from rxjs;
const stream: number[] = [1, 2, 3, 4, 5];
const observable: Observable<number> = from(stream);
observable.subscribe((val: number) => console.log(val));
// console output
/*
1
2
3
4
5
*/
```
`.from` converts an array into an `Observable` object that calls `.next` on each array element. The `.pipe` function accepts any number of arguments as array operators. This is where every operator gets implemented. Operators execute on streamlined data in order of their implementation as arguments for `.pipe`.
##### Reduce
`.reduce` minimizes the data stream into a single value before emitting.
```typescript
import { reduce } from rxjs/operators;
const stream: number[] = [1, 2, 3, 4, 5];
const observable: Observable<number> = from(stream).pipe(
reduce((accum, val) => (accum + val))
);
observable.subscribe((val: number) => console.log(val));
// console output
/*
15
*/
```
##### Filter
`.filter` trims a stream, eliminating stream values that do not satisfy its condition.
```typescript
import { filter } from rxjs/operators;
const stream: number[] = [1, 2, 3, 4, 5];
const observable: Observable<number> = from(stream).pipe(
filter((val) => (val % 2 === 0)) // filters out odd numbers
);
observable.subscribe((val: number) => console.log(val));
// console output
/*
2
4
*/
```
##### Map
`.map` targets and transforms each ongoing stream value.
```typescript
const stream: number[] = [1, 2, 3, 4, 5];
const observable: Observable<number> = from(stream).pipe(
map((val) => (val + 1))
);
observable.subscribe((val: number) => console.log(val));
// console output
/*
2
3
4
5
6
*/
```
##### Challenge: Every and ForEach
With knowledge of `.every` and `.forEach` as Array Extras, try to implement them as RxJS operators. Feel free to use the previous examples for guidance. A little bit of practice goes a long way after lots of reading!
#### HTTP in Angular
This section brings RxJS and Angular together to show how they interact. Typically, a service provided by Angular will provide the `Observable`. The `Observable`'s data stream can then mutate using RxJS operators with `.pipe`.
Angular provides an `HttpClient` service through `@angular/common/http`. `HttpClientModule` is also from `@angular/common/http` and exports the `HttpClient` service. The application's root module must import `HttpClientModule`. This makes `HttpClientModule` *injectable* from anywhere in the app.
The `HttpClientModule` service makes HTTP requests. These requests are asynchronous. What makes them interesting for Angular is how the request is handled. An `Observable` gets returned with each request. RxJS can take it away from there.
The upcoming example uses a public API built by [Typicode](https://jsonplaceholder.typicode.com). The API provides an array of 100 elements per asynchronous `GET` request.
```typescript
// ./models/post.model.ts
export interface Post {
userId: number;
id: number;
title: string;
body: string;
}
```
```typescript
// ./services/json.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, from } from 'rxjs';
import { switchMap, map, filter, reduce } from 'rxjs/operators';
import { Post } from '../models/post.model';
@Injectable({
providedIn: 'root'
})
export class JsonService {
constructor(private http: HttpClient) { }
getPostsByUserId(id: number): Observable<any> {
const trim$ = (stream) => from(stream)
.pipe(
filter((post: Post) => +post.userId === +id),
map((post: Post) => ({ title: post.title, body: post.body })),
reduce((accum: Post[], post: Post) => accum.concat([post]), [])
);
return this.http.get("https://jsonplaceholder.typicode.com/posts")
.pipe(
switchMap((value) => trim$(value))
);
}
}
```
```typescript
// ./components/example/example.component.ts
import { Component } from '@angular/core';
import { JsonService } from '../../services/json.service';
import { Post } from '../../models/post.model';
@Component({
selector: 'app-example',
template: `
<h1>Request User Posts</h1>
<span>User: </span><input #userInput>
<button (click)="requestForPosts(userInput.value)">REQUEST</button>
<hr>
<ul>
<div *ngIf="userPosts">
<div *ngFor="let post of userPosts">
<h3>{{ post.title }}</h3>
<p>{{ post.body }}</p>
</div>
</div>
<h3 *ngIf="!userPosts">No posts shown...</h3>
</ul>
`
})
export class ExampleComponent {
userPosts: Post[];
constructor(private json: JsonService) { }
requestForPosts(id: number): void {
this.json.getPostsByUserId(id)
.subscribe((posts: Post[]) => { this.userPosts = posts.length > 0 ? posts : null; });
}
}
```
`json.service.ts` creates an `Observable` on behalf of `component.example.ts`. The component may subscribe to the returned `Observable`. Only one value emits by the time the `Observable` resolves the data stream.
The request to `jsonplaceholder.typicode.com` yields a single array of 100 posts. The request via `HttpClient` yields an `Observable`. The operator `switchMap` returns another `Observable` which overwrites the current stream. The variable `trim$` stores the `Observable` as its value. Appending a `$` to a variable used for storing `Observable`s is convention.
`from` converts the array from `jsonplaceholder.typicode.com` into a 100-value-emitting `Observable`. RxJS operators then sift through each piece of data in the stream. They remove stream values irrelevant to the request. Data trimming takes place so that stream values stay lean of unnecessary information. The final results join together once again as a single array that emits one to its observers.
In `component.example.ts`, the JsonService references the method returning the just-described `Observable`. This method invokes upon button click in the component template. The input box also in the template supplies the single `id` argument.
With the button pressed, JsonService returns an `Observable` that emits a single array. `.subscribe` invokes on the returned `Observable`. The component then sets the value of `userPosts` equal to the emitted array.
Angular Change Detection picks up on the change in class data. The template updates and `*ngFor` ensures each array element from `userPosts` renders its own template element.
#### Conclusion
RxJS provides the core `Observable` along with its operators. The library installs automatically from the command-line using `ng new [name-of-app]` (Angular CLI). The RxJS core types and operators download to `rxjs` and `rxjs/operators`, respectively.
Even if you do not use the CLI, services such as `HttpClient` are still usable. The service returns a `Promise` instead of an `Observable` if RxJS is unavailable. The `Promise` object is native to JavaScript unlike the `Observable`. This will likely change in the next official JavaScript release.
That said, take full advantage of RxJS! Any iterable structure can accommodate the `Observable`. With it, the whole RxJS library becomes usable. Its operators efficiently transform data from a stream into results. Plus, observers can subscribe to results, increasing the overall portability of the data.
## Sources
- [Angular Team. “The RxJS library”. *Google*. Accessed 5 June 2018.](https://angular.io/guide/rx-library)
- [Forbes, Elliot. “Creating a Realtime App with Angular and Socket.io Tutorial”. *TutorialEdge.net*, 10 Jan. 2017. Accessed 5 June 2018.](https://tutorialedge.net/typescript/angular/angular-socket-io-tutorial)
- [RxJS Team. “RxJS Documentation”. *RxJS*. Accessed 5 June 2018.](https://rxjs-dev.firebaseapp.com)
- [Sukale, Ryan. “Difference between Rxjs Subject and Observable”. *TutorialHorizon*, 23 Mar. 2017. Accessed 5 June 2018.](https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable)
- [Wikipedia Community. “Reactive programming”. *Wikipedia*, 2 June 2018. Accessed 5 June 2018.](https://en.wikipedia.org/wiki/Reactive_programming)
## Resources
- [Angular Documentation](https://angular.io/guide)
- [Angular on GitHub](https://github.com/angular/angular)
- [Angular CLI](https://cli.angular.io)
- [RxJS and Angular](https://angular.io/guide/rx-library)
- [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming)
- [Reactive Extensions for JavaScript](https://rxjs-dev.firebaseapp.com)

View File

@ -0,0 +1,664 @@
---
title: Routing
---
# Routing
#### Motivation
Routing is essential. Many modern web applications host too much information for one page. Users should not have to scroll through an entire applications worth of content either. An application needs to split itself into distinguishable sections.
Users prioritize necessary information. Routing helps them find the application section with such information. Any other information useful to other users may exist on an entirely separate route. With routing, both users can find what they need quickly. Irrelevant details stay obscured behind irrelevant routes.
Routing excels at sorting and restricting access to application data. Sensitive data should never display to unauthorized users. Between every route the application may intervene. It can examine a users session for authentication purposes. This examination determines what the route renders if it should render at all. Routing gives developers the perfect chance to verify a user before proceeding.
Creating a list of routes promotes organization as well. In terms of development, it keeps the developer thinking in distinguishable sections. Users benefit from this too, but more-so developers when navigating the application code. A list of programmatic routers paints an accurate model of the applications front end.
As for Angular, routing takes up its own entire library within the framework. All modern front-end frameworks support routing, and Angular is no different. Routing happens from the client-side using either hash or location routing. Both styles allow the client to manage its own routes. No additional assistance from the server is necessary past the initial request.
The web browser rarely refreshes using client-side routing. Web browser utilities such as bookmarks, history, and the address bar still work despite no refreshing. This makes for a slick routing experience that does not mess up the browser. No more jumpy page reloads while routing to a different page.
Angular adds on a layer of abstraction over the core technologies used for routing. This article intends to explain this abstraction. There exists two routing strategies in Angular: path location and hash. This article focuses on the path location strategy since its the default option.
Plus, path location may deprecate hash routing following the full release of [Angular Universal](https://universal.angular.io). Regardless, the two strategies are very similar in implementation. Learning one learns the other. Time to get started!
#### RouterModule Setup
Routing utilities export with `RouterModule` available from `@angular/router`. It is not part of the core library since not all applications require routing. The most conventional way to introduce routing is as its own [feature module](https://angular.io/guide/feature-modules).
As route complexity grows, having it as its own module will promote the root modules simplicity. Keeping it stupid simple without compromising functionality constitutes good design for modules.
```typescript
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AComponent } from '../../components/a/a.component';
import { BComponent } from '../../components/b/b.component';
// an array of soon-to-be routes!
const routes: Routes = [];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule { }
```
`.forRoot(...)` is a class function available from the RouterModule class. The function accepts an array of `Route` objects as `Routes`. `.forRoot(...)` configures routes for eager-loading while its alternative `.forChild(...)` configures for lazy-loading.
Eager-loading meaning the routes load their content into the application from the get-go. Lazy-loading happens on-demand. The focus of this article is eager-loading. It is the default approach for loading in an application. The RouterModule class definition looks something like the next block of code.
```typescript
@NgModule({
// … lots of metadata ...
})
export class RouterModule {
forRoot(routes: Routes) {
// … configuration for eagerly loaded routes …
}
forChild(routes: Routes) {
// … configuration for lazily loaded routes …
}
}
```
Do not worry about the configuration details the example omits with comments. Having a general understanding will do for now.
Notice how AppRoutingModule imports the RouterModule while also exporting it. This makes sense given AppRoutingModule is a feature module. It imports into the root module as a feature module. It exposes RouterModule directives, interfaces, and services to the root component tree.
This explains why AppRoutingModule must export RouterModule. It does so for the sake of the root modules underlying component tree. It needs access to those routing utilities!
```typescript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AComponent } from './components/a/a.component';
import { BComponent } from './components/b/b.component';
import { AppRoutingModule } from './modules/app-routing/app-routing.module';
@NgModule({
declarations: [
AppComponent,
AComponent,
BComponent
],
imports: [
AppRoutingModule, // routing feature module
BrowserModule
],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule { }
```
The AppRoutingModule token imports from the very top. Its token inserts into the root modules imports array. The root component tree may now utilize the RouterModule library. That includes its directives, interfaces, and services as already mentioned. Big thanks goes to AppRoutingModule for exporting RouterModule!
The RouterModule utilities will come in handy for the roots components. The basic HTML for AppComponent makes use of one directive: `router-outlet`.
```html
<!-- app.component.html -->
<ul>
<!-- routerLink(s) here -->
</ul>
<router-outlet></router-outlet>
<!-- routed content appends here (AFTER THE ELEMENT, NOT IN IT!) -->
```
`routerLink` is an attribute directive of RouterModule. It will attach to each element of `<ul></ul>` once the routes are setup. `router-outlet` is a component directive with interesting behavior. It acts more as a marker for displaying routed content. Routed content results from navigation to a specific route. Usually that means a single component as configured in AppRoutingModule
The routed content renders right after `<router-outlet></router-outlet>`. Nothing renders inside of it. This does not make too much of a considerable difference. That said, do not expect `router-outlet` to behave like a container for routed content. It is merely a marker for appending routed content to the Document Object Model (DOM).
#### Basic Routing
The previous section establishes the basic setup for routing. Before actual routing can happen, a few more things must be addressed
The first question to address is what routes will this application consume? Well, there are two components: AComponent and BComponent. Each one should have its own route. They can render from AppComponents `router-outlet` depending on the current route location.
The route location (or path) defines what appends to a [website's origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) (e.g. http://localhost:4200) through a series of slashes (`/`).
```typescript
// … same imports from before …
const routes: Routes = [
{
path: 'A',
component: AComponent
},
{
path: 'B',
component: BComponent
}
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule { }
```
`http://localhost:4200/A` renders AComponent from AppComponents `router-outlet`. `http://localhost:4200/B` renders BComponent. You need a way to route to these locations without using the address bar though. An application should not rely upon a web browser's address bar for navigation.
*The global CSS (Cascading Style-sheets) supplements the HTML below it. An applications router link ought to have a pleasant appearance. This CSS applies to all other examples too.*
```css
/* global styles.css */
ul li {
cursor: pointer;
display: inline-block;
padding: 20px;
margin: 5px;
background-color: whitesmoke;
border-radius: 5px;
border: 1px solid black;
}
ul li:hover {
background-color: lightgrey;
}
```
```html
<!-- app.component.html -->
<ul>
<li routerLink="/A">Go to A!</li>
<li routerLink="/B">Go to B!</li>
</ul>
<router-outlet></router-outlet>
```
This is basic routing! Clicking either of the routerLink elments routes the web address. It reassigns it without refreshing the web browser. Angulars `Router` maps the routed address to the `Routes` configured in AppRoutingModule. It matches the address to the `path` property of a single `Route` object within the array. First match always wins, so match-all routes should lie at the very end of the `Routes` array.
Match-all routes prevent the application from crashing if it cannot match the current route. This can happen from the address bar where the user may type in any route. For this, Angular provides a wildcard path value `**` that accepts all routes. This route usually renders a PageNotFoundComponent component displaying “Error 404: Page not found”.
```typescript
// … PageNotFoundComponent imported along with everything else …
const routes: Routes = [
{
path: 'A',
component: AComponent
},
{
path: 'B',
component: BComponent
},
{
path: '',
redirectTo: 'A',
pathMatch: 'full'
},
{
path: '**',
component: PageNotFoundComponent
}
];
```
The `Route` object containing `redirectTo` keeps the PageNotFoundComponent from rendering as a result of `http://localhost:4200`. This is the applications home route. To fix this, `redirectTo` reroutes the home route to `http://localhost:4200/A`. `http://localhost:4200/A` indirectly becomes the applications new home route.
The `pathMatch: 'full'` tells the `Route` object to match against the home route (`http://localhost:4200`). It matches the empty path.
These two new `Route` objects go at the end of the array since first match wins. The last array element (`path: '**'`) always matches, so it goes last.
There is one last thing worth addressing before moving on. How does the user know where he or she is in the application relative to the current route? Sure there may be content specific to the route, but how is user supposed to make that connection? There should be some form of highlighting applied to the routerLinks. That way, the user will know which route is active for the given web page.
This is an easy fix. When you click a `routerLink` element, Angulars `Router` assigns *focus* to it. This focus can trigger certain styles which provide useful feedback to the user. The `routerLinkActive` directive can track this focus for the developer.
```html
<!-- app.component.html -->
<ul>
<li routerLink="/A" routerLinkActive="active">Go to A!</li>
<li routerLink="/B" routerLinkActive="active">Go to B!</li>
</ul>
<router-outlet></router-outlet>
```
The right assignment of `routerLinkActive` represents a string of classes. This example portrays only one class (`.active`), but any number of space-delimited classes may apply. When the `Router` assigns *focus* to a routerLink, the space-delimited classes apply to the host element. When the focus shifts away, the classes get removed automatically.
```css
/* global styles.css */
.active {
background-color: lightgrey !important;
}
```
Users can now easily recognize how the current route and the page content coincide. `lightgrey` highlighting applies to the routerLink matching the current route. `!important` ensures the highlighting overrides inline stylings.
#### Parameterized Routes
Routes do not have to be completely hard-coded. They can contain dynamic variables referenceable from the component corresponding the `Route` object. These variables are declared as parameters when writing the routes path.
Route parameters are either optional or mandatory for matching a particular `Route`. It depends on how a route writes its parameters. Two strategies exist: matrix and traditional parameterization.
Traditional parameterization begins from the `Routes` array configured in AppRoutingModule.
```typescript
const routes: Routes = [
// … other routes …
{
path: 'B',
component: BComponent
},
{
path: 'B/:parameter',
component: BComponent
},
// … other routes …
];
```
Focus on the two BComponent routes. Parameterization will eventually occur in both routes.
Traditional parameterization occurs in the second BComponent `Route`. `B/:parameter` contains the `parameter` parameter as indicated with the `:`. Whatever follows the colon marks the parameter's name. The `parameter` parameter is necessary for the second BComponent `Route` to match.
`parameter` reads in the value of whatever gets passed into the route. Routing to `http://localhost:4200/B/randomValue` will assign `parameter` the value of `randomValue`. This value can include anything besides another `/`. For example, `http://localhost:4200/B/randomValue/blahBlah` will not trigger the second BComponent `Route`. The PageNotFoundComponent renders instead.
BComponent can reference route parameters from its component class. Both approaches to parameterization (matrix and traditional) yield the same results in BComponent. Before seeing BComponent, examine the matrix form of parameterization below.
```typescript
// app.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(private router: Router) { }
routeMatrixParam(value: string) {
if (value)
this.router.navigate(['B', { parameter: value }]); // matrix parameter
else
this.router.navigate(['B']);
}
routeAddressParam(value: string) {
this.router.navigate(['B', value]);
}
}
```
Angulars dependency injection system provides an instantiation of the `Router`. This lets the component programmatically route. The `.navigate(...)` function accepts an array of values that resolves to a *routable* path. Something like `.navigate(['path', 'to', 'something'])` resolves to `http://localhost:4200/path/to/something`. `.navigate(...)` adds path-delimiting `/` marks when normalizing the array into a *routable* path.
The second form of parameterization occurs in `routeMatrixParam(...)`. See this line of code: `this.router.navigate(['B', { parameter: value }])`. This form of `parameter` is a matrix parameter. Its value is optional for the first BComponent `Route` to match (`/B`). The `Route` matches regardless of the parameter's presence in the path.
The `routeAddressParam(...)` resolves a route that matches the `http://localhost:4200/B/randomValue` parameterization approach. This traditional strategy needs a parameter to match the second BComponent route (`B/:parameter`).
The matrix strategy concerns `routeMatrixParam(...)`. With or without a matrix parameter in its path, the first BComponent route still matches. The `parameter` parameter passes to BComponent just like with the traditional approach.
To make full sense of the above code, here is the corresponding template HTML.
```html
// app.component.html
<ul>
<li routerLink="/A">Go to A!</li>
<li>
<input #matrixInput>
<button (click)="routeMatrixParam(matrixInput.value)">Matrix!</button>
</li>
<li>
<input #paramInput>
<button (click)="routeAddressParam(paramInput.value)">Param!</button>
</li>
</ul>
<router-outlet></router-outlet>
```
In the template, values are accepted as text input. The input injects it into the route path as a parameter. Two separate sets of boxes exist for each parameterization strategy (traditional and matrix). With all the pieces coming together, it is time to examine the BComponent component class.
```typescript
// b.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
@Component({
selector: 'app-b',
template: `
<p>Route param: {{ currParam }}</p>
`
})
export class BComponent implements OnInit {
currParam: string = "";
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.params.subscribe((param: ParamMap) => {
this.currParam = param['parameter'];
});
}
}
```
BComponent results from either of two BComponent routes in AppRoutingModule. `ActivatedRoute` instantiates into a set of useful information pertaining to the current route. That is, the route that caused BComponent to render. `ActivatedRoute` instantiates via dependency injection targeting the class constructor.
The `.params` field of `ActivatedRoute.params` returns an `Observable` which emits the route parameters. Notice how the two different parameterization approaches result in the `parameter` parameter. The returned `Observable` emits it as a key-value pair inside of a `ParamMap` object.
Between the two parameterization approaches, the `parameter` parameter resolved identically. The value emits from `ActivatedRoute.params` despite the approach to parameterization.
The address bar distinguishes the final results of each approach. Matrix parameterization (optional for `Route` match) yields the address: `http://localhost:4200/B;parameter=randomValue`. Traditional parameterization (required for `Route` match) yields: `http://localhost:4200/B/randomValue`.
Either way, the same BComponent results. The actual difference: a different BComponent `Route` matches. This entirely depends upon the parameterization strategy. The matrix approach ensures parameters are optional for `Route` matching. The traditional approach requires them.
#### Nested Routes
`Routes` may form a hierarchy. In the DOM, this involves one parent `router-outlet` rendering at least one child `router-outlet`. In the address bar, it looks like this: `http://localhost/parentRoutes/childRoutes`. In the `Routes` configuration, the `children: []` property denotes a `Route` object as having nested (child) routes.
```typescript
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NestComponent } from '../../components/nest/nest.component';
import { AComponent } from '../../components/nest/a/a.component';
import { BComponent } from '../../components/nest/b/b.component';
const routes: Routes = [
{
path: 'nest',
component: NestComponent,
children: [
{ path: 'A', component: AComponent },
{ path: 'B', component: BComponent }
]
}
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule { }
```
```typescript
// nest.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-nest',
template: `
<ul>
<li routerLink="./A">Go to A!</li>
<li routerLink="./B">Go to B!</li>
</ul>
<router-outlet></router-outlet>
`
})
export class NestComponent { }
```
NestComponent renders a `router-outlet` after rendering itself from another root-level `router-outlet` in AppComponent. The `router-outlet` of NestComponents template may render either AComponent (`/nest/A`) or BComponent (`/nest/B`).
The AppRoutingModule reflects this nesting in NestComponents `Route` object. The `children: []` field holds an array of `Route` objects. These `Route` object may also nest routes in their `children: []` fields. This can continue for however many layers of nested routes. The above example shows two layers of nesting.
Each `routerLink` contains a `./` as compared to `/`. The `.` ensures that the routerLink appends to the route path. The routerLink completely replaces the path otherwise. After routing to `/nest`, `.` expands into `/nest`.
This is useful for routing to either `/nest/A` or `/nest/B` from the `.nest` route. `A` and `B` constitute nested routes of `/nest`. Routing to `/A` or `/B` returns PageNotFound. `/nest` must prepend the two routes.
Take a look at the AppComponent containing the root-level `router-outlet` in its template. AppComponent is the first layer of nesting while NestComponent is the second.
```typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<ul>
<li routerLink="/nest">Go to nested routes!</li>
<li routerLink="/">Back out of the nested routes!</li>
</ul>
<router-outlet></router-outlet>
`
})
export class AppComponent { }
```
Inside the nest `Route` object, the `children: []` contains two more nested routes. They result in AComponent and BComponent when routing from `/nest` as previously discussed. These components are very simple for the sake of demonstration. `<li routerLink="/">...</li>` lets you navigate out of the nest routes to reset the example by navigating to the home route.
```typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-a',
template: `
<p>a works!</p>
`
})
export class AComponent { }
```
```typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-b',
template: `
<p>b works!</p>
`
})
export class BComponent { }
```
The `children: []` array accepts `Route` object as elements. `children: []` can apply to any of these elements as well. The children of these elements can continue nesting. This pattern may continue for however many layers of nesting. Insert a `router-outlet` into the template for every layer of nested routing.
Routing techniques apply regardless of a `Route` objects level of nesting. The parameterization techniques differ in only one aspect. Child routes can only access their parents parameters via `ActivatedRoute.parent.params`. `ActivatedRoute.params` targets the same level of nested routes. This excludes parent-level routes and their parameters.
`Route` guards are especially suited for nested routing. One `Route` object can restrict access to all its nested (child) routes.
#### Guarded Routes
Web applications often consist of public and private data. Both types of data tend to have their own pages with *guarded* routes. These routes allow/restrict access depending on the users privileges. Unauthorized users may interact with a guarded route. The route should block the user if he or she attempts to access its routed content.
Angular provides a bundle of authentication guards that can attach to any route. These methods trigger automatically depending on how the user interacts with the guarded route.
* `canActivate(...)` - fires when the user attempts to access a route
* `canActivateChild(...)` - fires when the user attempts to access a routes nested (child) routes
* `canDeactivate(...)` - fires when the user attempts to leave a route
Angulars guard methods are available from `@angular/router`. To help them authenticate, they may optionally receive a few parameters. Such parameters do not inject via dependency injection. Under the hood, each value gets passed in as an argument to the invoked guard method.
* `ActivatedRouteSnapshot` - available to all three
* `RouterStateSnapshot` - available to all three
* `Component` - available to `canDeactivate(...)`
`ActivatedRouteSnapshot` provides access to the route parameters of the guarded route. `RouterStateSnapshot` exposes the URL (uniform resource locator) web address matching the route. `Component` references the component rendered by the route.
To guard a route, a class implementing the guard methods needs to first exist as a service. The service can inject into AppRoutingModule to guard its `Routes`. The token value for the service may inject into any one `Route` object.
```typescript
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthService } from '../../services/auth.service';
import { UserService } from '../../services/user.service';
import { PrivateNestComponent } from '../../components/private-nest/private-nest.component';
import { PrivateAComponent } from '../../components/private-nest/private-a/private-a.component';
import { PrivateBComponent } from '../../components/private-nest/private-b/private-b.component';
const routes: Routes = [
{
path: 'private-nest',
component: PrivateNestComponent,
canActivate: [ AuthService ], // !!!
canActivateChild: [ AuthService ], // !!!
canDeactivate: [ AuthService ], // !!!
children: [
{ path: 'private-A', component: PrivateAComponent },
{ path: 'private-B', component: PrivateBComponent }
]
}
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ],
providers: [
AuthService,
UserService
]
})
export class AppRoutingModule { }
```
`canActivate`, `canActivateChild`, and `canDeactivate` implement from AuthService. The service implementation will be shown shortly alongside the UserService implementation.
UserService provides the information needed to authenticate a user. The AuthService guard method implementations perform the authentication. AppRoutingModule must include the two services into its providers array. This is so the modules injector knows how to instantiate them.
Nested routes exist off of the `/private-nest` path. The `Route` object for `/private-nest` contains a few more new fields. Their names should look familiar as they mirror their corresponding guard methods.
Each field fires its namesake's method implementation inside of the service when triggered. Any number of services can populate this array too. The method implementation of each service gets tested. They must return a boolean value or an `Observable` that emits a boolean value.
See the AuthService and UserService implementations below.
```typescript
// user.service.ts
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
class TheUser {
constructor(public isLoggedIn: boolean = false) { }
toggleLogin() {
this.isLoggedIn = true;
}
toggleLogout() {
this.isLoggedIn = false;
}
}
const globalUser = new TheUser();
@Injectable({
providedIn: 'root'
})
export class UserService {
theUser: TheUser = globalUser;
constructor(private router: Router) { }
get isLoggedIn() {
return this.theUser.isLoggedIn;
}
login() {
this.theUser.toggleLogin();
}
logout() {
this.theUser.toggleLogout();
this.router.navigate(['/']);
}
}
```
The same instance of `TheUser` gets passed with each instantiation of UserService. `TheUser` provides access to `isLoggedIn` determining the users login status. Two other public methods let the UserService toggle the value of `isLoggedIn`. This is so the user can log in and out.
You can think of `TheUser` as a global instance. `UserService` is a instantiable interface that configures this global. Changes to `TheUser` from one `UserService` instantiation apply to every other `UserService` instance. `UserService` implements into AuthService to provide access to `isLoggedIn` of `TheUser` for authentication.
```typescript
import { Component, Injectable } from '@angular/core';
import { CanActivate, CanActivateChild, CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { UserService } from './user.service';
@Injectable({
providedIn: 'root'
})
export class AuthService implements CanActivate, CanActivateChild, CanDeactivate<Component> {
constructor(private user: UserService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (this.user.isLoggedIn)
return true;
else
return false;
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.canActivate(route, state);
}
canDeactivate(component: Component, route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (!this.user.isLoggedIn || window.confirm('Leave the nest?'))
return true;
else
return false;
}
}
```
AuthService implements every guard method imported from `@angular/router`. Each guard method maps to a corresponding field in the PrivateNestComponents `Route` object. An instance of UserService instantiates from the AuthService constructor. AuthService determines if a user may proceed using `isLoggedIn` exposed by UserService.
Returning `false` from a guard instructs the route to block the user from routing. A return value of `true` lets the user proceed to his route destination. If more than one service authenticates, they all must return true to permit access. `canActivateChild` guards the child routes of PrivateNestComponent. This guard method accounts for users bypassing PrivateNestComponent through the address bar.
Guard method parameters pass in automatically upon invocation. While the example does not make use of them, they do supply useful information from the route. The developer can use this information to help authenticate the user.
AppComponent also instantiates UserService for direct use in its template. The UserService instantiation of AppComponent and AuthService reference the same user class (`TheUser`).
```typescript
import { Component } from '@angular/core';
import { UserService } from './services/user.service';
@Component({
selector: 'app-root',
template: `
<ul>
<li routerLink="/private-nest">Enter the secret nest!</li>
<li routerLink="/">Leave the secret nest!</li>
<li *ngIf="user.isLoggedIn"><button (click)="user.logout()">LOGOUT</button></li>
<li *ngIf="!user.isLoggedIn"><button (click)="user.login()">LOGIN</button></li>
</ul>
<router-outlet></router-outlet>
`
})
export class AppComponent {
constructor(private user: UserService) { }
}
```
UserService handles all the logic for AppComponent. AppComponent mostly concerns its template. A UserService does instantiate as `user` from the class constructor. `user` data determines the template's functionality.
#### Conclusion
Routing strikes a fine balance between organizing and restricting sections of the application. A smaller application such as a blog or tribute page may not require any routing. Even then, including a little bit of hash routing could not hurt. A user may only want to reference part of the page after all.
Angular applies its own routing library built on top of the HTML5 [history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API). This API omits hash routing to instead use the `pushState(...)` and `replaceState(...)` methods. They change the web address URL without refreshing the page. The default path location routing strategy in Angular works this way. Setting `RouterModule.forRoot(routes, { useHash: true })` enables hash routing if preferred.
This article focused on the default path location strategy. Regardless of the strategy, many routing utilities are available to route an application. The `RouterModule` exposes these utilities through its exports. Basic, parameterized, nested, and guarded routes are all possible utilizing RouterModule. For more advanced implementations including lazily-loaded routes, see the below links.
## Sources
- [Angular Team. “Routing and Navigation”. *Google*. Accessed 8 June 2018.](https://angular.io/guide/router)
- [Hussain, Asim. “Angular 5: Routing”. *codecraft.tv*. Accessed 8 June 2018.](https://codecraft.tv/courses/angular/routing)
- [Smith, Peter. “3 Types of Route Loading in Angular, Explained In 500ish words”. *Upstate Interactive*, 3 May 2017. Accessed 8 June 2018.](https://blog.upstate.agency/3-types-of-route-loading-in-angular-explained-in-500ish-words-f22976e1f60b)
- [Koretskyi, Maxim. “Avoiding common confusions with modules in Angular”. *Angular In Depth*, 10 Aug. 2017. Accessed 8 June 2018.](https://blog.angularindepth.com/avoiding-common-confusions-with-modules-in-angular-ada070e6891f)
## Resources
- [Angular Documentation](https://angular.io/guide)
- [Routing & Navigation](https://angular.io/guide/router)
- [Angular 5: Routing Tutorial by Asim Hussain](https://codecraft.tv/courses/angular/routing/overview)
- [Angular in Depth](https://blog.angularindepth.com)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Angular CLI](https://cli.angular.io)

View File

@ -0,0 +1,256 @@
---
title: Services and Injectors
---
# Services and Injectors
#### Motivation
Components are responsible for the data that renders into the template. Having external *services* to draw upon can simplify this responsibility. Plus, encapsulating extraneous is much easier to maintain.
Delegating too many responsibilities onto a single component can complicate the component class. And what if these responsibilities applied to several components? Copying and pasting such logic is extremely poor practice. Any future changes to the logic would be harder to implement and test.
Angular meant to curb this issue with services and dependency injection. Both concepts work together to provide *modular* functionality.
Components do not need to provide any extraneous information either. A services imports what it needs to function on behalf of the components it *services*. The components only need to instantiate the service. From there they *service* their own needs with the instantiated service instance.
As for testing and future modification, all the logic is in one place. The service instantiates from its source. Tests and modifications to the source apply anywhere the service is injected.
#### Introduction to Services
A service is a type of *schematic* available in Angular. It is generatable by the command-line interface (CLI): `ng generate service [name-of-service]`. Replace `[name-of-service]` with a preferable name. The CLI command yields the following.
```typescript
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LoggerService {
constructor() { }
}
```
The logic of a service is distinct within its class. Angular interprets a class as an *injectable* service based off the `@Injectable` decorator. Injectable services must *register* with an injector.
The component instantiates a service while the injector provides that instance. Keep reading into the next section for more on injectors.
The `@Injectable` metadata field `providedIn: root` targets the root module of the current application (`app.module.ts`). It registers the service with the modules injector so that it can *inject* that service into any of its children.
Injectors are the building blocks of Angular's dependency injection system. Injectors are a good place to focus your attention before continuing with services.
#### Injectors
An application, beginning with `app.module.ts`, contains a hierarchy of injectors. They exist alongside each module and component in the application tree.
![Application Hierarchy](https://raw.githubusercontent.com/sosmaniac-FCC/designatedata/master/image5.png)
The green circles indicate injectors. They provide service instances to instantiating components. Depending on which injector a service is registered with, it may or may not be available to a component.
Services registered at the root of the app (`app.module.ts`) are available to all components. An injector for a component may not have a certain service registered. If that is the case and the component requests its instantiation, the injector will defer to its parent. This trend continues until either reaching the root injector or the service is found.
Looking at the diagram, say that a service registers at point Bs injector. All components at point C and down will not be able to access the service registered at Bs injector. Injectors will never defer to their children for a service instance.
#### Dependency Injection
There are multiple ways to register a service with an application's injectors.
The `providedIn: root` metadata field of `@Injectable` provides the most recommended approach. This metadata field released with Angular 6.
As mentioned before, `providedIn: root` registers a service with the root module injector. It is instantiable across the entire application as a result.
The novelty of `providedIn: root` is *tree-shaking*. If the service is unused despite its registration, it gets *shaken* from the application at run-time. That way it does not consume any resources.
The other two ways are more direct and traditional. Granted, they do not offer tree-shaking.
A service can register with any injector along the component tree. You insert the service as a provider in the `@Component` metadata field: `providers: []`. The service is available to the component and its children
In the third registration strategy, the `providers: []` metadata exists as its own field in the `@NgModule` decorator. The service is instantiable from the module to the underlying component tree.
Remember that unlike with `providedIn: root`, `@NgModule` registration does not offer tree-shaking. Both strategies are otherwise identical. Once a service registers with `@NgModule`, it consumes resources even if left unused by the application.
#### Services Continued
Writing an actual service comes next. To recap, services handle certain functions on behalf of an applications components.
Services excel at handling common operations. They spare components the responsibility by doing so. It saves time not having to re-write common operations across multiple components. It is also more testable because the code is in one place. Changes only need to happen in one place without having to search elsewhere.
#### Use Cases
A couple examples goes a long way towards a complete understanding of services.
* console logs
* API requests
Both are common across most applications. Having services to handle these operations will reduce component complexity.
##### Console Logs
This example builds up from the base `@Injectable` skeleton. The skeleton is available through executing the CLI (`ng generate service [name-of-service]]`).
```typescript
// services/logger.service.ts
import { Injectable } from '@angular/core';
interface LogMessage {
message:string;
timestamp:Date;
}
@Injectable({
providedIn: 'root'
})
export class LoggerService {
callStack:LogMessage[] = [];
constructor() { }
addLog(message:string):void {
// prepend new log to bottom of stack
this.callStack = [{ message, timestamp: new Date() }].concat(this.callStack);
}
clear():void {
// clear stack
this.callStack = [];
}
printHead():void {
// print bottom of stack
console.log(this.callStack[0] || null);
}
printLog():void {
// print bottom to top of stack on screen
this.callStack.reverse().forEach((logMessage) => console.log(logMessage));
}
getLog():LogMessage[] {
// return the entire log as an array
return this.callStack.reverse();
}
}
```
LoggerService registers with the root module through the `@Injectable` metadata. Thus it can instantiate in the `app.component.html`.
```typescript
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { LoggerService } from './services/logger.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
logs:object[] = [];
constructor(private logger:LoggerService) { }
updateLog():void {
this.logger.printHead();
this.logs = this.logger.getLog();
}
logMessage(event:any, message:string):void {
event.preventDefault();
this.logger.addLog(`Message: ${message}`);
this.updateLog();
}
clearLog():void {
this.logger.clear();
this.logs = [];
}
ngOnInit():void {
this.logger.addLog(View Initialized);
this.updateLog();
}
}
```
The template HTML provides further insight into the components use of LoggerService.
```html
<!-- app.component.html -->
<h1>Log Example</h1>
<form (submit)="logMessage($event, userInput.value)">
<input #userInput placeholder="Type a message...">
<button type="submit">SUBMIT</button>
</form>
<h3>Complete Log</h3>
<button type="button" (click)="clearLog()">CLEAR</button>
<ul>
<li *ngFor="let log of logs; let i=index">{{ logs.length - i }} > {{ log.message }} @ {{ log.timestamp }}</li>
</ul>
```
This has the feel of a ToDo application. You can log messages and clear the log of messages. Imagine if all the logic from the service was shoved into AppComponent! It would have complicated the code. LoggerService keeps the log-related code encapsulated from the core AppComponent class.
##### Fetch Requests
Here is one more example worth playing around with. This example is possible thanks to [typicodes JSONPlaceholder<sup>1</sup>](https://jsonplaceholder.typicode.com). The API is public and free to use.
```typescript
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
// https://jsonplaceholder.typicode.com
// public API created by typicode @ https://github.com/typicode
interface Post {
userId:number;
id:number;
title:string;
body:string;
}
@Injectable({
providedIn: 'root'
})
export class PlaceholderService {
constructor(private http:HttpClient) { }
getPosts():Observable<Post[]> {
return this.http.get('https://jsonplaceholder.typicode.com/posts');
}
getPost(id:number):Observable<Post> {
return this.http.get(`https://jsonplaceholder.typicode.com/posts/${id}`);
}
}
```
This is more of a stand-alone piece than a fully fleshed out example. Fetch requests tend to work better as an injectable service. The alternative is an over-complicated component. The injected class subscribes to what the PlaceholderService pre-configures.
#### Conclusion
Services and dependency injection are very useful together. They allow developers to encapsulate common logic and inject across multiple different components. This alone is a massive convenience for any future maintenance.
Injectors work as intermediaries. They mediate between instantiating components and a reservoir of registered services. Injectors offer these instantiable services to their branch children.
See the next few links for more information on services and dependency injection.
## Sources
1. [Typicode, *JSONPlaceholder*, https://jsonplaceholder.typicode.com, Accessed 29 May 2018.](https://jsonplaceholder.typicode.com)
## Resources
- [Angular Documentation](https://angular.io/docs)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Dependency Injection](https://angular.io/guide/dependency-injection-pattern)
- [Intro to Services and DI](https://angular.io/guide/architecture-services)

View File

@ -0,0 +1,242 @@
---
title: Views
---
# Views
#### Motivation
Views offer a necessary layer of abstraction. They keep Angular independent of platform specific utilities. As a cross-platform technology, Angular uses its views to connect with the platform.
For every element in Angulars template HTML, there is a corresponding view. Angular recommends interacting with the platforms through these views. While direct manipulation is still possible, Angular warns against it. Angular offers its own application programming interface (API) to replace the native manipulations.
Shunning views for platform-specific API has its consequences. When developing Angular in a web browser, elements exist in two places: the DOM and the view. Messing only with the DOM does not impact the view.
Since Angular does not interface with the platform, this creates a discontinuity. Views should mirror the platform one-to-one. Otherwise Angular wastes resources managing elements that mismatch it. This is terrible in the event of deleted elements.
These sorts of discrepancies make views appear unnecessary. Never forget that Angular is a universal development platform above all. Views are a necessary abstraction for this end.
By adhering to views, Angular applications will function across all supported development platforms. Platforms include the Web, Android, and Apple iOS.
#### Note
From here-on, this article assumes a web browser environment. Feel free to mentally replace the DOM with something more applicable to your preferred platform.
#### What are Views?
Views are almost like their own virtual DOM. Each view contains a reference to a corresponding section of the DOM. Inside a view are nodes that mirror what is in the this section. Angular assigns one view node per DOM element. Each node holds a reference to a matching element.
When Angular checks for changes, it checks the views. Angular avoids the DOM under the hood. The views reference the DOM on its behalf. Other mechanisms are in place to ensure that view changes render to the DOM. Conversely, changes to the DOM do not affect the views.
Again, views are common across all development platforms besides the DOM. Even if developing for one platform, views are still considered best practice. They guarantee Angular has a correct interpretation of the DOM.
Views may not exist on third-party libraries. Direct DOM manipulation is an escape hatch for this kind of scenario. Granted, do not expect the application to function cross-platform.
#### Types of Views
There are two main types of views: embedded and host.
There also exists view containers. They hold embedded and host views and are often referred to as simple “views”.
Every `@Component` class registers a view container (view) with Angular. New components generate a custom selector targeting a certain DOM element. The view attaches to that element wherever it appears. Angular now knows the component exists looking at the view model.
Host views attach to components created dynamically with factories. Factories provide a blueprint for view instantiation. That way the application can instantiate the components host view during runtime. A host view attaches to a components wrapper per its instantiation. This view stores data describing conventional component capabilities.
`<ng-template></ng-template>` is a akin to the HTML5 `<template></template>` element. Angular's `ng-template` works with embedded views. These views do not attach to DOM elements unlike host views. They are identical to host views in that they both types exist inside of view containers.
Keep in mind, `ng-template` is not a DOM element. It gets commented out later leaving nothing but the embedded view nodes behind.
The difference depends on input data; embedded views store no component data. They store a series of elements as nodes comprising its template. The template makes up all the innerHTML of `ng-template`. Each element within the embedded view is its own separate view node.
#### Host Views and Containers
Host views *host* dynamic components. View containers (views) attach automatically to elements already in the template. Views can attach to any element beyond what is unique to component classes.
Think of the traditional method of component generation. It begins by creating a class, decorating it with `@Component`, and filling in metadata. This approach occurs for any pre-defined component element of the template.
Try using the Angular command-line interface (CLI) command: `ng generate component [name-of-component]`. It yields the following.
```typescript
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css']
})
export class ExampleComponent implements OnInit {
constructor() { }
ngOnInit() { }
}
```
This creates the component with the selector `app-example`. This attaches a view container to `<app-example></app-example>` in the template. If this were the root of the application, its view would encapsulate all other views. The root view marks the beginning of the application from Angular's perspective.
Creating components dynamically and registering them in the Angular view model takes a few extra steps. Structural directives help manage dynamic content (`*ngIf, *ngFor, and *ngSwitch…`). Directives do not scale to bigger applications however. Too many structural directives complicates the template.
This is where instantiating components from existing class logic comes in handy. These components need to create a host view that can insert into the view model. Host views holds data for components so that Angular recognizes their structural purpose.
##### Host Views Continued
Every component has a class definition. Yet JavaScript does not support classes. Classes are syntactic sugar. They produce functions containing component factories instead.
Factories act as blueprints for host views. They build views to interface with Angular on behalf of their components. Host views attach to DOM elements. Technically any element is OK but the most common target is `<ng-component></ng-component>`.
A view container (view) for holding views must first exist. `<ng-container></ng-container>` is a great place to attach a view container. View containers are the same type of views that also apply to template class elements.
A few helpers and references from `@angular/core` provide the other needed utilities. The following example puts it all together.
```typescript
// another.component.ts
import { Component } from '@angular/core';
@Component({
template: `
<h1>Another Component Content</h1>
<h3>Dynamically Generated!</h3>
`
})
export class AnotherComponent { }
```
```typescript
// example.component.ts
import { AfterViewInit, Component, ViewChild,
ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { AnotherComponent } from './another.component';
@Component({
selector: 'app-example',
template: `
<h1>Application Content</h1>
<ng-container #container></ng-container>
<h3>End of Application</h3>
`,
entryComponents: [ AnotherComponent ]
})
export class ExampleComponent implements AfterViewInit {
@ViewChild("container", { read: ViewContainerRef }) ctr: ViewContainerRef;
constructor(private resolve: ComponentFactoryResolver) { }
ngAfterViewInit() {
const factory = this.resolve.resolveComponentFactory(AnotherComponent);
this.ctr.createComponent(factory);
}
}
```
Assume AnotherComponent and ExampleComponent are both declared under the same module. AnotherComponent is a simple class component dynamically added into ExampleComponent's view. ExampleComponents `entryComponents` metadata must contain AnotherComponent for [bootstrapping](https://angular.io/guide/bootstrapping).
While ExampleComponent is a part of the template, AnotherComponent remains detached. It dynamically renders into the template from ExampleComponent.
There are two view containers present: `<app-example></app-example>` and `<ng-container></ng-container>`. The host view for this example will insert into `ng-container`.
The `AfterViewInit` lifecycle hook fires after the `@ViewChild` queries complete. Using the *template reference variable* `#container`, the `@ViewChild` references `ng-container` as `ctr`.
`ViewContainerRef` is the type of reference for view containers (views). `ViewContainerRef` references a view that supports the insertion of other views. `ViewContainerRef` contains more methods for managing its contained views.
Through dependency injection, the constructor instantiates an instance of Angulars `ComponentFactoryResolver` service. This service extracts the the factory function (host view blueprint) of AnotherComponent.
The single argument of `createComponent` requires a factory. The `createComponent` function derives from `ViewContainerRef`. It instantiates AnotherComponent under a host view derived from the component's factory.
The host view then inserts into the view container. `<ng-component></ng-component>` wraps the component inside of the view container. It has attached to it the aforementioned host view. `ng-component` is the host view's connection with the DOM.
There are other ways create a host view dynamically from a component. Other ways often [focus on optimization](https://blog.angularindepth.com/working-with-dom-in-angular-unexpected-consequences-and-optimization-techniques-682ac09f6866).
The `ViewContainerRef` holds a powerful API. It can manage any number of views either host or embedded within its view. The API includes view operations such as insert, move, and delete. This lets you manipulate the DOM through Angulars view model. This is best practice so that Angular and the DOM match each other.
#### Embedded Views
Note: embedded views attach to other views no added input. Host views attach to a DOM element with input data from its host view describing it as a component.
Structural directives create an [`ng-template` surrounding a chunk of HTML content](https://angular.io/guide/structural-directives#the-asterisk--prefix). The directive's host element has a view container attached. This make it so that the content can conditionally render into its intended layout.
The `ng-template` holds embedded view nodes representing each element within its innerHTML. `ng-template` is by no means a DOM element. It comments itself out. The tags define the extend of its embedded view.
#### Embedded Views Continued
Instantiating an embedded view requires no external resources beyond its own reference. The `@ViewChild` query can fetch that.
With the template reference, calling `createEmbeddedView` from it does the trick. The innerHTML of the reference becomes its own embedded view instance.
In the next example, `<ng-container></ng-container>` is a view container. `ng-container` gets commented out during compilation just like `ng-template`. Thus it provides an outlet for inserting the embedded view while keeping the DOM lean.
The embedded view template inserts at the layout location of `ng-container`. This newly inserted view has no additional view encapsulation besides the view container. Remember how that differs from host views (host views attach to their `ng-component` element wrapper).
```typescript
import { Component, AfterViewInit, ViewChild,
ViewContainerRef, TemplateRef } from '@angular/core';
@Component({
selector: 'app-example',
template: `
<h1>Application Content</h1>
<ng-container #container></ng-container> <!-- embed view here -->
<h3>End of Application</h3>
<ng-template #template>
<h1>Template Content</h1>
<h3>Dynamically Generated!</h3>
</ng-template>
`
})
export class ExampleComponent implements AfterViewInit {
@ViewChild("template", { read: TemplateRef }) tpl: TemplateRef<any>;
@ViewChild("container", { read: ViewContainerRef }) ctr: ViewContainerRef;
constructor() { }
ngAfterViewInit() {
const view = this.tpl.createEmbeddedView(null);
this.ctr.insert(view);
}
}
```
`@ViewChild` queries for the *template reference variable* `#template`. This provides a template reference of type `TemplateRef`. `TemplateRef` holds the `createEmbeddedView` function. It instantiates the template as an embedded view.
The single argument of `createEmbeddedView` is for context. If you wanted to pass in additional metadata, you could do it here as an object. The fields should match up with the `ng-template` attributes (`let-[context-field-key-name]=“value”`). Passing `null` indicates no extra metadata is necessary.
A second `@ViewChild` query provides a reference to `ng-container` as a `ViewContainerRef`. Embedded views only attach to other views, never the DOM. The `ViewContainerRef` references the view that takes in the embedded view.
An embedded view may also insert into the component view of `<app-example></app-example>`. This approach positions the view at the very end of ExampleComponents view. In this example however, we want the content to show up in the very middle where `ng-container` sits.
The `ViewContainerRef` `insert` function *inserts* the embedded view into the `ng-container`. The view content shows ups in the intended location right in the middle of ExampleComponent's view.
#### Conclusion
Manipulating the DOM with platform specific methods is not recommended. Creating and managing a tight set of views keeps Angular and the DOM on the same page. Updating the views informs Angular of the current state of the DOM. Updates to the views also carry over into what the DOM displays.
Angular provides a flexible API for view interaction. Developing platform independent applications is possible thanks to this level of abstraction. Of course, the temptation to fallback on platform dependent strategies persists. Unless you have a very good reason not to, try to stick with the views API Angular provides. This will yield predictable results across all platforms.
Check out the below resources too! This article merely scratches the surface. Views have plenty of other use cases too vast for one article.
## Sources
- [AngularInDepth.com. “Component View, Host View, Embedded View”, #40423772. 11 July 2017. “What is the difference between a view, a host view and an embedded view”](https://stackoverflow.com/questions/40423772/what-is-the-difference-between-a-view-a-host-view-and-an-embedded-view)
- [Angular Team. “Structural Directives”. *Google*. Accessed 31 May 2018](https://angular.io/guide/structural-directives)
- [Koretskyi, Maxim. “Exploring Angular DOM manipulation techniques using ViewContainerRef”. *Angular In Depth*, 4 Mar. 2017. Accessed 30 May 2018.](https://blog.angularindepth.com/exploring-angular-dom-abstractions-80b3ebcfc02)
- [Koretskyi, Maxim. “Implementing advanced DOM manipulation scenarios”.*Youtube*, uploaded by ng-conf, 19 Apr. 2018. Accessed 30 May 2018](https://www.youtube.com/watch?v=vz9cNCkaPsY)
- [Koretskyi, Maxim. “Working with DOM in Angular: unexpected consequences and optimization techniques”. *Angular In Depth*, 3 May 2017. Accessed 31 May 2018](https://blog.angularindepth.com/working-with-dom-in-angular-unexpected-consequences-and-optimization-techniques-682ac09f6866)
## Resources
- [Angular Documentation](https://angular.io/guide/pipes)
- [Angular in Depth](https://blog.angularindepth.com)
- [ViewContainerRef](https://angular.io/api/core/ViewContainerRef)
- [TemplateRef](https://angular.io/api/core/TemplateRef)
- [Angular GitHub Repository](https://github.com/angular/angular)
- [Angular CLI](https://cli.angular.io)