Angular Flashcards

1
Q

Pre-requisites for running angular app

A

install node.js, that is what angular CLI runs with

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Creating new app

A

ng new appname –defaults = to create app with defaults
cd folder
npm start

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

new app with single typescript file

A

ng new appname –routing –style scss -s -t
style scss - scss styles
-s = put style in component.ts file
-t = put the html in the component.ts file
–routing = if your app is going to have more than one page

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

@component -decorator

A
it is a directive that declares the class 
the decorator is a function that says pass these parameters
@Component({
  selector: 'app-root',
selector is used as element in html like    for the component to show up
components are the visual piece of information that we see on the screen
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Directives in angular

A

There are three kinds of directives in Angular:

Components—directives with a template.
Structural directives—change the DOM layout by adding and removing DOM elements.
Attribute directives—change the appearance or behavior of an element, component, or another directive.
Components are the most common of the three directives. You saw a component for the first time in the Getting Started tutorial.

Structural Directives change the structure of the view. Two examples are NgFor and NgIf. Learn about them in the Structural Directives guide.

Attribute directives are used as attributes of elements. The built-in NgStyle directive in the Template Syntax guide, for example, can change several element styles at the same time.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Creating a new Directive

A

ng generate directive highlight
import { Directive, ElementRef } from ‘@angular/core’;

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
    constructor(el: ElementRef) {
       el.nativeElement.style.backgroundColor = 'yellow';
    }
}
You use the ElementRef in the directive's constructor to inject a reference to the host DOM element, the element to which you applied appHighlight.

ElementRef grants direct access to the host DOM element through its nativeElement property.

This first implementation sets the background color of the host element to yellow.

in appComponent.html:

<p>Highlight me!</p>

using the attribute directive
To summarize, Angular found the appHighlight attribute on the host <p> element. It created an instance of the HighlightDirective class and injected a reference to the </p><p> element into the directive’s constructor which sets the </p><p> element’s background style to yellow.</p>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Directives

A
Decorator that marks a class as an Angular directive. You can define your own directives to attach custom behavior to elements in the DOM.
selector	
The CSS selector that identifies this directive in a template and triggers instantiation of the directive.

providers
Configures the injector of this directive or component with a token that maps to a provider of a dependency.

Subclass- component:
The options provide configuration metadata that determines how the directive should be processed, instantiated and used at runtime.

Directive classes, like component classes, can implement life-cycle hooks to influence their configuration and behavior.

Options
The CSS selector that identifies this directive in a template and triggers instantiation of the directive.

selector: string

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

npm start

A

it looks at package.json; script - sees that start - refers to ng serve and runs that command

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Changing port that angular runs from 4200

A

npm start – –port 4201 ; it builds the application

http://localhost:4201/

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Structure of application - src - app folder

A

src – app = this has our source code
app folder has 4 files:
appmodule.ts = it is the manifest; everything in our app
appcomponent.ts = it is the first component that loads inside our webpage
app-routing.module.ts = our routing module

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

spec.ts

A

to test your components

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

assets folder

A

if you have images or fonts put them here; it will automatically deploy for you

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

files index.html and main.ts

A

starting point of the app
when the app cranks up, index.html is the base page that loads , this page contains our app component
main.ts = this kicks off angular in the page
index.html = there is a script tag that runs main.ts which kicks off angular
——–
main.ts
platformBrowserDynamic().bootstrapModule(AppModule):
go ahead and load the browser platforms, which is angular component
bootstrap with AppModule- which means start running it
when angular starts; it says go look into AppModule for everything you need to load

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

package.json

A

our dependencies for the application lives and the scripts
angular is listed here as we are using it
scripts like npm start are listed

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

AppModule.ts

A

it says bootstrap - AppComponent
what features to use? in the imports we specify that
imports: [
BrowserModule,
AppRoutingModule
],
it contains everything that our applications needs to start
@ngModule decorator- it is a function; it says this class called AppModule is an ngModule
we declare the components used in it
we import the functionality to use
which component to start with- bootstrap

Module is just a manifest - nothing visual on the screen for the users. it helps to organize the app

@NgModule({
  declarations: [
    AppComponent,
    HighlightDirective
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

AppComponent.ts

A

selector in appComponent.ts - this is what is being used in index.html to list like
we prefix the selectors like app-name; so that it does not collide with normal html elements like <div></div>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

creating a component

A

ng generate component heroes / ng g c heores -d
it creates heroes.component.ts and heroes.component…spect.ts files and updates the app.module.ts
-d = for dry run

we could directly paste the selector in the app.component.ts

Selector - the name of the html element we will use
template URL -is the location of html template for this component
the hero is a model that may contain the data we can use in our component

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

dry run

A

ng g c heroes -d

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

ngOnInit()

A

for start up code

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Interpolation

A

Display models with {{model}}

<div> Hello {{hero.name}} </div> - this is read only data

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

one way property binding

A

<img></img> Binding a DOM property to a value or expression using square brackets []
using dot for nested properties and attr to bind to attributes
save - binding for the disabled property of a button

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

attribute binding

A

<div></div>

if there is no DOM property then we use attribute binding

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Two-way data binding

A

initial value in the model property is shown in the html page, if any changes are made to the input element then the changes are made in the component model properties

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Event binding

A

Execute when an event occurs , wrap with ()
(target)=”expression” or on-target=”expression”
No
if the button is clicked onNo() function is executed

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
ngModel
[(ngModel)]= Model.PropertyName; [] - for property binding from the Component Model and then then ()- event binding if any changes are made to the html element then changes are made to the component property it is a directive, just binding the data and not changing the structure of the page
26
Rendering a list ; structural director; *ngFor
{{ hero.FirstName }} {{ hero.LastName }} heroes - this is a an array in angular
  • {{hero.name}}
similarly we could have table and ngFor on tr element
27
*ngIf
``` display content based on an expression Content is added or removed from the DOM set *ngIf directive to an expression that evaluates to true or false
you selected {{selectedHero.firstName}}
if selectedHero = null or does not have value then does not show up or undefined if selectedHero has value or truthy ```
28
Class Binding
``` for styles class binding; we could use the dot syntax or class binding syntax [class.active]="isActive" ; class="{classname: expression}"
; if isActive is true then apply active class ``` ```
if isActive is true then apply foo class if isDisabled is true then apply bar class ```
29
Summary of what could be done in component and html
``` {{ model }} -interpolation [ property ] - Bind to a DOM property ( event ) -Bind to an event ngModel -2 way data binding *nglf - Conditional element *ngFor - Loop ```
30
Convert array to json object
{{heroes | json}} heroes = [ { id: 10, name: 'John' }, { id: 20, name: 'Peter' }, { id: 30, name: 'Saint' } ] [ { "id": 10, "name": "John" }, { "id": 20, "name": "Peter" }, { "id": 30, "name": "Saint" } ] ```
  {{heroes | json}}
[ { "id": 10, "name": "John" }, { "id": 20, "name": "Peter" }, { "id": 30, "name": "Saint" } ] Pre - maintains the spacings ```
31
example with *ngFor,*ngIf, model creation, event calling on the selection of list element
import { Component, OnInit } from '@angular/core'; ``` @Component({ selector: 'app-heroes', template: `

heroes works!

``` ```
  • {{hero.name}}
you selected {{selectedValue}}
`, styles: [] }) export class HeroesComponent implements OnInit { heroes = [ { id: 10, name: 'John' }, { id: 20, name: 'Peter' }, { id: 30, name: 'Saint' } ] selectedValue: string; constructor() { } ``` ``` ngOnInit(): void { } ok(selectedValuePassed: any) { this.selectedValue = selectedValuePassed.name; } ``` }
32
Services
To have reusable code in your application and use them in any component that you want May be one service that logs and may be one for error handling
33
@Injectable
``` for angular to know the class as service we use injectable @injectable is a function/decorator; it operates on anything that follows it. this make the class a service @Injectable({providedIn:'root'}) - this is the default value, which say provide it in the root module. it means we are saying that this service is available in the application.if there are multiple modules, we could tell in which module to put it in ``` ``` import {injectable} from '@angular/core' @injectable({providedIn:'root'}) export class HeroService { getHeroes(){ return []; //may be list of Heros } } ```
34
using service in component
``` export class HeroesComponent implements OnInit{ heroes: Hero[]; //array of Hero constructor(private heroService:HeroService) ngOnInit() { this.heroes=this.heroService.getHeroes(); } } Here we are using dependency injection, angular has built into it we do not need to new up the HeroService class. Here we are saying i need HeroService. angular looks into the root and who is provided to it using @Injectable.if there is one that matches the ServiceName, it gives it to you. Then it checks if it already exists,if not it will create a new instance. if it already exists then it gives that instance to us. Service discovery works with the DI system ```
35
Angular Dependency Injection
defining the service in the constructor; angular automatically finds the service and if there is an instance created and uses it; it is singleton it checks who in the root are provided with @injectable; if that matches the HeroService name. if the instance exists, it will give that instance; if the instance does not exist then it creates a new instance Service discovery works with the dependency injection system
36
HTTP
``` serviceClass uses http to get the data it needs. in the service class, we inject httpClient class.this is a class that comes with angular. it gives bunch of stuff like get, headers,Intercept http traffic, change the data that comes back. HttpClient - it is super charged httpfetch. ``` ``` import{HttpClient} from '@angular/common/http'; @Injectable({providedIn:"root"}) export class HeroService { constructor(private http:HttpClient){} getHeros(){ return this.http.get('api/heroes'); we specify the return type here; we are using the get method of HttpClient Class } } we have HttpClient Module in the app.Module.ts: import '@angular/common/http'; ```
37
ngx-logger
https: //www.npmjs.com/package/ngx-logger https: //onthecode.co.uk/angular-logging-made-easy-with-ngx-logger/
38
src/Environments/environment
for prod or dev
39
angular.json
this has file replacements during the production release "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ],
40
The command used to run in production mode is ng serve --configuration=production.
The command used to run in production mode is ng serve --configuration=production.
41
npm install --save
Update npm 5: As of npm 5.0.0, installed modules are added as a dependency by default, so the --save option is no longer needed. The other save options still exist and are listed in the documentation for npm install. Original answer: Before version 5, NPM simply installed a package under node_modules by default. When you were trying to install dependencies for your app/module, you would need to first install them, and then add them (along with the appropriate version number) to the dependencies section of your package.json. The --save option instructed NPM to include the package inside of the dependencies section of your package.json automatically, thus saving you an additional step. In addition, there are the complementary options --save-dev and --save-optional which save the package under devDependencies and optionalDependencies, respectively. This is useful when installing development-only packages, like grunt or your testing library.
42
using ngx-logger for logging
``` in environment.ts: import { NgxLoggerLevel } from 'ngx-logger'; export const environment = { production: false, apiURL: 'https://localhost:44302', logLevel: NgxLoggerLevel.WARN, serverLogLevel: NgxLoggerLevel.OFF, disableConsoleLogging: false }; ``` ``` in environment.prod.ts: import { NgxLoggerLevel } from 'ngx-logger'; export const environment = { production: true, apiURL: '.', logLevel: NgxLoggerLevel.OFF, serverLogLevel: NgxLoggerLevel.ERROR, disableConsoleLogging: true }; ``` package.json "ngx-logger": "^4.1.2", in app.Module.ts: in the server side, it is a post. we could get the data from the body and specifying it as type object LoggerModule.forRoot({ serverLoggingUrl: `${environment.apiURL}api/logs`, level: environment.logLevel, serverLogLevel: environment.serverLogLevel, disableConsoleLogging: environment.disableConsoleLogging }),
43
To run angular app locally with production settings
ng serve --configuration=production.
44
Showing git version info in angular app
in version.js: getting the git info const { gitDescribeSync } = require('git-describe'); const { version } = require('../package.json'); const { resolve, relative } = require('path'); const { writeFileSync } = require('fs-extra'); ``` const gitInfo = gitDescribeSync({ dirtyMark: false, dirtySemver: false }); ``` gitInfo.version = version; const file = resolve(__dirname, '..', 'src', 'environments', 'version.ts'); writeFileSync(file, `// IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN! /* tslint:disable */ export const VERSION = ${JSON.stringify(gitInfo, null, 4)}; /* tslint:enable */ `, { encoding: 'utf-8' }); console.log(`Wrote version info ${gitInfo.raw} to ${relative(resolve(__dirname, '..'), file)}`); ----- in package.json: specify the script to run { scripts: { "postinstall": "node version.js" } } Now anytime we run npm i our app version will get updated for us. This script will create a file in our environments folder called version.ts. It will look something like this: ``` // IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN! /* tslint:disable */ export const VERSION = { "dirty": true, "raw": "30374842-dirty", "hash": "30374842", "distance": null, "tag": null, "semver": null, "suffix": "30374842-dirty", "semverString": null, "version": "0.0.1" }; /* tslint:enable */ ``` We can now import that file in any component like: import { VERSION } from 'environments/version'; ``` @Component({ selector: 'app-footer', template: ` Version: {{version.version}} ` }) export class FooterComponent { version = VERSION; } https://medium.com/@amcdnl/version-stamping-your-app-with-the-angular-cli-d563284bb94d ```
45
Tree shaking
Tree shaking is a term commonly used within a JavaScript context to describe the removal of dead code. Dead code is any code that will never be executed. It may be some condition, loop or any file which was simply created but wasn't used in your project. It relies on the import and export statements in ES2015 to detect if code modules are exported and imported for use between JavaScript files. In modern JavaScript applications, we use module bundlers (e.g., webpack or Rollup) to automatically remove dead code when bundling multiple JavaScript files into single files. This is important for preparing code that is production ready, for example with clean structures and minimal file size.
46
Routing and navigation
The Angular Router enables navigation from one view to the next as users perform application tasks. The Angular Router ("the router") borrows from this model. It can interpret a browser URL as an instruction to navigate to a client-generated view. It can pass optional parameters along to the supporting view component that help it decide what specific content to present. You can bind the router to links on a page and it will navigate to the appropriate application view when the user clicks a link. You can navigate imperatively when the user clicks a button, selects from a drop box, or in response to some other stimulus from any source. And the router logs activity in the browser's history journal so the back and forward buttons work as well.
47
The browser is a familiar model of application navigation:
Enter a URL in the address bar and the browser navigates to a corresponding page. Click links on the page and the browser navigates to a new page. Click the browser's back and forward buttons and the browser navigates backward and forward through the history of pages you've seen.
48
routing - index.html path
Most routing applications should add a element to the index.html as the first child in the tag to tell the router how to compose navigation URLs. If the app folder is the application root, as it is for the sample application, set the href value exactly as shown here. Phoweb src/index.html (base-href)
49
Router imports
The Angular Router is an optional service that presents a particular component view for a given URL. It is not part of the Angular core. It is in its own library package, @angular/router. Import what you need from it as you would from any other Angular package. src/app/app.module.ts (import) import { RouterModule, Routes } from '@angular/router';
50
Router Configuration
A routed Angular application has one singleton instance of the Router service. When the browser's URL changes, that router looks for a corresponding Route from which it can determine the component to display. A router has no routes until you configure it. The following example creates five route definitions, configures the router via the RouterModule.forRoot() method, and adds the result to the AppModule's imports array. src/app/app.module.ts (excerpt) ``` const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes List' } }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; ``` ``` @NgModule({ imports: [ RouterModule.forRoot( appRoutes, { enableTracing: true } // ```
51
RouterModule.forRoot()
The appRoutes array of routes describes how to navigate. Pass it to the RouterModule.forRoot() method in the module imports to configure the router. Each Route maps a URL path to a component. There are no leading slashes in the path. The router parses and builds the final URL for you, allowing you to use both relative and absolute paths when navigating between application views.
52
``` USING ID: const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes List' } }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; ```
The :id in the second route is a token for a route parameter. In a URL such as /hero/42, "42" is the value of the id parameter. The corresponding HeroDetailComponent will use that value to find and present the hero whose id is 42. You'll learn more about route parameters later in this guide.
53
``` USING data propery: const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes List' } }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; ```
The data property in the third route is a place to store arbitrary data associated with this specific route. The data property is accessible within each activated route. Use it to store items such as page titles, breadcrumb text, and other read-only, static data. You'll use the resolve guard to retrieve dynamic data later in the guide.
54
``` USING empty path: const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes List' } }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; ```
The empty path in the fourth route represents the default path for the application, the place to go when the path in the URL is empty, as it typically is at the start. This default route redirects to the route for the /heroes URL and, therefore, will display the HeroesListComponent. here when are saying redirect; we are also saying pathMatch:'ful'l
55
``` USING **: const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes List' } }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; ```
The ** path in the last route is a wildcard. The router will select this route if the requested URL doesn't match any paths for routes defined earlier in the configuration. This is useful for displaying a "404 - Not Found" page or redirecting to another route.
56
``` Order for the routing: const appRoutes: Routes = [ { path: 'crisis-center', component: CrisisListComponent }, { path: 'hero/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroListComponent, data: { title: 'Heroes List' } }, { path: '', redirectTo: '/heroes', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; ```
The order of the routes in the configuration matters and this is by design. The router uses a first-match wins strategy when matching routes, so more specific routes should be placed above less specific routes. In the configuration above, routes with a static path are listed first, followed by an empty path route, that matches the default route. The wildcard route comes last because it matches every URL and should be selected only if no other routes are matched first.
57
Tracing in routing
If you need to see what events are happening during the navigation lifecycle, there is the enableTracing option as part of the router's default configuration. This outputs each router event that took place during each navigation lifecycle to the browser console. This should only be used for debugging purposes. You set the enableTracing: true option in the object passed as the second argument to the RouterModule.forRoot() method. ``` @NgModule({ imports: [ RouterModule.forRoot( appRoutes, { enableTracing: true } // ```
58
Router outlet
The RouterOutlet is a directive from the router library that is used like a component. It acts as a placeholder that marks the spot in the template where the router should display the components for that outlet. Given the configuration above, when the browser URL for this application becomes /heroes, the router matches that URL to the route path /heroes and displays the HeroListComponent as a sibling element to the RouterOutlet that you've placed in the host component's template. in general case, it is placed in app.component.html - the root component
59
Directive in detail
This article focuses on Angular directives — what are they, how to use them, and to build our own. Directives are perhaps the most important bit of an Angular application, and if we think about it, the most-used Angular unit, the component, is actually a directive. An Angular component isn’t more than a directive with a template. When we say that components are the building blocks of Angular applications, we’re actually saying that directives are the building blocks of Angular applications. ``` Basic overview At the core, a directive is a function that executes whenever the Angular compiler finds it in the DOM. Angular directives are used to extend the power of the HTML by giving it new syntax. Each directive has a name — either one from the Angular predefined like ng-repeat, or a custom one which can be called anything. And each directive determines where it can be used: in an element, attribute, class or comment. ``` By default, from Angular versions 2 and onward, Angular directives are separated into three different types: Components As we saw earlier, components are just directives with templates. Under the hood, they use the directive API and give us a cleaner way to define them. The other two directive types don’t have templates. Instead, they’re specifically tailored to DOM manipulation. Attribute directives Attribute directives manipulate the DOM by changing its behavior and appearance. We use attribute directives to apply conditional style to elements, show or hide elements or dynamically change the behavior of a component according to a changing property. Structural directives These are specifically tailored to create and destroy DOM elements. Some attribute directives — like hidden, which shows or hides an element — basically maintain the DOM as it is. But the structural Angular directives are much less DOM friendly, as they add or completely remove elements from the DOM. So, when using these, we have to be extra careful, since we’re actually changing the HTML structure.
60
Router links
Now you have routes configured and a place to render them, but how do you navigate? The URL could arrive directly from the browser address bar. But most of the time you navigate as a result of some user action such as the click of an anchor tag. Consider the following template: src/app/app.component.html

Angular Router

Crisis Center Heroes The RouterLink directives on the anchor tags give the router control over those elements. The navigation paths are fixed, so you can assign a string to the routerLink (a "one-time" binding). Had the navigation path been more dynamic, you could have bound to a template expression that returned an array of route link parameters (the link parameters array). The router resolves that array into a complete URL.
61
Active router links
The RouterLinkActive directive toggles css classes for active RouterLink bindings based on the current RouterState. On each anchor tag, you see a property binding to the RouterLinkActive directive that look like routerLinkActive="...". The template expression to the right of the equals (=) contains a space-delimited string of CSS classes that the Router will add when this link is active (and remove when the link is inactive). You set the RouterLinkActive directive to a string of classes such as [routerLinkActive]="'active fluffy'" or bind it to a component property that returns such a string. Active route links cascade down through each level of the route tree, so parent and child router links can be active at the same time. To override this behavior, you can bind to the [routerLinkActiveOptions] input binding with the { exact: true } expression. By using { exact: true }, a given RouterLink will only be active if its URL is an exact match to the current URL.
62
using $ may be string interpolation in angular
this.logger.log(`${this.route.outlet} is the router outlet`);
63
Observables
Observables provide support for passing messages between publishers and subscribers in your application. Observables offer significant benefits over other techniques for event handling, asynchronous programming, and handling multiple values. Observables are declarative—that is, you define a function for publishing values, but it is not executed until a consumer subscribes to it. The subscribed consumer then receives notifications until the function completes, or until they unsubscribe. An observable can deliver multiple values of any type—literals, messages, or events, depending on the context. The API for receiving values is the same whether the values are delivered synchronously or asynchronously. Because setup and teardown logic are both handled by the observable, your application code only needs to worry about subscribing to consume values, and when done, unsubscribing. Whether the stream was keystrokes, an HTTP response, or an interval timer, the interface for listening to values and stopping listening is the same. Because of these advantages, observables are used extensively within Angular, and are recommended for app development as well.
64
Observable Basic usage and terms
As a publisher, you create an Observable instance that defines a subscriber function. This is the function that is executed when a consumer calls the subscribe() method. The subscriber function defines how to obtain or generate values or messages to be published. To execute the observable you have created and begin receiving notifications, you call its subscribe() method, passing an observer. This is a JavaScript object that defines the handlers for the notifications you receive. The subscribe() call returns a Subscription object that has an unsubscribe() method, which you call to stop receiving notifications. Here's an example that demonstrates the basic usage model by showing how an observable could be used to provide geolocation updates.
65
Observable example
``` // Create an Observable that will start listening to geolocation updates // when a consumer subscribes. const locations = new Observable((observer) => { let watchId: number; ``` // Simple geolocation API check provides values to publish if ('geolocation' in navigator) { watchId = navigator.geolocation.watchPosition((position: Position) => { observer.next(position); }, (error: PositionError) => { observer.error(error); }); } else { observer.error('Geolocation not available'); } ``` // When the consumer unsubscribes, clean up data ready for next subscription. return { unsubscribe() { navigator.geolocation.clearWatch(watchId); } }; }); ``` ``` // Call subscribe() to start listening for updates. const locationsSubscription = locations.subscribe({ next(position) { console.log('Current Position: ', position); }, error(msg) { console.log('Error Getting Location: ', msg); } }); ``` ``` // Stop listening for location after 10 seconds setTimeout(() => { locationsSubscription.unsubscribe(); }, 10000); ```
66
Defining observers
A handler for receiving observable notifications implements the Observer interface. It is an object that defines callback methods to handle the three types of notifications that an observable can send: NOTIFICATION TYPE DESCRIPTION next: Required. A handler for each delivered value. Called zero or more times after execution starts. error: Optional. A handler for an error notification. An error halts execution of the observable instance. complete: Optional. A handler for the execution-complete notification. Delayed values can continue to be delivered to the next handler after execution is complete. An observer object can define any combination of these handlers. If you don't supply a handler for a notification type, the observer ignores notifications of that type.
67
Subscribing
An Observable instance begins publishing values only when someone subscribes to it. You subscribe by calling the subscribe() method of the instance, passing an observer object to receive the notifications.
68
Rxjs observables
In order to show how subscribing works, we need to create a new observable. There is a constructor that you use to create new instances, but for illustration, we can use some methods from the RxJS library that create simple observables of frequently used types: of(...items)—Returns an Observable instance that synchronously delivers the values provided as arguments. from(iterable)—Converts its argument to an Observable instance. This method is commonly used to convert an array to an observable.
69
example of creating and subscribing to a simple observable, with an observer that logs the received message to the console:
Subscribe using observer" content_copy // Create simple observable that emits three values const myObservable = of(1, 2, 3); // Create observer object const myObserver = { next: x => console.log('Observer got a next value: ' + x), error: err => console.error('Observer got an error: ' + err), complete: () => console.log('Observer got a complete notification'), }; ``` // Execute with the observer object myObservable.subscribe(myObserver); // Logs: // Observer got a next value: 1 // Observer got a next value: 2 // Observer got a next value: 3 // Observer got a complete notification Alternatively, the subscribe() method can accept callback function definitions in line, for next, error, and complete handlers. For example, the following subscribe() call is the same as the one that specifies the predefined observer: ``` Subscribe with positional arguments: content_copy myObservable.subscribe( x => console.log('Observer got a next value: ' + x), err => console.error('Observer got an error: ' + err), () => console.log('Observer got a complete notification') ); In either case, a next handler is required. The error and complete handlers are optional. Note that a next() function could receive, for instance, message strings, or event objects, numeric values, or structures, depending on context. As a general term, we refer to data published by an observable as a stream. Any type of value can be represented with an observable, and the values are published as a stream.
70
observable stream
Note that a next() function could receive, for instance, message strings, or event objects, numeric values, or structures, depending on context. As a general term, we refer to data published by an observable as a stream. Any type of value can be represented with an observable, and the values are published as a stream
71
subscriber function
Observables are declarative—that is, you define a function for publishing values, but it is not executed until a consumer subscribes to it. The subscribed consumer then receives notifications until the function completes, or until they unsubscribe.
72
JavaScript Promises Versus RxJS Observables
https://coryrylan.com/blog/javascript-promises-versus-rxjs-observables
73
Create observable with constructor
For example, to create an observable equivalent to the of(1, 2, 3) above, you could do something like this: // This function runs when subscribe() is called function sequenceSubscriber(observer) { // synchronously deliver 1, 2, and 3, then complete observer.next(1); observer.next(2); observer.next(3); observer.complete(); ``` // unsubscribe function doesn't need to do anything in this // because values are delivered synchronously return {unsubscribe() {}}; } ``` ``` // Create a new Observable that will deliver the above sequence const sequence = new Observable(sequenceSubscriber); ``` ``` // execute the Observable and print the result of each notification sequence.subscribe({ next(num) { console.log(num); }, complete() { console.log('Finished sequence'); } }); ``` ``` // Logs: // 1 // 2 // 3 // Finished sequence ```
74
Create with custom fromEvent function -Not Clear
``` Create with custom fromEvent function content_copy function fromEvent(target, eventName) { return new Observable((observer) => { const handler = (e) => observer.next(e); ``` ``` // Add the event handler to the target target.addEventListener(eventName, handler); ``` ``` return () => { // Detach the event handler from the target target.removeEventListener(eventName, handler); }; }); } Now you can use this function to create an observable that publishes keydown events: ``` ``` Use custom fromEvent function content_copy const ESC_KEY = 27; const nameInput = document.getElementById('name') as HTMLInputElement; ``` ``` const subscription = fromEvent(nameInput, 'keydown') .subscribe((e: KeyboardEvent) => { if (e.keyCode === ESC_KEY) { nameInput.value = ''; } }); ```
75
Multicasting in observables - Not Clear
A typical observable creates a new, independent execution for each subscribed observer. When an observer subscribes, the observable wires up an event handler and delivers values to that observer. When a second observer subscribes, the observable then wires up a new event handler and delivers values to that second observer in a separate execution. Sometimes, instead of starting an independent execution for each subscriber, you want each subscription to get the same values—even if values have already started emitting. This might be the case with something like an observable of clicks on the document object. Multicasting is the practice of broadcasting to a list of multiple subscribers in a single execution. With a multicasting observable, you don't register multiple listeners on the document, but instead re-use the first listener and send values out to each subscriber. When creating an observable you should determine how you want that observable to be used and whether or not you want to multicast its values. Let’s look at an example that counts from 1 to 3, with a one-second delay after each number emitted. ``` Create a delayed sequence content_copy function sequenceSubscriber(observer) { const seq = [1, 2, 3]; let timeoutId; ``` ``` // Will run through an array of numbers, emitting one value // per second until it gets to the end of the array. function doSequence(arr, idx) { timeoutId = setTimeout(() => { observer.next(arr[idx]); if (idx === arr.length - 1) { observer.complete(); } else { doSequence(arr, ++idx); } }, 1000); } ``` doSequence(seq, 0); ``` // Unsubscribe should clear the timeout to stop execution return {unsubscribe() { clearTimeout(timeoutId); }}; } ``` ``` // Create a new Observable that will deliver the above sequence const sequence = new Observable(sequenceSubscriber); ``` sequence.subscribe({ next(num) { console.log(num); }, complete() { console.log('Finished sequence'); } }); ``` // Logs: // (at 1 second): 1 // (at 2 seconds): 2 // (at 3 seconds): 3 // (at 3 seconds): Finished sequence Notice that if you subscribe twice, there will be two separate streams, each emitting values every second. It looks something like this: ``` Two subscriptions content_copy // Subscribe starts the clock, and will emit after 1 second sequence.subscribe({ next(num) { console.log('1st subscribe: ' + num); }, complete() { console.log('1st sequence finished.'); } }); ``` // After 1/2 second, subscribe again. setTimeout(() => { sequence.subscribe({ next(num) { console.log('2nd subscribe: ' + num); }, complete() { console.log('2nd sequence finished.'); } }); }, 500); ``` ``` // Logs: // (at 1 second): 1st subscribe: 1 // (at 1.5 seconds): 2nd subscribe: 1 // (at 2 seconds): 1st subscribe: 2 // (at 2.5 seconds): 2nd subscribe: 2 // (at 3 seconds): 1st subscribe: 3 // (at 3 seconds): 1st sequence finished // (at 3.5 seconds): 2nd subscribe: 3 // (at 3.5 seconds): 2nd sequence finished Changing the observable to be multicasting could look something like this: ``` Create a multicast subscriber content_copy function multicastSequenceSubscriber() { const seq = [1, 2, 3]; // Keep track of each observer (one for every active subscription) const observers = []; // Still a single timeoutId because there will only ever be one // set of values being generated, multicasted to each subscriber let timeoutId; ``` // Return the subscriber function (runs when subscribe() // function is invoked) return (observer) => { observers.push(observer); // When this is the first subscription, start the sequence if (observers.length === 1) { timeoutId = doSequence({ next(val) { // Iterate through observers and notify all subscriptions observers.forEach(obs => obs.next(val)); }, complete() { // Notify all complete callbacks observers.slice(0).forEach(obs => obs.complete()); } }, seq, 0); } ``` ``` return { unsubscribe() { // Remove from the observers array so it's no longer notified observers.splice(observers.indexOf(observer), 1); // If there's no more listeners, do cleanup if (observers.length === 0) { clearTimeout(timeoutId); } } }; }; } ``` ``` // Run through an array of numbers, emitting one value // per second until it gets to the end of the array. function doSequence(observer, arr, idx) { return setTimeout(() => { observer.next(arr[idx]); if (idx === arr.length - 1) { observer.complete(); } else { doSequence(observer, arr, ++idx); } }, 1000); } ``` ``` // Create a new Observable that will deliver the above sequence const multicastSequence = new Observable(multicastSequenceSubscriber()); ``` ``` // Subscribe starts the clock, and begins to emit after 1 second multicastSequence.subscribe({ next(num) { console.log('1st subscribe: ' + num); }, complete() { console.log('1st sequence finished.'); } }); ``` ``` // After 1 1/2 seconds, subscribe again (should "miss" the first value). setTimeout(() => { multicastSequence.subscribe({ next(num) { console.log('2nd subscribe: ' + num); }, complete() { console.log('2nd sequence finished.'); } }); }, 1500); ``` ``` // Logs: // (at 1 second): 1st subscribe: 1 // (at 2 seconds): 1st subscribe: 2 // (at 2 seconds): 2nd subscribe: 2 // (at 3 seconds): 1st subscribe: 3 // (at 3 seconds): 1st sequence finished // (at 3 seconds): 2nd subscribe: 3 // (at 3 seconds): 2nd sequence finished Multicasting observables take a bit more setup, but they can be useful for certain applications. Later we will look at tools that simplify the process of multicasting, allowing you to take any observable and make it multicasting. ```
76
observables Error handling
Because observables produce values asynchronously, try/catch will not effectively catch errors. Instead, you handle errors by specifying an error callback on the observer. Producing an error also causes the observable to clean up subscriptions and stop producing values. An observable can either produce values (calling the next callback), or it can complete, calling either the complete or error callback. myObservable.subscribe({ next(num) { console.log('Next num: ' + num)}, error(err) { console.log('Received an errror: ' + err)} }); https://angular.io/guide/observables
77
Router state
After the end of each successful navigation lifecycle, the router builds a tree of ActivatedRoute objects that make up the current state of the router. You can access the current RouterState from anywhere in the application using the Router service and the routerState property. Each ActivatedRoute in the RouterState provides methods to traverse up and down the route tree to get information from parent, child and sibling routes.
78
Activated route
The route path and parameters are available through an injected router service called the ActivatedRoute. It has a great deal of useful information including:
79
Activated route Property
Property Description url An Observable of the route path(s), represented as an array of strings for each part of the route path. data An Observable that contains the data object provided for the route. Also contains any resolved values from the resolve guard. paramMap An Observable that contains a map of the required and optional parameters specific to the route. The map supports retrieving single and multiple values from the same parameter. queryParamMap An Observable that contains a map of the query parameters available to all routes. The map supports retrieving single and multiple values from the query parameter. fragment An Observable of the URL fragment available to all routes. outlet The name of the RouterOutlet used to render the route. For an unnamed outlet, the outlet name is primary. routeConfig The route configuration used for the route that contains the origin path. parent The route's parent ActivatedRoute when this route is a child route. firstChild Contains the first ActivatedRoute in the list of this route's child routes. children Contains all the child routes activated under the current route. Two older properties are still available. They are less capable than their replacements, discouraged, and may be deprecated in a future Angular version. params—An Observable that contains the required and optional parameters specific to the route. Use paramMap instead. queryParams—An Observable that contains the query parameters available to all routes. Use queryParamMap instead.
80
Router events
Router events During each navigation, the Router emits navigation events through the Router.events property. These events range from when the navigation starts and ends to many points in between. The full list of navigation events is displayed in the table below. Router Event Description NavigationStart An event triggered when navigation starts. RouteConfigLoadStart An event triggered before the Router lazy loads a route configuration. RouteConfigLoadEnd An event triggered after a route has been lazy loaded. RoutesRecognized An event triggered when the Router parses the URL and the routes are recognized. GuardsCheckStart An event triggered when the Router begins the Guards phase of routing. ChildActivationStart An event triggered when the Router begins activating a route's children. ActivationStart An event triggered when the Router begins activating a route. GuardsCheckEnd An event triggered when the Router finishes the Guards phase of routing successfully. ResolveStart An event triggered when the Router begins the Resolve phase of routing. ResolveEnd An event triggered when the Router finishes the Resolve phase of routing successfuly. ChildActivationEnd An event triggered when the Router finishes activating a route's children. ActivationEnd An event triggered when the Router finishes activating a route. NavigationEnd An event triggered when navigation ends successfully. NavigationCancel An event triggered when navigation is canceled. This can happen when a Route Guard returns false during navigation, or redirects by returning a UrlTree. NavigationError An event triggered when navigation fails due to an unexpected error. Scroll An event that represents a scrolling event. These events are logged to the console when the enableTracing option is enabled also. For an example of filtering router navigation events, visit the router section of the Observables in Angular guide.
81
Router Summary
Summary The application has a configured router. The shell component has a RouterOutlet where it can display views produced by the router. It has RouterLinks that users can click to navigate via the router. Here are the key Router terms and their meanings: Router Part Meaning Router Displays the application component for the active URL. Manages navigation from one component to the next. RouterModule A separate NgModule that provides the necessary service providers and directives for navigating through application views. Routes Defines an array of Routes, each mapping a URL path to a component. Route Defines how the router should navigate to a component based on a URL pattern. Most routes consist of a path and a component type. RouterOutlet The directive () that marks where the router displays a view. RouterLink The directive for binding a clickable HTML element to a route. Clicking an element with a routerLink directive that is bound to a string or a link parameters array triggers a navigation. RouterLinkActive The directive for adding/removing classes from an HTML element when an associated routerLink contained on or inside the element becomes active/inactive. ActivatedRoute A service that is provided to each route component that contains route specific information such as route parameters, static data, resolve data, global query params, and the global fragment. RouterState The current state of the router including a tree of the currently activated routes together with convenience methods for traversing the route tree. Link parameters array An array that the router interprets as a routing instruction. You can bind that array to a RouterLink or pass the array as an argument to the Router.navigate method. Routing component An Angular component with a RouterOutlet that displays views based on router navigations. https://angular.io/guide/router#router-outlet
82
Property binding [property]
Use property binding to set properties of target elements or directive @Input() decorators. For an example demonstrating all of the points in this section, see the property binding example / download example. One-way in Property binding flows a value in one direction, from a component's property into a target element property. You can't use property binding to read or pull values out of target elements. Similarly, you cannot use property binding to call a method on the target element. If the element raises events, you can listen to them with an event binding. If you must read a target element property or call one of its methods, see the API reference for ViewChild and ContentChild. Examples The most common property binding sets an element property to a component property value. An example is binding the src property of an image element to a component's itemImageUrl property: src/app/app.component.html content_copy Here's an example of binding to the colSpan property. Notice that it's not colspan, which is the attribute, spelled with a lowercase s. src/app/app.component.html content_copy Span 2 columns For more details, see the MDN HTMLTableCellElement documentation. Another example is disabling a button when the component says that it isUnchanged: src/app/app.component.html content_copy Disabled Button Another is setting a property of a directive: src/app/app.component.html content_copy

[ngClass] binding to the classes property making this blue

Yet another is setting the model property of a custom component—a great way for parent and child components to communicate: src/app/app.component.html content_copy
83
workspace
You develop applications in the context of an Angular workspace. A workspace contains the files for one or more projects. A project is the set of files that comprise a standalone application or a shareable library. The Angular CLI ng new command creates a workspace. content_copy ng new When you run this command, the CLI installs the necessary Angular npm packages and other dependencies in a new workspace, with a root-level application named my-project. The workspace root folder contains various support and configuration files, and a README file with generated descriptive text that you can customize. By default, ng new creates an initial skeleton application at the root level of the workspace, along with its end-to-end tests. The skeleton is for a simple Welcome application that is ready to run and easy to modify. The root-level application has the same name as the workspace, and the source files reside in the src/ subfolder of the workspace. This default behavior is suitable for a typical "multi-repo" development style where each application resides in its own workspace. Beginners and intermediate users are encouraged to use ng new to create a separate workspace for each application. Angular also supports workspaces with multiple projects. This type of development environment is suitable for advanced users who are developing shareable libraries, and for enterprises that use a "monorepo" development style, with a single repository and global configuration for all Angular projects. To set up a monorepo workspace, you should skip the creating the root application. See Setting up for a multi-project workspace below.
84
WORKSPACE CONFIG FILES .editorconfig
Configuration for code editors. See EditorConfig.
85
WORKSPACE CONFIG FILES .gitignore
Specifies intentionally untracked files that Git should ignore.
86
WORKSPACE CONFIG FILES README.md
Introductory documentation for the root app.
87
WORKSPACE CONFIG FILES angular.json
CLI configuration defaults for all projects in the workspace, including configuration options for build, serve, and test tools that the CLI uses, such as TSLint, Karma, and Protractor. For details, see Angular Workspace Configuration.
88
WORKSPACE CONFIG FILES package.json
Configures npm package dependencies that are available to all projects in the workspace. See npm documentation for the specific format and contents of this file.
89
WORKSPACE CONFIG FILES package-lock.json *
Provides version information for all packages installed into node_modules by the npm client. See npm documentation for details. If you use the yarn client, this file will be yarn.lock instead.
90
WORKSPACE CONFIG FILES src/
Source files for the root-level application project.
91
WORKSPACE CONFIG FILES node_modules/
Provides npm packages to the entire workspace. Workspace-wide node_modules dependencies are visible to all projects.
92
WORKSPACE CONFIG FILES tsconfig.json
Default TypeScript configuration for projects in the workspace.
93
WORKSPACE CONFIG FILES tslint.json
Default TSLint configuration for projects in the workspace.
94
Application project files
By default, the CLI command ng new my-app creates a workspace folder named "my-app" and generates a new application skeleton in a src/ folder at the top level of the workspace. A newly generated application contains source files for a root module, with a root component and template. When the workspace file structure is in place, you can use the ng generate command on the command line to add functionality and data to the application. This initial root-level application is the default app for CLI commands (unless you change the default after creating additional apps). Besides using the CLI on the command line, you can also use an interactive development environment like Angular Console, or manipulate files directly in the app's source folder and configuration files. For a single-application workspace, the src/ subfolder of the workspace contains the source files (application logic, data, and assets) for the root application. For a multi-project workspace, additional projects in the projects/ folder contain a project-name/src/ subfolder with the same structure.
95
Application source files
Files at the top level of src/ support testing and running your application. Subfolders contain the application source and application-specific configuration.
96
APP SUPPORT FILES app/
Contains the component files in which your application logic and data are defined. See details below.
97
APP SUPPORT FILES assets/
Contains image and other asset files to be copied as-is when you build your application.
98
APP SUPPORT FILES environments/
Contains build configuration options for particular target environments. By default there is an unnamed standard development environment and a production ("prod") environment. You can define additional target environment configurations. we have created jsonserver.ts environment
99
APP SUPPORT FILES favicon.ico
An icon to use for this application in the bookmark bar. by default it is A for angular apps
100
APP SUPPORT FILES index.html
The main HTML page that is served when someone visits your site. The CLI automatically adds all JavaScript and CSS files when building your app, so you typically don't need to add any or tags here manually. it has which loads the application
101
APP SUPPORT FILES main.ts
The main entry point for your application. Compiles the application with the JIT compiler and bootstraps the application's root module (AppModule) to run in the browser. You can also use the AOT compiler without changing any code by appending the --aot flag to the CLI build and serve commands.
102
APP SUPPORT FILES polyfills.ts
Provides polyfill scripts for browser support. In web development, a polyfill is code that implements a feature on web browsers that do not support the feature. Most often, it refers to a JavaScript library that implements an HTML5 web standard, either an established standard (supported by some browsers) on older browsers, or a proposed standard (not supported by any browsers) on existing browsers. Formally, "a polyfill is a shim for a browser API".[1] Polyfills allow web developers to use an API regardless of whether or not it is supported by a browser, and usually with minimal overhead. Typically they first check if a browser supports an API, and use it if available, otherwise using their own implementation.[1][2] Polyfills themselves use other, more supported features, and thus different polyfills may be needed for different browsers. The term is also used as a verb: polyfilling is providing a polyfill for a feature.
103
APP SUPPORT FILES styles.sass
Lists CSS files that supply styles for a project. The extension reflects the style preprocessor you have configured for the project.
104
APP SUPPORT FILES test.ts
The main entry point for your unit tests, with some Angular-specific configuration. You don't typically need to edit this file.
105
Ahead-of-time (AOT) compilation
An Angular application consists mainly of components and their HTML templates. Because the components and templates provided by Angular cannot be understood by the browser directly, Angular applications require a compilation process before they can run in a browser. The Angular ahead-of-time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase before the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser.
106
Advantages of AOT compiler
Here are some reasons you might want to use AOT. Faster rendering With AOT, the browser downloads a pre-compiled version of the application. The browser loads executable code so it can render the application immediately, without waiting to compile the app first. Fewer asynchronous requests The compiler inlines external HTML templates and CSS style sheets within the application JavaScript, eliminating separate ajax requests for those source files. Smaller Angular framework download size There's no need to download the Angular compiler if the app is already compiled. The compiler is roughly half of Angular itself, so omitting it dramatically reduces the application payload. Detect template errors earlier The AOT compiler detects and reports template binding errors during the build step before users can see them. Better security AOT compiles HTML templates and components into JavaScript files long before they are served to the client. With no templates to read and no risky client-side HTML or JavaScript evaluation, there are fewer opportunities for injection attacks.
107
Choosing a compiler
Angular offers two ways to compile your application: Just-in-Time (JIT), which compiles your app in the browser at runtime. Ahead-of-Time (AOT), which compiles your app at build time. JIT compilation is the default when you run the ng build (build only) or ng serve (build and serve locally) CLI commands: content_copy ng build ng serve For AOT compilation, include the --aot option with the ng build or ng serve command: content_copy ng build --aot ng serve --aot The ng build command with the --prod meta-flag (ng build --prod) compiles with AOT by default.
108
src/ folder, the app/ folder
Inside the src/ folder, the app/ folder contains your project's logic and data. Angular components, templates, and styles go here.
109
SRC/APP/ FILES app/app.component.ts
Defines the logic for the app's root component, named AppComponent. The view associated with this root component becomes the root of the view hierarchy as you add components and services to your application.
110
SRC/APP/ FILES app/app.component.html
Defines the HTML template associated with the root AppComponent.
111
SRC/APP/ FILES app/app.component.css
Defines the base CSS stylesheet for the root AppComponent.
112
SRC/APP/ FILES app/app.component.spec.ts
Defines a unit test for the root AppComponent
113
SRC/APP/ FILES app/app.module.ts
Defines the root module, named AppModule, that tells Angular how to assemble the application. Initially declares only the AppComponent. As you add more components to the app, they must be declared here.
114
Application configuration files
The application-specific configuration files for the root application reside at the workspace root level. For a multi-project workspace, project-specific configuration files are in the project root, under projects/project-name/. Project-specific TypeScript configuration files inherit from the workspace-wide tsconfig.json, and project-specific TSLint configuration files inherit from the workspace-wide tslint.json.
115
APPLICATION-SPECIFIC CONFIG FILES browserslist
Configures sharing of target browsers and Node.js versions among various front-end tools. See Browserslist on GitHub for more information.
116
APPLICATION-SPECIFIC CONFIG FILES karma.conf.js
Application-specific Karma configuration.
117
APPLICATION-SPECIFIC CONFIG FILES tsconfig.app.json
Application-specific TypeScript configuration, including TypeScript and Angular template compiler options. See TypeScript Configuration and Angular Compiler Options.
118
APPLICATION-SPECIFIC CONFIG FILES tsconfig.spec.json
TypeScript configuration for the application tests. See TypeScript Configuration.
119
APPLICATION-SPECIFIC CONFIG FILES tslint.json
Application-specific TSLint configuration.
120
End-to-end test files
An e2e/ folder at the top level contains source files for a set of end-to-end tests that correspond to the root-level application, along with test-specific configuration files. For a multi-project workspace, application-specific end-to-end tests are in the project root, under projects/project-name/e2e/. content_copy e2e/ src/ (end-to-end tests for my-app) app.e2e-spec.ts app.po.ts protractor.conf.js (test-tool config) tsconfig.json (TypeScript config inherits from workspace)
121
Multiple projects
A multi-project workspace is suitable for an enterprise that uses a single repository and global configuration for all Angular projects (the "monorepo" model). A multi-project workspace also supports library development. Setting up for a multi-project workspace If you intend to have multiple projects in a workspace, you can skip the initial application generation when you create the workspace, and give the workspace a unique name. The following command creates a workspace with all of the workspace-wide configuration files, but no root-level application. content_copy ng new my-workspace --createApplication="false" You can then generate apps and libraries with names that are unique within the workspace. content_copy cd my-workspace ng generate application my-first-app
122
Multiple project file structure
The first explicitly generated application goes into the projects/ folder along with all other projects in the workspace. Newly generated libraries are also added under projects/. When you create projects this way, the file structure of the workspace is entirely consistent with the structure of the workspace configuration file, angular.json. content_copy my-workspace/ ... (workspace-wide config files) projects/ (generated applications and libraries) my-first-app/ --(an explicitly generated application) ... --(application-specific config) e2e/ ----(corresponding e2e tests) src/ ----(e2e tests source) ... ----(e2e-specific config) src/ --(source and support files for application) my-lib/ --(a generated library) ... --(library-specific config) src/ --source and support files for library)
123
Library project files
When you generate a library using the CLI (with a command such as ng generate library my-lib), the generated files go into the projects/ folder of the workspace. For more information about creating your own libraries, see Creating Libraries. Libraries (unlike applications and their associated e2e projects) have their own package.json configuration files. Under the projects/ folder, the my-lib folder contains your library code. LIBRARY SOURCE FILES PURPOSE src/lib Contains your library project's logic and data. Like an application project, a library project can contain components, services, modules, directives, and pipes. src/test.ts The main entry point for your unit tests, with some library-specific configuration. You don't typically need to edit this file. src/public-api.ts Specifies all files that are exported from your library. karma.conf.js Library-specific Karma configuration. ng-package.json Configuration file used by ng-packagr for building your library. package.json Configures npm package dependencies that are required for this library. tsconfig.lib.json Library-specific TypeScript configuration, including TypeScript and Angular template compiler options. See TypeScript Configuration. tsconfig.spec.json TypeScript configuration for the library tests. See TypeScript Configuration. tslint.json Library-specific TSLint configuration.
124
ng-template this will not show up
Let's get started learning ng-template with an example. Here we are defining two tab buttons of a tab component (more on this later): @Component({ selector: 'app-root', template: ` {{loginText}} {{signUpText}} ``` `}) export class AppComponent { loginText = 'Login'; signUpText = 'Sign Up'; lessons = ['Lesson 1', 'Lessons 2']; ``` login() { console.log('Login'); } signUp() { console.log('Sign Up'); } } view raw01.ts hosted with ❤ by GitHub The first thing that you will notice about ng-template If you try the example above, you might be surprised to find out that this example does not render anything to the screen! This is normal and it's the expected behavior. This is because with the ng-template tag we are simply defining a template, but we are not using it yet.
125
The ng-template directive and ngIf
You probably came across ng-template for the first time while implementing an if/else scenario such as for example this one:
...
Loading...
view raw02.ts hosted with ❤ by GitHub This is a very common use of the ngIf/else functionality: we display an alternative loading template while waiting for the data to arrive from the backend. As we can see, the else clause is pointing to a template, which has the name loading. The name was assigned to it via a template reference, using the #loading syntax. But besides that else template, the use of ngIf also creates a second implicit ng-template! Let's have a look at what is happening under the hood:
...
Loading...
view raw03.ts hosted with ❤ by GitHub This is what happens internally as Angular desugars the more concise *ngIf structural directive syntax. Let's break down what happened during the desugaring: the element onto which the structural directive ngIf was applied has been moved into an ng-template The expression of *ngIf has been split up and applied to two separate directives, using the [ngIf] and [ngIfElse] template input variable syntax And this is just one example, of a particular case with ngIf. But with ngFor and ngSwitch a similar process also occurs. These directives are all very commonly used, so this means these templates are present everywhere in Angular, either implicitly or explicitly.
126
Multiple Structural Directives on a single element
Let's see what happens if for example we try to use ngIf and ngFor in the same element: ```
{{lesson | json}}
view raw04.ts hosted with ❤ by GitHub This would not work! Instead, we would get the following error message: ``` Uncaught Error: Template parse errors: Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with * This means that its not possible to apply two structural directives to the same element. In order to do so, we would have to do something similar to this: ```
{{lesson | json}}
view raw05.ts hosted with ❤ by GitHub In this example, we have moved the ngIf directive to an outer wrapping div, but in order for this to work we have to create that extra div element. ``` This solution would already work, but is there a way to apply a structural directive to a section of the page without having to create an extra element? Yes and that is exactly what the ng-container structural directive allows us to do!
127
The ng-container directive
In order to avoid having to create that extra div, we can instead use ng-container directive: ```
{{lesson | json}}
``` view raw06.ts hosted with ❤ by GitHub As we can see, the ng-container directive provides us with an element that we can attach a structural directive to a section of the page, without having to create an extra element just for that. There is another major use case for the ng-container directive: it can also provide a placeholder for injecting a template dynamically into the page.
128
Dynamic Template Creation with the ngTemplateOutlet directive
Being able to create template references and point them to other directives such as ngIf is just the beginning. We can also take the template itself and instantiate it anywhere on the page, using the ngTemplateOutlet directive: view raw07.ts hosted with ❤ by GitHub We can see here how ng-container helps with this use case: we are using it to instantiate on the page the loading template that we defined above. We are refering to the loading template via its template reference #loading, and we are using the ngTemplateOutlet structural directive to instantiate the template. We could add as many ngTemplateOutlet tags to the page as we would like, and instantiate a number of different templates. The value passed to this directive can be any expression that evaluates into a template reference, more on this later. Now that we know how to instantiate templates, let's talk about what is accessible or not by the template.
129
Template Context
One key question about templates is, what is visible inside them? Does the template have its own separate variable scope, what variables can the template see? Inside the ng-template tag body, we have access to the same context variables that are visible in the outer template, such as for example the variable lessons. And this is because all ng-template instances have access also to the same context on which they are embedded. But each template can also define its own set of input variables! Actually, each template has associated a context object containing all the template-specific input variables. Let's have a look at an example: @Component({ selector: 'app-root', template: `
Approximately {{lessonsCounter}} lessons ...
``` `}) export class AppComponent { ``` totalEstimate = 10; ctx = {estimate: this.totalEstimate}; } view raw08.ts hosted with ❤ by GitHub Here is the breakdown of this example: this template, unlike the previous templates also has one input variable (it could also have several) the input variable is called lessonsCounter, and it's defined via a ng-template property using the prefix let- The variable lessonsCounter is visible inside the ng-template body, but not outside the content of this variable is determined by the expression that its assigned to the property let-lessonsCounter That expression is evaluated against a context object, passed to ngTemplateOutlet together with the template to instantiate This context object must then have a property named estimate, for any value to be displayed inside the template the context object is passed to ngTemplateOutlet via the context property, that can receive any expression that evaluates to an object Given the example above, this is what would get rendered to the screen: Approximately 10 lessons ... This gives us a good overview of how to define and instantiate our own templates. Another thing that we can also do is interact with a template programmatically at the level of the component itself: let's see how we can do that.
130
Template References
The same way that we can refer to the loading template using a template reference, we can also have a template injected directly into our component using the ViewChild decorator: @Component({ selector: 'app-root', template: ` {{loginText}} {{signUpText}} ``` `}) export class AppComponent implements OnInit { ``` @ViewChild('defaultTabButtons') private defaultTabButtonsTpl: TemplateRef; ngOnInit() { console.log(this.defaultTabButtonsTpl); } } view raw09.ts hosted with ❤ by GitHub As we can see, the template can be injected just like any other DOM element or component, by providing the template reference name defaultTabButtons to the ViewChild decorator. This means that templates are accessible also at the level of the component class, and we can do things such as for example pass them to child components! An example of why we would want to do that is to create a more customizable component, where can pass to it not only a configuration parameter or configuration object: we can also pass a template as an input parameter.
131
Configurable Components with Template Partial @Inputs
Let's take for example a tab container, where we would like to give the user of the component the possibility of configuring the look and feel of the tab buttons. Here is how that would look like, we would start by defining the custom template for the buttons in the parent component: @Component({ selector: 'app-root', template: `
{{loginText}} {{signUpText}}
``` `}) export class AppComponent implements OnInit { ``` } view raw10.ts hosted with ❤ by GitHub And then on the tab container component, we could define an input property which is also a template named headerTemplate: @Component({ selector: 'tab-container', template: `
...
``` ... rest of tab container component ... `}) export class TabContainerComponent { @Input() headerTemplate: TemplateRef; } view raw11.ts hosted with ❤ by GitHub A couple of things are going on here, in this final combined example. Let's break this down: ``` there is a default template defined for the tab buttons, called defaultTabButtons This template will be used only if the input property headerTemplate remains undefined If the property is defined, then the custom input template passed via headerTemplate will be used to display the buttons instead the headers template is instantiated inside a ng-container placeholder, using the ngTemplateOutlet property the decision of which template to use (default or custom) is taken using a ternary expression, but if that logic was complex we could also delegate this to a controller method The end result of this design is that the tab container will display a default look and feel for the tab buttons if no custom template is provided, but it will use the custom template if its available. https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/
132
Summary of The core directives ng-container, ng-template and ngTemplateOutlet
The core directives ng-container, ng-template and ngTemplateOutlet all combine together to allow us to create highly dynamical and customizable components. We can even change completely the look and feel of a component based on input templates, and we can define a template and instantiate on multiple places of the application.
133
javascript foreach
this.lessons.forEach((lesson, index) => { this.lessons[index].description = index + ' - ' + this.lessons[index].description });
134
Advantages of angular MVC framework over normal Jquery
Summary and Conclusions So let's summarize: the advantages of using an MVC framework like Angular as we have seen are huge, so let's list them one by one. Separation Of Concerns We can build frontend applications with a lot less code than previous generation technologies. This is because we don't have to write code that manually synchronizes the Model and the View - that code is generated for us automatically. The code that we do need to write will be a lot more readable and maintainable, due to the clear separation of concerns between the Model and the View. Transparent Model to View Synchronization The synchronization between Model and View is not only transparent but its optimized in a way that is not possible in practice to achieve manually. UI Performance The View is modified by generating directly DOM object trees in a cross-browser compatible way, instead of by generating HTML and then passing it to the browser for parsing - this effectively bypasses the parsing step altogether. The HTML still needs to be parsed, but it's done only once per template by Angular and by the browser each time. The parsing is done either at application startup time (Just In Time, or JIT), or ahead of time (AOT) when be build the application. And this one of the main reasons why it's so worth to have a more advanced development environment like the CLI: because using it we can have all these features and benefits working transparently out of the box. Also, the generation and modification of the view are itself done in an optimized way, meaning that only the parts of the DOM tree that have modified data will be affected, while the rest of the page remains the same. https://blog.angular-university.io/why-angular-angular-vs-jquery-a-beginner-friendly-explanation-on-the-advantages-of-angular-and-mvc/
135
Advantages of SPAs and the Key Concept About How They Work | https://blog.angular-university.io/why-a-single-page-application-what-are-the-benefits-what-is-a-spa/
Section Summary – Advantages of SPAs and the Key Concept About How They Work Building our application as a SPA will give us a significant number of benefits: We will be able to bring a much-improved experience to the user The application will feel faster because less bandwidth is being used, and no full page refreshes are occurring as the user navigates through the application The application will be much easier to deploy in production, at least certainly the client part: all we need is a static server to serve a minimum of 3 files: our single page index.html, a CSS bundle, and a Javascript bundle. We can also split the bundles into multiple parts if needed using code splitting. The frontend part of the application is very simple to version in production, allowing for simplified deployment and rollbacks to previous version of the frontend if needed And this just one possible deployment scenario of SPAs in production. Other Production Scenarios Other scenarios include pre-rendering large parts of the application and upload everything to a static hosting server, in-memory caching on the server of only certain pages, do versioning using DNS, etc. Its today simpler than ever to make SEO-friendly SPAs, so they will likely have increased adoption in the future, in scenarios where SPAs have not been frequently used. The Way SPAs Work The way that single page applications bring these benefits is linked to the way that they work internally: After the startup, only data gets sent over the wire as a JSON payload or some other format. But no HTML or CSS gets sent anymore over the wire after the application is running. The key point to understand how single page applications work is the following: instead of converting data to HTML on the server and then send it over the wire, in a SPA we have now moved that conversion process from the server to the client. The conversion happens last second on the client side, which allow us to give a much improved user experience to the user. I hope that this convinces you of the advantages of SPAs. If not please let me know and why that is not the case so I can better develop some of the points. Also, at this stage I want to show you some code straight away. Let’s build a small Hello World SPA in Angular, and take it from there. We are going to see how the concepts that we have introduced map to the small application that we are about to build.
136
accessing image from assets folder
template: ` `
137
Angular inputs :Input is for passing values down to child components
// app.component.html ``` is a component with the the selector, 'app-apple' . // apple.component.ts ... @Component({ selector: 'app-apple', templateUrl: './apple.component.html', styleUrls: ['./apple.component.css'] }) ... So what if the apples component is almost the same for each instance, but we need it to display a different description for each instance? We use Input . // app.component.html ``` appleDescription can be any class property inside app.component.html. // apple.component.ts import { Component, OnInit, Input } from '@angular/core'; ... export class AppleComponent implements OnInit { @Input() description: string; ... Now, description is passed in by whomever the parent component is. In this case it’s app.component.html. Any value can be passed into [description] and description can be used anywhere inside of apple.component.html or apple.component.ts as if it were a regular class property that follows normal change detection. One caveat is that description , or any Input property, is not ready in the .ts file until after ngOnInit . It will not be ready, it’ll be null, in the constructor. ``` // apple.component.html {{ description || 'Nothing has been typed yet...' }} ```
138
Angular outputs: Output is used for passing values up to parent components.
https://itnext.io/angular-input-output-f0418ab4cc91 ``` Output is the opposite of Input . Instead of the child component receiving values, the parent component will receive values. // app.component.html ``` incrementLimeCounter($event) is some class function. // app.component.ts ... incrementLimeCounter(amount) { this.limeCounter += amount; } ... We are saying that there should be an Output defined inside lime.component.html called increment . // lime.component.ts import { Component, OnInit, Output, EventEmitter } from '@angular/core'; ... export class LimeComponent implements OnInit { @Output() increment: EventEmitter = new EventEmitter(); ... clickMe() { this.increment.emit(1); } ... Output s are of type EventEmitter , with each EventEmitter having a type just as Inputs also have a type. In this case it’s of type number . Now, anytime clickMe() is called, increment will emit an event back to the parent component with the value 1. The value emitted could be anything and most likely will be dynamic in a real implementation.
139
angular table expansions links
https: //material.angular.io/cdk/table/overview https: //material.angular.io/components/table/examples https: //stackblitz.com/angular/nqdqmkykbvg?file=src%2Fapp%2Ftable-expandable-rows-example.ts https: //material.angular.io/cdk/table/overview https: //stackblitz.com/angular/nqdqmkykbvg?file=src%2Fapp%2Ftable-expandable-rows-example.html https: //stackoverflow.com/questions/46123854/expandable-table-rows-in-angular-4-with-angular-material https: //stackblitz.com/edit/angular-material2-expandable-rows-filter-pagination-sorting?file=app%2Fcdk-detail-row.directive.ts
140
Input - custom property name binding @Input('init') count: number = 0;
https://ultimatecourses.com/blog/passing-data-angular-2-components-input It may be that you’d want your “public” property names to differ from the internal input names. Here’s what we might want to do: @Component({ selector: 'app-root', template: `
```
` }) export class AppComponent { initialCount: number = 10; } ``` Because count is no longer being bound to, we’re trying to bind to an init property instead. To keep the internal property name(s) different to the public names, we can do this: ``` @Component({...}) export class CounterComponent { ``` @Input('init') count: number = 0; // ... } We simply pass a string into the @Input() decorator with the name of the property we want to bind to. That’s it, and we can use this.count as usual inside CounterComponent. This gives you some nice flexibility with creating components or composing your very own component library.
141
Intercepting input change in angular
In Angular, for a child component to allow its parent component to pass on some data to it, it needs to provide a binding input property to which the parent component can bind its data to. The child component specifies such binding property by decorating it with @Input() attribute. For example sake, consider an order-processing application that an store associate would use to process orders received. 👆 we have a child component item-details that specifies two properties - item and notifyItemProcessed,(line#9–10), as @Input() properties. This would allow a parent component order to pass on an order item and a reference to a parent’s method that the child component should call when an item has been processed, like below : ``` 👆the parent component order assigns its itemSelected property to the child component’s input property item (line# 13) and thus the child component gets a reference to the currently selected item in parent component via its item property. Similarly, the parent component is also passing a reference to the method that the child component should call when the selected item is processed via the child component’s input property notifyItemProcessed(line#14). Now, lets say, the child component wants to set the status of the item (passed to it from parent component ) to ‘In Process’ whenever the item selected for processing in the parent component changes. Additionally the child component may also want to reset its internal properties suppliedQuantity, scannedUPC and errors whenever a new item is passed to it. For this, the child component need to know when the value of its input property item changes. Child component has two options to intercept the change to its input properties: 1. Using the typescript’s class member accessors(getter/setter) to define the input property item or 2. Using the angular component’s ngOnChanges event. ```
142
Using Typescript Accessors (getter/setter) for @input change detection
Using Typescript Accessors (getter/setter) In the child component class, we can define our @Input property itemusing typescript accessors that would allow us to intercept whenever the property is set to a new value, like shown below: import {Component,Input,SimpleChanges} from '@angular/core'; ``` @Component({ selector: 'item-details', templateUrl: 'item-details.html', }) export class ItemDetails { ``` private _item; // private property _item ``` // use getter setter to define the property get item(): any { return this._item; } ``` @Input() set item(val: any) { console.log('previous item = ', this._item); console.log('currently selected item=', val); this._item = val; this._item.status = 'In Process'; } @Input() notifyItemProcessed: () => void; suppliedQuantity: number; scannedUPC: string; errors: string[]; constructor(){} ``` } 👆 line#12 -22, we defined the item property using typescript accessors. In the setter of the property (line#16–22), we intercept the new value and set its status to ‘In Process’. Note that we added a new private member _item inside our class to store the value of the property which is accessed using the getter/setter we defined. But the public @Input property being same i.e. item the parent component would continue to bind data to it in the same way as we did above: ```
143
Using ngOnChanges event for input change detection
https://medium.com/@bharat.tiwari/intercept-input-property-change-in-angular-690567eb63ec Another option to intercept for any change in any of the input property is to use the Angular’s ngOnChanges event: import {Component,Input, OnChanges, SimpleChanges, SimpleChange} from '@angular/core'; ``` @Component({ selector: 'item-details', templateUrl: 'item-details.html', }) export class ItemDetails implements OnChanges { ``` ``` private _item; get item(): any { return this._item; } ``` @Input() set item(val: any) { console.log('previous item = ', this._item); console.log('currently selected item=', val); this._item = val; this._item.status = 'In Process'; } @Input() notifyItemProcessed: () => void; suppliedQuantity: number; scannedUPC: string; errors: string[]; constructor(){} ngOnChanges(changes: SimpleChanges) { const currentItem: SimpleChange = changes.item; console.log('prev value: ', currentItem.previousValue); console.log('got item: ', currentItem.currentValue); if(currentItem.currentValue){ this.scannedUPC = changes.item.currentValue.upc; } this.suppliedQuantity = 0; } .. .. .. } Line# 30–38, we are using ngOnChanges event to intercept any change in the input properties. Note that this event will be triggered when any of the input bound properties change. The ngOnChanges event method would receive an object of type SimpleChanges object that would give us each of the property that has changed as SimpleChange object containing the property’s previousValue and CurrentValue. The SimpleChange object also provides isFirstChange() function that can be used to verify if its the first time the property value has changed. Here is the plunkr example of the above two approaches: Angular parent-child Component Communication using @Input() - Plunker Created on Plnkr: Helping developers build the web. embed.plnkr.co So, which one is to use of the two options? Cannot say one should be preferred over other. Both options work good. I found that with Typescript Accessor, I was required to use ChangeDetectorRef.detectChanges()to trigger the change if I use the property in some Angular expression on the template. With ngOnChanges it was handled by Angular. So I guess I would use ngOnChanges mostly because its more Angular in-built, but the Typescript Accessor approach would be useful when there is some customization need to be done to the property value when its being read(get).
144
using getter setter or ngOnChnages for @Input change detection
So, which one is to use of the two options? Cannot say one should be preferred over other. Both options work good. I found that with Typescript Accessor, I was required to use ChangeDetectorRef.detectChanges()to trigger the change if I use the property in some Angular expression on the template. With ngOnChanges it was handled by Angular. So I guess I would use ngOnChanges mostly because its more Angular in-built, but the Typescript Accessor approach would be useful when there is some customization need to be done to the property value when its being read(get).
145
Date pipe in angular
https://www.angularjswiki.com/angular/angular-date-pipe-formatting-date-times-in-angular-with-examples/ {{item.patientDOB | date:'shortDate'}} {{item.hospitalAdmission | date:'short'}} {{item.hospitalDischarge | date:'short'}}
146
ngIf Then and else
*ngIf="show;then showBlock; else notShowBlock">

Show this only if "show" is true

Show this only if "show" is not true

147
Splitting the data by comma in the angular html
```
  • {{ category.category_name }}
    {{ subCategory }}
  • ```
    148
    Basic overview of Just In Time (JIT) Vs Ahead Of Time (AOT) Compilation in Angular Applications
    The main differences between JIT and AOT in Angular are: The time when the compilation takes place. JIT generates JavaScript however, AoT usually generates TypeScript. Flow of events with Just-in-Time Compilation: Development of Angular application with TypeScript. Compilation of the application with tsc. Bundling. Minification. Deployment. Once we’ve deployed the app and the user opens her browser, she will go through the following steps (without strict CSP): Download all the JavaScript assets. Angular bootstraps. Angular goes through the JiT compilation process, i.e. generation of JavaScript for each component in our application. The application gets rendered. Flow of events with Ahead-of-Time Compilation: In contrast, with AoT we get through the following steps: Development of Angular application with TypeScript. Compilation of the application with ngc. Performs compilation of the templates with the Angular compiler and generates (usually) TypeScript. Compilation of the TypeScript code to JavaScript. Bundling. Minification. Deployment. Although the above process seems lightly more complicated the user goes only through the steps: Download all the assets. Angular bootstraps. The application gets rendered. As you can see the third step is missing which means faster/better UX.
    149
    we do not need whole formbuilder to use react components
    ``` export class SelectDisabledExample { disableSelect = new FormControl(false); } ```

    Disable select

    150
    using ReactiveForms Module
    in src/app/app.module.ts: import { ReactiveFormsModule } from '@angular/forms'; ``` @NgModule({ imports: [ // other imports ... ReactiveFormsModule ], }) export class AppModule { } ``` Generating and importing a new form control: src/app/name-editor/name-editor.component.ts: import { Component } from '@angular/core'; import { FormControl } from '@angular/forms'; ``` @Component({ selector: 'app-name-editor', templateUrl: './name-editor.component.html', styleUrls: ['./name-editor.component.css'] }) export class NameEditorComponent { name = new FormControl(''); } in html: ``` Name:
    151
    having nullable values in angular interface
    interface Pokemon { value: string; viewValue: string; } ``` interface PokemonGroup { disabled?: boolean; name: string; pokemon: Pokemon[]; } ``` pokemonGroups: PokemonGroup[] = [ { name: 'Grass', pokemon: [ {value: 'bulbasaur-0', viewValue: 'Bulbasaur'}, {value: 'oddish-1', viewValue: 'Oddish'}, {value: 'bellsprout-2', viewValue: 'Bellsprout'} ] }, { name: 'Water', pokemon: [ {value: 'squirtle-3', viewValue: 'Squirtle'}, {value: 'psyduck-4', viewValue: 'Psyduck'}, {value: 'horsea-5', viewValue: 'Horsea'} ] }, { name: 'Fire', disabled: true, pokemon: [ {value: 'charmander-6', viewValue: 'Charmander'}, {value: 'vulpix-7', viewValue: 'Vulpix'}, {value: 'flareon-8', viewValue: 'Flareon'} ] }, { name: 'Psychic', pokemon: [ {value: 'mew-9', viewValue: 'Mew'}, {value: 'mewtwo-10', viewValue: 'Mewtwo'}, ] } ];
    152
    *ngFor with in *ngFor
    Pokemon -- None -- {{pokemon.viewValue}}
    153
    chaging when the errors are triggered in angular
    import {Component} from '@angular/core'; import {FormControl, FormGroupDirective, NgForm, Validators} from '@angular/forms'; import {ErrorStateMatcher} from '@angular/material/core'; ``` /** Error when invalid control is dirty, touched, or submitted. */ export class MyErrorStateMatcher implements ErrorStateMatcher { isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { const isSubmitted = form && form.submitted; return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted)); } } ``` /** @title Select with a custom ErrorStateMatcher */ @Component({ selector: 'select-error-state-matcher-example', templateUrl: 'select-error-state-matcher-example.html', styleUrls: ['select-error-state-matcher-example.css'], }) export class SelectErrorStateMatcherExample { selected = new FormControl('valid', [ Validators.required, Validators.pattern('valid'), ]); selectFormControl = new FormControl('valid', [ Validators.required, Validators.pattern('valid'), ]); nativeSelectFormControl = new FormControl('valid', [ Validators.required, Validators.pattern('valid'), ]); ``` matcher = new MyErrorStateMatcher(); } ``` A global error state matcher can be specified by setting the ErrorStateMatcher provider. This applies to all inputs. For convenience, ShowOnDirtyErrorStateMatcher is available in order to globally cause input errors to show when the input is dirty and invalid. ``` @NgModule({ providers: [ {provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher} ] }) ```
    154
    Error handling in component and service
    What happens if the request fails on the server, or if a poor network connection prevents it from even reaching the server? HttpClient will return an error object instead of a successful response. You could handle in the component by adding a second callback to the .subscribe(): app/config/config.component.ts (showConfig v.3 with error handling) content_copy showConfig() { this.configService.getConfig() .subscribe( (data: Config) => this.config = { ...data }, // success path error => this.error = error // error path ); } It's certainly a good idea to give the user some kind of feedback when data access fails. But displaying the raw error object returned by HttpClient is far from the best way to do it. Getting error details Detecting that an error occurred is one thing. Interpreting that error and composing a user-friendly response is a bit more involved. Two types of errors can occur. The server backend might reject the request, returning an HTTP response with a status code such as 404 or 500. These are error responses. Or something could go wrong on the client-side such as a network error that prevents the request from completing successfully or an exception thrown in an RxJS operator. These errors produce JavaScript ErrorEvent objects. The HttpClient captures both kinds of errors in its HttpErrorResponse and you can inspect that response to figure out what really happened. Error inspection, interpretation, and resolution is something you want to do in the service, not in the component. You might first devise an error handler like this one: ``` app/config/config.service.ts (handleError) content_copy private handleError(error: HttpErrorResponse) { if (error.error instanceof ErrorEvent) { // A client-side or network error occurred. Handle it accordingly. console.error('An error occurred:', error.error.message); } else { // The backend returned an unsuccessful response code. // The response body may contain clues as to what went wrong, console.error( `Backend returned code ${error.status}, ` + `body was: ${error.error}`); } // return an observable with a user-facing error message return throwError( 'Something bad happened; please try again later.'); }; Notice that this handler returns an RxJS ErrorObservable with a user-friendly error message. Consumers of the service expect service methods to return an Observable of some kind, even a "bad" one. ``` Now you take the Observables returned by the HttpClient methods and pipe them through to the error handler. ``` app/config/config.service.ts (getConfig v.3 with error handler) content_copy getConfig() { return this.http.get(this.configUrl) .pipe( catchError(this.handleError) ); } ```
    155
    Retrying on failed observables
    Sometimes the error is transient and will go away automatically if you try again. For example, network interruptions are common in mobile scenarios, and trying again may produce a successful result. The RxJS library offers several retry operators that are worth exploring. The simplest is called retry() and it automatically re-subscribes to a failed Observable a specified number of times. Re-subscribing to the result of an HttpClient method call has the effect of reissuing the HTTP request. Pipe it onto the HttpClient method result just before the error handler. app/config/config.service.ts (getConfig with retry) content_copy getConfig() { return this.http.get(this.configUrl) .pipe( retry(3), // retry a failed request up to 3 times catchError(this.handleError) // then handle the error ); }
    156
    Observables and operators
    The previous sections of this guide referred to RxJS Observables and operators such as catchError and retry. You will encounter more RxJS artifacts as you continue below. RxJS is a library for composing asynchronous and callback-based code in a functional, reactive style. Many Angular APIs, including HttpClient, produce and consume RxJS Observables. RxJS itself is out-of-scope for this guide. You will find many learning resources on the web. While you can get by with a minimum of RxJS knowledge, you'll want to grow your RxJS skills over time in order to use HttpClient effectively. If you're following along with these code snippets, note that you must import the RxJS observable and operator symbols that appear in those snippets. These ConfigService imports are typical. app/config/config.service.ts (RxJS imports) content_copy import { Observable, throwError } from 'rxjs'; import { catchError, retry } from 'rxjs/operators';
    157
    adding HTTP headers for save operations like httpPost and HttpGet and Delete
    Many servers require extra headers for save operations. For example, they may require a "Content-Type" header to explicitly declare the MIME type of the request body; or the server may require an authorization token. Adding headers The HeroesService defines such headers in an httpOptions object that will be passed to every HttpClient save method. app/heroes/heroes.service.ts (httpOptions) content_copy import { HttpHeaders } from '@angular/common/http'; ``` const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Authorization': 'my-auth-token' }) }; Updating headers You can't directly modify the existing headers within the previous options object because instances of the HttpHeaders class are immutable. ``` Use the set() method instead, to return a clone of the current instance with the new changes applied. Here's how you might update the authorization header (after the old token expired) before making the next request. httpOptions.headers = httpOptions.headers.set('Authorization', 'my-new-auth-token');
    158
    Making a POST request
    In addition to fetching data from the server, HttpClient supports mutating requests, that is, sending data to the server with other HTTP methods such as PUT, POST, and DELETE. The following sections excerpt methods of the sample's HeroesService. Making a POST request Apps often POST data to a server. They POST when submitting a form. In the following example, the HeroesService posts when adding a hero to the database. app/heroes/heroes.service.ts (addHero) content_copy /** POST: add a new hero to the database */ addHero (hero: Hero): Observable { return this.http.post(this.heroesUrl, hero, httpOptions) .pipe( catchError(this.handleError('addHero', hero)) ); } The HttpClient.post() method is similar to get() in that it has a type parameter (you're expecting the server to return the new hero) and it takes a resource URL. It takes two more parameters: hero - the data to POST in the body of the request. httpOptions - the method options which, in this case, specify required headers. Of course it catches errors in much the same manner described above. The HeroesComponent initiates the actual POST operation by subscribing to the Observable returned by this service method. app/heroes/heroes.component.ts (addHero) content_copy this.heroesService .addHero(newHero) .subscribe(hero => this.heroes.push(hero)); When the server responds successfully with the newly added hero, the component adds that hero to the displayed heroes list.
    159
    Making a DELETE request
    This application deletes a hero with the HttpClient.delete method by passing the hero's id in the request URL. app/heroes/heroes.service.ts (deleteHero) content_copy /** DELETE: delete the hero from the server */ deleteHero (id: number): Observable { const url = `${this.heroesUrl}/${id}`; // DELETE api/heroes/42 return this.http.delete(url, httpOptions) .pipe( catchError(this.handleError('deleteHero')) ); } The HeroesComponent initiates the actual DELETE operation by subscribing to the Observable returned by this service method. app/heroes/heroes.component.ts (deleteHero) content_copy this.heroesService .deleteHero(hero.id) .subscribe(); The component isn't expecting a result from the delete operation, so it subscribes without a callback. Even though you are not using the result, you still have to subscribe. Calling the subscribe() method executes the observable, which is what initiates the DELETE request. You must call subscribe() or nothing happens. Just calling HeroesService.deleteHero() does not initiate the DELETE request. ``` content_copy // oops ... subscribe() is missing so nothing happens this.heroesService.deleteHero(hero.id); ```
    160
    Always subscribe!
    An HttpClient method does not begin its HTTP request until you call subscribe() on the observable returned by that method. This is true for all HttpClient methods. The AsyncPipe subscribes (and unsubscribes) for you automatically. All observables returned from HttpClient methods are cold by design. Execution of the HTTP request is deferred, allowing you to extend the observable with additional operations such as tap and catchError before anything actually happens. Calling subscribe(...) triggers execution of the observable and causes HttpClient to compose and send the HTTP request to the server. You can think of these observables as blueprints for actual HTTP requests. In fact, each subscribe() initiates a separate, independent execution of the observable. Subscribing twice results in two HTTP requests. ``` content_copy const req = http.get('/api/heroes'); // 0 requests made - .subscribe() not called. req.subscribe(); // 1 request made. req.subscribe(); // 2 requests made. ```
    161
    Making a PUT reques
    An app will send a PUT request to completely replace a resource with updated data. The following HeroesService example is just like the POST example. app/heroes/heroes.service.ts (updateHero) content_copy /** PUT: update the hero on the server. Returns the updated hero upon success. */ updateHero (hero: Hero): Observable { return this.http.put(this.heroesUrl, hero, httpOptions) .pipe( catchError(this.handleError('updateHero', hero)) ); } For the reasons explained above, the caller (HeroesComponent.update() in this case) must subscribe() to the observable returned from the HttpClient.put() in order to initiate the request.
    162
    Toastr Service methods return:
    Toastr Service methods return: export interface ActiveToast { /** Your Toast ID. Use this to close it individually */ toastId: number; /** the message of your toast. Stored to prevent duplicates */ message: string; /** a reference to the component see portal.ts */ portal: ComponentRef; /** a reference to your toast */ toastRef: ToastRef; /** triggered when toast is active */ onShown: Observable; /** triggered when toast is destroyed */ onHidden: Observable; /** triggered on toast click */ onTap: Observable; /** available for your use in custom toast */ onAction: Observable; }
    163
    create an object that implements the interface like
    interface foo { one: number; two: string; } const bar: foo = { one: 5, two: "hello" };
    164
    JSON.stringify() - convert from javascript object to JSON
    A common use of JSON is to exchange data to/from a web server. When sending data to a web server, the data has to be a string. Convert a JavaScript object into a string with JSON.stringify(). ``` var obj = { name: "John", age: 30, city: "New York" }; var myJSON = JSON.stringify(obj); document.getElementById("demo").innerHTML = myJSON; ``` JSON object: {"name":"John","age":30,"city":"New York"}
    165
    JSON.parse() - convert from json to javascript object
    A common use of JSON is to exchange data to/from a web server. When receiving data from a web server, the data is always a string. Parse the data with JSON.parse(), and the data becomes a JavaScript object.

    Create Object from JSON String

    ``` var txt = '{"name":"John", "age":30, "city":"New York"}' var obj = JSON.parse(txt); document.getElementById("demo").innerHTML = obj.name + ", " + obj.age; ```
    166
    Lifecycle methods with the basic component
    ``` These are the methods which occur with a component in Angular. As components load and unload from the DOM, these lifecycle methods triggers which give us the chance to do something in these key moments. Please look at the below illustration for better understanding. ngOnInit() ngOnChanges() ngOnDestroy() ngDoCheck() ```
    167
    Lifecycle methods with the basic component ngOnInit()
    This lifecycle hook is called after the component is loaded and all the data-bound properties are set and it is called only once when the component is loaded into the DOM. We don’t have to implement this interface OnInit Angular implements it whether you implement or not. ``` export class AppComponent implements OnInit { title = 'angular-lifecycle-hooks'; ``` constructor(private appService: AppService) {} ngOnInit() { this.appService.items.subscribe((data: any) => { this.itemList.push(data); console.log(this.itemList.length); }); } use cases if we want to add something once the component is loaded, this is the place like subscribing to data from the API, initialize some third party lib etc.
    168
    Lifecycle methods with the basic component ngOnChanges()
    This lifecycle hook is called before ngOnInit() and whenever there is a change in the input properties. It is called every time the data changes. We have to implement this interface OnChanges and it takes SimpleChanges Object as an input parameter. This simplechanges object has currentValue and previousValue so that we can compare and do all sorts of things. Look at the below file from this project, we want to add index number for each item added so that we can display number before each entry in the list. Since we need to change these before we display on the screen, ngOnChanges() is the best place. ``` export class DisplayListComponent implements OnInit, OnChanges, DoCheck { constructor(private bsModalRef: BsModalRef) { } ``` @Input() itemList: any[]; @Output() showDescription = new EventEmitter(); @Output() deleteOut = new EventEmitter(); items: string[]; ``` ngOnChanges(changes: SimpleChanges) { console.log('--app-display-list--ngOnChanges()----'); console.log('previous values', changes.itemList.previousValue); console.log('current values', changes.itemList.currentValue); const itemList = changes.itemList.currentValue; if (undefined !== itemList) { this.items = itemList.map((item) => { item.value = `Item: ${item.id} Name:${item.name} Description: ${item.description}`; return item; }); } } ``` we are changing the item before it displays it on the screen in ngOnChanges use cases whenever there is a change in the @Input data property, we can do some more changes in this method by comparing previous and current values.
    169
    Lifecycle methods with the basic component ngDoCheck()
    There is a problem with the above code if you add an item, it won’t be added to the list. it’s because we didn’t change the reference of the array, we just changed the content of it by pushing one element each time. In the above file, all the logic is in the ngOnChanges method and it doesn’t detect the changes and item is not displayed in the list. In these scenario’s we need to use ngDoCheck() because we need to trigger change detection manually. Look at the logic in ngDoCheck, we are comparing the array and assigning it to the items array. import { Component, OnInit, Input, OnChanges, SimpleChanges, DoCheck } from '@angular/core'; @Component({ selector: 'app-display-list', templateUrl: './display-list.component.html', styleUrls: ['./display-list.component.css'] }) export class DisplayListComponent implements OnInit, OnChanges, DoCheck { constructor() { } @Input() itemList: string[]; items: string[]; ``` ngOnChanges(changes: SimpleChanges) { console.log('--app-display-list--ngOnChanges()----'); console.log('previous values', changes.itemList.previousValue); console.log('current values', changes.itemList.currentValue); const itemList = changes.itemList.currentValue; this.items = itemList.map((item, index) => `Item: ${index + 1} ${item}`); } ``` ngDoCheck() { if (this.items !== this.itemList) { this.items = this.itemList.map((item, index) => `Item: ${index + 1} ${item}`); } console.log('ngDoCheck', this.itemList); } ngOnInit() { console.log('--app-display-list--ngOnInit()----'); console.log(this.itemList); } } added ngDoCheck() because ngOnChanges doesn’t see the input changes
    170
    Lifecycle methods with the basic component ngOnDestroy()ngOnDestroy()
    Angular cleans up all the event handlers or subscriptions in this method. This is called just before the component is destroyed. This is the best place to unsubscribe all the subscriptions and detach any event handlers to avoid memory leaks. Here is an example where we are unsubscribing appService items observable in the AppComponent ngOnDestroy Method. We have added takeUntil operator from the rxjs library which allows subscribing until the certain condition met true. import { Component , OnInit, OnChanges, OnDestroy } from '@angular/core'; import { AppService } from './app.service'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; ``` @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnDestroy { title = 'angular-lifecycle-hooks'; ``` constructor(private appService: AppService) {} itemList: string[] = []; showDesc = false; destroy$: Subject = new Subject(); addItemList(item: any) { this.appService.addItems(item); } deleteItem(item: any) { console.log(item); this.itemList = this.itemList.filter((itm: any) => itm.id !== item.id); } enableDescription(event) { this.showDesc = event; } ``` ngOnInit() { console.log('app component OnInit'); this.appService.items.pipe(takeUntil(this.destroy$)).subscribe((data: any) => { this.itemList.push(data); console.log(this.itemList.length); }); } ``` ngOnDestroy() { this.destroy$.next(true); this.destroy$.unsubscribe(); } use cases The best place to clean up event handlers or any subscriptions.
    171
    string interpolation: to write a string with embedded objects in it
    item.value = `Item: ${item.id} Name:${item.name} Description: ${item.description}`;
    172
    Lifecycle methods with component’s view
    In Angular, we follow the component design pattern and every component has a view associated with it. These lifecycle methods are called once the view is loaded. ngAfterViewinit() ngAfterViewChecked()
    173
    Lifecycle methods with component’s view ngAfterViewinit()
    we can initialize the number of items in the footer component with the help of ngAfterViewInit() method in app.component.ts. Look at the following code in appcomponent.html: in appcomponent.ts: constructor(private appService: AppService) {} itemList: string[] = []; showDesc = false; showFooter = true; numberOfItems = 1; @ViewChild('footer') footerComponent: FooterComponent; ngAfterViewInit() { console.log('ngAfterViewInit:::::app component'); setTimeout(() => { this.footerComponent.numberOfItems = this.itemList.length; });
    174
    Lifecycle methods with component’s view ngAfterViewChecked()
    This is called once after ngAfterViewInit() and every time after ngDoCheck(). if possible avoid this for performance reasons.
    175
    Lifecycle methods with content projection into Component’s view
    In Angular, There is a way we can project content into the component’s view. Look at the following illustration, whatever you put between the component tag will be projected into the component’s view in place of . These lifecycle methods will be called once content projection is completed ngAfterContentInit() ngAfterContentChecked()
    176
    Lifecycle methods with content projection into Component’s view ngAfterContentInit() and usage of @ContentChild(ErrorMessageComponent) errorMessage: ErrorMessageComponent;
    ``` This lifecycle hook is called whenever Angular projects content into the view that this directive is in. This is called only once after ngDoCheck. Look at the following illustration, we have implemented AfterContentInit and AfterContentChecked in app-error Component. We have defined another component app-error-message component with input message, In this way, we will have the flexibility with the messages and we are projecting and this app-error-message component into the app-error component which invokes lifecycle methods ngAfterContentInit() and ngAfterContentChecked() in the app-error component. // displaying app-error when there are no items ``` error-message.component.ts : import { Component, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-error-message', templateUrl: './error-message.component.html', styleUrls: ['./error-message.component.css'] }) export class ErrorMessageComponent implements OnInit { constructor() { } @Input() message; ngOnInit() { } } error.component.html:
    ---- error.component.ts import { Component, OnInit, AfterContentChecked, AfterContentInit, ContentChild } from '@angular/core'; import { ErrorMessageComponent } from './error-message.component'; ``` @Component({ selector: 'app-error', templateUrl: './error.component.html', styleUrls: ['./error.component.css'] }) export class ErrorComponent implements OnInit, AfterContentChecked, AfterContentInit { ``` constructor() { } @ContentChild(ErrorMessageComponent) errorMessage: ErrorMessageComponent; ngOnInit() {} ngAfterContentChecked() { console.log('------ngAfterContentChecked-----'); console.log(this.errorMessage.message); } ngAfterContentInit() { console.log('------ngAfterContentInit-----'); console.log(this.errorMessage.message); this.errorMessage.message = this.errorMessage.message.toUpperCase(); } } So, in ngAfterContentInit we are making error message to uppercase, No matter what case the message is sent, we can see the error message in uppercase it will appear in uppercase.
    177
    Lifecycle methods with content projection into Component’s view ngAfterContentChecked()
    This lifecycle hook is called whenever Angular projects content into the view that this directive is in. This is called every time after ngDoCheck. Look at the following example, we know we are using content projection for error component. what if we want to show a number of attempts and the time of the last attempt. we can't use ngAfterContentInit() for it because it occurs only once.
    178
    Angular life cycle hooks
    https://medium.com/bb-tutorials-and-thoughts/angular-understanding-angular-lifecycle-hooks-with-a-sample-project-375a61882478 ngOnInit(): This is called when the component is loaded into the DOM and it occurs only once. ngOnChanges(): This is called when there is Input property to the component and it is called before ngOnInit() and occurs every time there is a change in the input property. It is not called if there is no input property to the component ngDoCheck(): occurs every time there is a change detection and immediately after ngOnChanges() and ngOnInit(). ngOnDestroy(): This is called right before the component gets destroyed and occurs only once. ngAfterViewInit(): This is called once after the component’s view/ child views are loaded and right after ngAfterContentChecked() and occurs only once. ngAfterViewChecked(): This is called after component’s view/ child views are loaded and called after ngAfterViewInit() and every time after ngDoCheck(). ngAfterContentInit(): This is called once external content is projected into component’s view and right after the first ngDoCheck() and occurs only once. ngAfterContentChecked(): This is called after external content projected into component’s view and called after ngAfterContentInit() and every subsequent ngDoCheck().
    179
    All init lifecycle hooks gets called only once
    ngOnInit(): This is called when the component is loaded into the DOM and it occurs only once. ngAfterViewInit(): This is called once after the component’s view/ child views are loaded and right after ngAfterContentInit(): This is called once external content is projected into component’s view and right after the first ngDoCheck() and occurs only once.
    180
    intially called angular events
    ``` constructor called only once ngonInit -only once ngDoCheck AfterContentInit - only once AfterConentChecked AfterViewInit -only once AfterViewCheckedCount ``` if there are no input properties this is sequence
    181
    when there are changes on the page or when mouse over and mouse out on an angular element and not static elements. after each web api succesful call these events are called in sequence
    ngDoCheck AfterConentChecked AfterViewChecked so all the events are called in sequence and each one of them are called same number of times for normal angular app when we switch to different route the below events are called twice in sequence ngDoCheck AfterConentChecked AfterViewChecked and later ngOnDestroy is called
    182
    angular hook ups testing code
    https://medium.com/bb-tutorials-and-thoughts/angular-understanding-angular-lifecycle-hooks-with-a-sample-project-375a61882478 import { Component, OnInit, OnChanges, OnDestroy, AfterViewInit, AfterViewChecked, AfterContentInit, AfterContentChecked, DoCheck } from '@angular/core'; export class StaffComponent implements OnInit, DoCheck, OnChanges, OnDestroy, AfterViewInit, AfterViewChecked, AfterContentInit, AfterContentChecked { ``` constructorCount: number = 0; onInitCount: number = 0; OnChangesCount: number = 0; OnDestroyCount: number = 0; AfterViewInitCount: number = 0; AfterViewCheckedCount: number = 0; AfterContentInitCount: number = 0; AfterContentCheckedCount: number = 0; DoCheckCount: number = 0; ``` constructor(private rest: RestService, private logger: NGXLogger) { this. dataSourceStaff = new MatTableDataSource; this. constructorCount++; this. logger.log(`ConstructorCount ${this.constructorCount}`); } ``` ngOnInit(): void { this.getStaff(); this.onInitCount++; this.logger.log(`ngOnInitCount ${this.onInitCount}`); } ngDoCheck(): void { this.DoCheckCount++; this.logger.log(`ngDoCheckCount ${this.DoCheckCount}`); } ngOnDestroy(): void { this.OnDestroyCount++; this.logger.log(`ngOnDestroyCount ${this.OnDestroyCount}`); } ngOnChanges(): void { this.OnChangesCount++; this.logger.log(`ngOnChangesCount ${this.OnChangesCount}`); } ngAfterViewInit(): void { this.AfterViewInitCount++; this.logger.log(`AfterViewInitCount ${this.AfterViewInitCount}`); } ngAfterViewChecked(): void { this.AfterViewCheckedCount++; this.logger.log(`AfterViewCheckedCount ${this.AfterViewCheckedCount}`); } ngAfterContentInit(): void { this.AfterContentInitCount++; this.logger.log(`AfterContentInitCount ${this.AfterContentInitCount}`); } ``` ``` ngAfterContentChecked(): void { this.AfterContentCheckedCount++; this.logger.log(`AfterContentCheckedCount ${this.AfterContentCheckedCount}`); } } ```
    183
    Four ways of listening to DOM events in Angular (Part 1: Event Binding)
    https://medium.com/claritydesignsystem/four-ways-of-listening-to-dom-events-in-angular-part-1-event-binding-3ec7e9f51a1d Event binding is the simplest (or the most proper) way of listening to events in a component template. With event binding, you cannot listen to events fired outside a component’s template with the exceptions of global elements such as window, document, and body. Listening to global events in a reusable component is not recommended as it could potentially result in poor performance. Parent component can hear and catch DOM events (not custom Angular events) fired inside child components as the events bubble up. Event bindings will be active once they are set on an element and they will stay active until the elements are removed from the DOM so that means you cannot control when to add or remove event listeners dynamically.
    184
    Four ways of listening to DOM events in Angular: | @HostListener: Angular decorator that handles events on the host element
    https://medium.com/claritydesignsystem/four-ways-of-listening-to-dom-events-in-angular-part-2-hostlistener-1b66d45b3e3d @HostListener is Angular’s decorator method that’s used for listening to DOM events on the host element of both component and attribute directives. @HostListener sets the listeners once the directive is initialized and removes them automatically once the directive gets destroyed. @HostListener catches and listens to events from children or nested elements when they bubble up to the host element. Moreover, you can listen to events on global elements, but you should do so sparingly for performance reasons.
    185
    pseudo-events
    https://medium.com/claritydesignsystem/angular-pseudo-events-d4e7f89247ee
    186
    Top Common Mistakes of Angular Developers
    https://hackernoon.com/top-common-mistakes-of-angular-developers-2a36524f2c21
    187
    https://angular.io/api/common/I18nSelectPipe
    https://angular.io/api/common/I18nSelectPipe in component.ts file genderMap: any = { M: 'Male', F: 'Female', U: 'Unknown' }; in html template: {{item.shortName | i18nSelect: genderMap}}
    188
    skip spec file for component/service
    If you would like to skip spec file for specific component. New version: ng generate component "componentName" --skipTests Example ng generate component recipe-list --skipTests Old version : ng generate component "componentName" --spec false Example ng generate component recipe-list --spec false
    189
    Angular Modules
    https://www.youtube.com/watch?v=I0i8kNdIsvE&list=PL6n9fhu94yhWNJaDgh0mfae _9xoQ4E_Zj&index=31 In simple terms an Angular Module is a class decorated with @NgModule decorator. every angular application will have atleast one module the root module. By default the root application module is called AppModule An Angular Module is a mechanism to group components, directives, pipes and services that are related to a feature area of an angular application. ``` As we have already discussed an Angular module is a class that is decorated with @NgModule decorator. The @NgModule decorator has the following properties. declarations bootstrap providers imports exports ```
    190
    feature modules
    For example, if you are building an application to manage employees, you might have the following features in your application. Application Feature Description Employee Feature -Deals with creating, reading, updating and deleting employees Login Feature - Deals with login, logout, authenticate and authorize users Report Feature-Deals with generating employee reports like total number of employees by department, top 10 best employees etc To group the components, directives, pipes and services related to a specific feature area, we create a module for each feature area. These modules are called feature modules.
    191
    Root Module
    Every Angular application has at least one module, the root module. By default, this root application module is called AppModule. We bootstrap this root module to launch the application. If the application that you are building is a simple application with a few components, then all you need is the root module. As the application starts to grow and become complex, in addition to the root module, we may add several feature modules. We then import these feature modules into the root module. We will discuss creating feature modules in our upcoming videos
    192
    Core Module
    The most important use of this module is to include the providers of http services. Services in Angular are usually singletons. So to ensure that, only one instance of a given service is created across the entire application, we include all our singleton service providers in the core module. In most cases, a CoreModule is a pure services module with no declarations. The core module is then imported into the root module (AppModule) only. CoreModule should never be imported in any other module. We will discuss creating a core module in our upcoming videos
    193
    Shared Module
    This module contains reusable components, directives, and pipes that we want to use across our application. The Shared module is then imported into specific Feature Modules as needed. The Shared module might also export the commonly used Angular modules like CommonModule, FormsModule etc. so they can be easily used across your application, without importing them in every Feature Module. We will discuss creating a shared module in our upcoming videos
    194
    Routing Modules
    An angular application may also have one or more routing modules for application level routes and feature module routes
    195
    Routing- setting pagenot found for wrong route | set default route when route is not correct
    import { HomeComponent } from './home.component'; import { PageNotFoundComponent } from './page-not-found.component'; ``` const appRoutes: Routes = [ // home route { path: 'home', component: HomeComponent }, { path: 'list', component: ListEmployeesComponent }, { path: 'create', component: CreateEmployeeComponent }, { path: 'edit/:id', component: CreateEmployeeComponent }, // redirect to the home route if the client side route path is empty { path: '', redirectTo: '/home', pathMatch: 'full' }, // wild card route { path: '**', component: PageNotFoundComponent } ]; ```
    196
    How to set Routing in the application
    ```
    197
    How to import feature module into app module
    ng g m employee/employee --flat -m app ``` new module is created imported into app module with import statement imports array is also updated in app module ```
    198
    Organize angular module imports
    structure the imports in module; first angular modules; then imported user modules; then imported services; then components
    199
    How to Add components to an module
    include them in import statements | add them to the declarations
    200
    NgModule, we need to import this module for a class to be a an angular module it needs @NgModule decorator
    NgModule, we need to import this module for a class to be a an angular module it needs @NgModule decorator
    201
    import { CommonModule } from '@angular/common';
    most of the angular basic directives and pipes are present in common module like ngIf,ngFor and decimal pipes etc are availble in common module ``` // Exports all the basic Angular directives and pipes // such as NgIf, NgFor,NgClass, DecimalPipe etc. import { CommonModule } from '@angular/common'; ```
    202
    How to Importing module vs components in a module
    ``` For Module - just import the module name and add it to imports array For Component - just import the component name and add it to declarations array ```
    203
    ``` Browser Module Vs Common Module Feature Module imports Common Module (we can not import browser module as it is already imported in root module) Root Module imports Browser Module; so that we could use common Module directives ```
    ``` required for providing essential services to launch and run a browser application Browser module should only be imported in the root module and only once Browser Module, imports and re-exports the common module ``` so even through there is no common module in the root module, all the common module directives like NgIf, NgFor are available in the root module
    204
    How to make components and Modules in this module available to any module that imports this module
    ``` @NgModule({ imports: [ CommonModule, ReactiveFormsModule ], declarations: [ CreateEmployeeComponent, ListEmployeesComponent ], // If you want the components that belong to this module, available to // other modules, that import this module, then include all those // components in the exports array. Similarly you can also export the // imported Angular Modules // exports: [ // CreateEmployeeComponent, // ReactiveFormsModule // ] }) export class EmployeeModule { } ```
    205
    How to Use a component that is being imported from a module in another component
    ``` export from feature module the component @NgModule({ imports: [ CommonModule, ReactiveFormsModule ], declarations: [ CreateEmployeeComponent, ListEmployeesComponent ], // If you want the components that belong to this module, available to // other modules, that import this module, then include all those // components in the exports array. Similarly you can also export the // imported Angular Modules // exports: [ // CreateEmployeeComponent, // ReactiveFormsModule // ] }) export class EmployeeModule { } ``` ------------------ import it in root module then you could use in any of the components
    206
    Feature service in the rootModule
    https://csharp-video-tutorials.blogspot.com/2018/12/creating-feature-module-in-angular.html ``` @NgModule({ declarations: [ AppComponent, HomeComponent, PageNotFoundComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule, EmployeeModule ], providers: [EmployeeService], bootstrap: [AppComponent] }) export class AppModule { } ``` when a service is provided at module level, it is registered with the root injector and it is available to all components across all the modules in our entire application We can still simplify the code in root module. Notice the EmployeeService is still in the root module. We can move this service to the EmployeeModule or CoreModule. We will discuss this in our upcoming videos.
    207
    we could have all the feature routes and other routes in app.routing module; but it is better to have feature routes in feature.routing.module.ts
    we could have all the feature routes and other routes in app.routing module; but it is better to have feature routes in feature.routing.module.ts
    208
    ``` feature routing module naming convention feature-routing.module.ts ``` like employee-routing.module.ts login-routing.module.ts
    ``` feature routing module naming convention feature-routing.module.ts ``` like employee-routing.module.ts login-routing.module.ts
    209
    ``` How to use Child routes we use forChild; instead of forRoot in the routing module to register routes ```
    ``` // In a feature module forChild() method must be used to register routes // Export RouterModule, so the it's directives like RouterLink, RouterOutlet // are available to the EmployeeModule that imports this module @NgModule({ imports: [ RouterModule.forChild(appRoutes) ], exports: [ RouterModule ] }) export class EmployeeRoutingModule { } ```
    210
    Exporting Router Module in the feature routing module
    ``` // In a feature module forChild() method must be used to register routes // Export RouterModule, so the it's directives like RouterLink, RouterOutlet // are available to the EmployeeModule that imports this module @NgModule({ imports: [ RouterModule.forChild(appRoutes) ], exports: [ RouterModule ] }) export class EmployeeRoutingModule { } ``` in this case it does not make much difference because the EmployeeModule which is going to import the employeeRoutingModule does not have any top level component that makes use of RouterModule Directives like RouterOutlet and RouterLink etc so exporting RouterModule is not needed curretnly but having there will have future proof
    211
    RouterModule Directives like RouterOutlet and RouterLink etc
    RouterModule Directives like RouterOutlet and RouterLink etc importing router module gives us that options
    212
    RouterModule.forRoot(appRoutes) vs RouterModule.forChild(appRoutes)
    ``` // In a feature module forChild() method must be used to register routes // Export RouterModule, so the it's directives like RouterLink, RouterOutlet // are available to the EmployeeModule that imports this module @NgModule({ imports: [ RouterModule.forChild(appRoutes) ], exports: [ RouterModule ] }) export class EmployeeRoutingModule { } ``` ``` --- appModule @NgModule({ imports: [ RouterModule.forRoot(appRoutes) ], exports: [ RouterModule ] }) export class AppRoutingModule { } ``` ---- forRoot() method registers the specified routes. It also creates an instance of the Router service and registers it with the angular's dependency injector. forChild() method on the other hand only registers the additional specified routes and tells angular to reuse the Router service instance that forRoot has created. Angular services are singletons. So, to ensure that, there is only one instance of Router service, forRoot() method should be called only once in the main application routing module. In all the feature routing modules forChild() method should be used to register the additional routes. When the forChild() method is called, Angular Router knows it has to only register the additional specified routes and not to re-register the Angular Router service.
    213
    forRoot() should be called only once in the main app routing module all the feature routing modules; forChild should be called
    forRoot() should be called only once in the main app routing module all the feature routing modules; forChild should be called
    214
    How to Set routerlink or Route navigation on click of button
    ```
  • List
  • Create
  • ``` editButtonClick(employeeId: number) { this._router.navigate(['/employees/edit', employeeId]); } if (this.employee.id) { this.employeeService.updateEmployee(this.employee).subscribe( () => this.router.navigate(['employees']), (err: any) => console.log(err) );
    215
    Angular CLI commands
    For Generating a new component and letting know which module to update for with the info: ng g c MeasureDataProfiler --module=shared.module.ts --dry-run Skip test when generating the component: ng g c MeasureDataProfiler --skipTests=true
    216
    Registering a Service in a Component
    https://www.pluralsight.com/guides/registering-a-service-with-an-angular-module-or-component This method should be used when the service in concern is strictly related to the concerned component and won't be used elsewhere in the app. You can register a service using the following syntax. import { Component, OnInit } from '@angular/core'; import { DemoService } from './demo.service'; ``` @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers:[DemoService] }) export class AppComponent implements OnInit { title = 'services-demo'; someProperty; ``` constructor(private demoService:DemoService) { } ngOnInit() { this.someProperty = this.demoService.someProperty; } } Notice that in the providers array of the component, the service is registered and then consumed in the constructor of the component. This way, the service will not be used by any other component, directive, or pipe in the whole app. Real World Scenario Suppose you are building an app in which you are required to build a component that will convert text to speech. This component will require a service that will talk to some prominent language translator API from Microsoft, Google, or Facebook. This reusable Angular service will be used only in this component and not anywhere else, so this can be injected only in this component.
    217
    Registering a Service in AppModule
    This method should be used when you want to have only one instance of your service to be used across the app. When only one instance of your service exists across the app, it is called a singleton service. You can register a service in the app module using following syntax: import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { DemoService } from './demo.service'; ``` @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule ], providers: [DemoService], bootstrap: [AppComponent] }) export class AppModule { } Notice that in the providers array of the component, the service is registered. This way the service is consumable in any module, service, component, directive, or pipe across the app. ```
    218
    Self Registering a Service Using providedIn Attribute
    This is yet another way of registering only one instance of a service that can be consumed across the app in any module, service, component, directive, or pipe. You can register the service in root injector of the app using following syntax. This is the preferred way to create a singleton service from the beginning of Angular 6.0. import { Injectable } from '@angular/core'; ``` @Injectable({ providedIn: 'root' }) export class DemoService { ``` someProperty = 'Some Value'; constructor() { } } Notice that the providedIn attribute in the Injectable() decorator has been used to register the service in the root injector of the app. Real World Scenario This example applies to both the approaches given above, which help you register a singleton instance of a service. In any enterprise app, authentication is an important aspect. In a single page app framework, services generally talk to a corresponding server side API, so the authentication service will talk to the authentication endpoint on the server. On the client side, only one instance of this service will be required, so this service can be registered in the AppModule or using providedIn attribute on the service itself. A simple authentication service will have at least a currentUser property telling which user is currently logged in. The login and logout methods are shown below. import { Injectable } from '@angular/core'; @Injectable( {providedIn: 'root' } ) ``` export class AuthService { currentUser:IUser; ``` constructor() { } login(){} logout() {} }
    219
    Single Instance of a Service by Registering in a Module
    When you register the service in a feature module and that feature module is imported only by the app level AppModule, then also only one instance of the service exists and is available for use by any other feature module, service, component, directive, or pipe across the app. Real World Scenario Any app can have a requirement to show small toast messages to the end user on certain user interactions. Such toast messages can be shown to the user by using a Toastr Javascript library. Since Toastr JavaScript library is a vanilla JavaScript library, it is a best practice to wrap it inside a reusable Angular service. This Toastr reusable service is an example of a shared service that can be registered in the shared module. Shared modules are generally the modules that are only imported by an app module, so only one instance of the Toastr service will exist in the component.
    220
    Why angular needs Node js
    https://www.quora.com/Why-does-Angular-2-need-Node-js Angular2 is now called as Angular so I will refer to it as ‘Angular’ in my answer. Angular does not need node.js directly. Node js is used for all the build and development tools. Angular is a framework and you may use typescript or javascript or dart programming language to program using Angular. Typescript is the most popular choice. So I will consider that in my answer. A web browser such as Chrome, Firefox or Internet Explorer understands only Javascript so we have to transpile [1]our Typescript to Javascript and for that we use typescript transpiler which requires NodeJS. Also we want to perform some steps like minification, bundling, build optimization, etc. This steps are required in order to reduce size for deployment of the webapp and to serve it efficiently. All of this tools are easily available in JavaScript community as a gulp or grunt plugins(gulp and grunt require node js). This are also available as stand alone node js scripts. Moreover when you are developing the app it would be very inconvenient to make changes and run the app manually so there are some development tools that keep watch at the files and if the file is modified then the tool automatically re run the application with new changes and re render it in the browser. This kind of tools are also easily available in the nodejs eco system. But once app passes through development life cycle and you create a distribution build then those are just static files which can be served through any web server or a CDN and it does not require any node js instance unless your web-server directly requires it. Note: If all of the above is overwhelming, then do not worry, the angular team has come up with angular cli project which helps you take care of all the above steps of development and build cycle using a single package. Take a look at angular cli project Angular CLI
    221
    Why angular needs Node js -2
    Angular 2 like many other frame work requires a task runner to do some basic stuff. You need some sort of script that can be run on your machine that allows you to have a build, run test cases, transpile your code if needed, load dependancy etc There are many such packages available, which are packaged as a Node package and easily installable using the code package manager (npm). This is why you require Node. Also Node dominates the industry for such tasks. It is not mandatory to use node.js for developing angular application. You can very well go ahead without node.js for developing angular application but it would not be wise to do so. Let me explain you some of the reasons how node.js makes angular app development process easier for us: Node allows you to spin up a lightweight web server to host your application locally in your system. NPM (Node Package Manager) comes with node.js by default. NPM allows you to manage your dependencies. So, you don’t have to worry for operations like adding a dependency, removing some, updating your package.json. Third and the most important, npm gives you angular cli or ng cli(angular command line interface) . Angular CLI is a great tool for scaffolding your application. So, you don’t need to write boilerplates manually. Angular recommends the use of TypeScript. Now, your browser does not understand TypeScript. It needs to be transpiled to JavaScript. Also, you need to bundle your js files and stylesheets together with the html doc so as to get the web app CLI which is ready to be hosted. Angular CLI helps you to do all these behind the scene. By default, ng cli uses webpack for bundling your application and is very helpful for beginners who have just jumped into web development with angular as it abstracts such complexities.
    222
    converting a series of number or array to observable by using of operator
    import { of } from 'rxjs'; nums = of(1, 2, 3, 4, 5, 6, 7, 8); here nums is observable which could be subscribed or we could add pipe operators to it ``` beers = [ { name: 'Stella', country: 'Belgium', price: 9.5 }, { name: 'Sam Adams', country: 'USA', price: 8.5 }, { name: 'Bud Light', country: 'USA', price: 6.5 }, { name: 'Brooklyn Lager', country: 'USA', price: 8.0 }, { name: 'Sapporo', country: 'Japan', price: 7.5 }, ]; let observableValue = of(beers); ```
    223
    How to use filter, map, or reduce operators of Rxjs all of these return an observable, we use them with pipe and comma-separated we could have them separately as well Filter output 2,4,6,8 Map output 4,8,12,16 Reduce output 40 ; it has accumulator and current value
    https://yakovfain.com/2017/08/30/rxjs-essentials-part-2-map-filter-reduce/ import { of } from 'rxjs'; import { filter,map, reduce } from 'rxjs/operators'; nums = of(1, 2, 3, 4, 5, 6, 7, 8); here nums is observable which could be subscribed or we could add pipe operators to it nums .pipe( filter((num: number) => num % 2 == 0), map((num: number) => num * 2), reduce((acc: number, curr: number) => acc + curr, 0) ) .subscribe( (num) => console.log(num), (err) => console.log(err), () => console.log('streaming is complete') ); }
    224
    How to Subscribe for an observable with all the options for success, failure and stream complete
    ``` nums .pipe( filter((num: number) => num % 2 == 0), map((num: number) => num * 2), reduce((acc: number, curr: number) => acc + curr, 0) ) .subscribe( (num) => console.log(num), (err) => console.log(err), () => console.log('streaming is complete') ); } ```
    225
    There are some pretty heavy change in the use of rxjs 6
    There are some pretty heavy change in the use of rxjs 6. Imports : As already stated, you should now use : import { map } from 'rxjs/operators'; (and same for other operators) I want to mention here the other main changes : Observable, Subject and methods that create Observables (like of) have now to be imported like that : import { Observable, of, Subject } from 'rxjs'; You will need to use pipe to apply most operators, which might look a bit strange. e.g. : ``` obs.pipe( map(....), secondOperator(....), thirdOperator() ) instead of ``` obs.map(....) .secondOperator(....) .thirdOperator() And finally, due to the change with pipe and conflict with JavaScript reserved words, some operators had to be renamed : do becomes tap catch and finally become catchError finalize switch becomes switchAll other functions were renamed as well : fromPromise becomes from throw becomes throwError
    226
    using of in earlier and current versions
    You need to import it: for Angular >= 6.0.0 uses RxJS 6.0.0 Angular Changelog 6.0.0 import { of } from 'rxjs'; And its usage has been changed, you no longer call it off of Observable: of('token'); RxJS v5.x to v6 Update Guide - HowTo: Convert to pipe syntax which uses of() for Angular <= 5.x.xx import 'rxjs/add/observable/of'; And it's used as you have in your question Observable.of('token');
    227
    Tree Shaking
    Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. It relies on the static structure of ES2015 module syntax, i.e. import and export. The name and concept have been popularized by the ES2015 module bundler rollup. https://webpack.js.org/guides/tree-shaking/
    228
    there are map, reduce,filter methods in javascripts - these work on arrays and map, reduce, filter operators in Rxjs- these work on observables
    there are map, reduce,filter methods in javascripts - these work on arrays and map, reduce, filter operators in Rxjs- these work on observables
    229
    Javascript .map()
    Let me explain how it works with a simple example. Say you have received an array containing multiple objects – each one representing a person. The thing you really need in the end, though, is an array containing only the id of each person. // What you have var officers = [ { id: 20, name: 'Captain Piett' }, { id: 24, name: 'General Veers' }, { id: 56, name: 'Admiral Ozzel' }, { id: 88, name: 'Commander Jerjerrod' } ]; // What you need [20, 24, 56, 88] There are multiple ways to achieve this. You might want to do it by creating an empty array, then using .forEach(), .for(...of), or a simple .for() to meet your goal. Let’s compare! Using .forEach(): var officersIds = []; officers.forEach(function (officer) { officersIds.push(officer.id); }); Notice how you have to create an empty array beforehand? Let’s see what it looks like when using .map(): var officersIds = officers.map(function (officer) { return officer.id }); We can even be more concise with arrow functions (requires ES6 support, Babel or TypeScript) const officersIds = officers.map(officer => officer.id); So how does .map() work? Basically is takes 2 arguments, a callback and an optional context (will be considered as this in the callback) which I did not use in the previous example. The callback runs for each value in the array and returns each new value in the resulting array. Keep in mind that the resulting array will always be the same length as the original array.
    230
    Javascirpt .reduce() method
    Just like .map(), .reduce() also runs a callback for each element of an array. What’s different here is that reduce passes the result of this callback (the accumulator) from one array element to the other. The accumulator can be pretty much anything (integer, string, object, etc.) and must be instantiated or passed when calling .reduce(). Time for an example! Say you have an array with these pilots and their respective years of experience: var pilots = [ { id: 10, name: "Poe Dameron", years: 14, }, { id: 2, name: "Temmin 'Snap' Wexley", years: 30, }, { id: 41, name: "Tallissan Lintra", years: 16, }, { id: 99, name: "Ello Asty", years: 22, } ]; We need to know the total years of experience of all of them. With .reduce(), it’s pretty straightforward: var totalYears = pilots.reduce(function (accumulator, pilot) { return accumulator + pilot.years; }, 0); Notice that I’ve set the starting value as 0. I could have also used an existing variable if necessary. After running the callback for each element of the array, reduce will return the final value of our accumulator (in our case: 82). Let’s see how this can be shortened with ES6’s arrow functions: const totalYears = pilots.reduce((acc, pilot) => acc + pilot.years, 0); Now let’s say I want to find which pilot is the most experienced one. For that, I can use reduce as well: var mostExpPilot = pilots.reduce(function (oldest, pilot) { return (oldest.years || 0) > pilot.years ? oldest : pilot; }, {}); I named my accumulator oldest. My callback compares the accumulator to each pilot. If a pilot has more years of experience than oldest, then that pilot becomes the new oldest so that’s the one I return. As you can see, using .reduce() is an easy way to generate a single value or object from an array.
    231
    javascript filter method .filter()
    ``` What if you have an array, but only want some of the elements in it? That’s where .filter() comes in! Here’s our data: var pilots = [ { id: 2, name: "Wedge Antilles", faction: "Rebels", }, { id: 8, name: "Ciena Ree", faction: "Empire", }, { id: 40, name: "Iden Versio", faction: "Empire", }, { id: 66, name: "Thane Kyrell", faction: "Rebels", } ]; Say we want two arrays now: one for rebel pilots, the other one for imperials. With .filter() it couldn’t be easier! var rebels = pilots.filter(function (pilot) { return pilot.faction === "Rebels"; }); var empire = pilots.filter(function (pilot) { return pilot.faction === "Empire"; }); That’s it! And it’s even shorter with arrow functions: const rebels = pilots.filter(pilot => pilot.faction === "Rebels"); const empire = pilots.filter(pilot => pilot.faction === "Empire"); Basically, if the callback function returns true, the current element will be in the resulting array. If it returns false, it won’t be. ```
    232
    Combining .map(), .reduce(), and .filter() on javascript arrays
    ``` Since all three are called on arrays and since .map() and .filter() both return arrays, we can easily chain our calls. Let’s check out another example. Here’s our data: var personnel = [ { id: 5, name: "Luke Skywalker", pilotingScore: 98, shootingScore: 56, isForceUser: true, }, { id: 82, name: "Sabine Wren", pilotingScore: 73, shootingScore: 99, isForceUser: false, }, { id: 22, name: "Zeb Orellios", pilotingScore: 20, shootingScore: 59, isForceUser: false, }, { id: 15, name: "Ezra Bridger", pilotingScore: 43, shootingScore: 67, isForceUser: true, }, { id: 11, name: "Caleb Dume", pilotingScore: 71, shootingScore: 85, isForceUser: true, }, ]; Our objective: get the total score of force users only. Let’s do it step by step! First, we need to filter out the personnel who can’t use the force: var jediPersonnel = personnel.filter(function (person) { return person.isForceUser; }); // Result: [{...}, {...}, {...}] (Luke, Ezra and Caleb) With that we have 3 elements left in our resulting array. We now need to create an array containing the total score of each Jedi. var jediScores = jediPersonnel.map(function (jedi) { return jedi.pilotingScore + jedi.shootingScore; }); // Result: [154, 110, 156] And let’s use reduce to get the total: var totalJediScore = jediScores.reduce(function (acc, score) { return acc + score; }, 0); // Result: 420 And now here’s the fun part… we can chain all of this to get what we want in a single line: var totalJediScore = personnel .filter(function (person) { return person.isForceUser; }) .map(function (jedi) { return jedi.pilotingScore + jedi.shootingScore; }) .reduce(function (acc, score) { return acc + score; }, 0); And look how pretty it is with arrow functions: const totalJediScore = personnel .filter(person => person.isForceUser) .map(jedi => jedi.pilotingScore + jedi.shootingScore) .reduce((acc, score) => acc + score, 0); ```
    233
    MergeMap,You might also have heard about flatMap. FlatMap is an alias of mergeMap and behaves in the same way import { of, from } from 'rxjs'; import { map, mergeMap, delay, mergeAll } from 'rxjs/operators'; ``` const getData = (param) => { return of(`retrieved new data with param ${param}`).pipe( delay(1000) ) } ``` // using a regular map from([1,2,3,4]).pipe( map(param => getData(param)) ).subscribe(val => val.subscribe(data => console.log(data))); ``` // using map and mergeAll from([1,2,3,4]).pipe( map(param => getData(param)), mergeAll() ).subscribe(val => console.log(val)); ``` // using mergeMap from([1,2,3,4]).pipe( mergeMap(param => getData(param)) ).subscribe(val => console.log(val));
    https://medium.com/@luukgruijs/understanding-rxjs-map-mergemap-switchmap-and-concatmap-833fc1fb09ff Now let’s say there is a scenario where we have an Observable that emits an array, and for each item in the array we need to fetch data from the server. We could do this by subscribing to the array, then setup a map that calls a function which handles the API call and then subscribe to the result. This could look like the following: import { of, from } from 'rxjs'; import { map, delay } from 'rxjs/operators'; ``` const getData = (param) => { return of(`retrieved new data with param ${param}`).pipe( delay(1000) ) } ``` from([1,2,3,4]).pipe( map(param => getData(param)) ).subscribe(val => console.log(val); ur map function returns the value of the getData function. In this case that is an Observable. This does however create a problem because now we’re dealing with an additional Observable. To further clarify this: we have from([1,2,3,4]) as our ‘outer’ Observable, and the result of the getData() as our ‘inner’ Observable. In theory we have to subscribe to both our outer and inner Observable to get the data out. This could like this: import { of, from } from 'rxjs'; import { map, delay } from 'rxjs/operators'; ``` const getData = (param) => { return of(`retrieved new data with param ${param}`).pipe( delay(1000) ) } ``` from([1,2,3,4]).pipe( map(param => getData(param)) ).subscribe(val => val.subscribe(data => console.log(data))); As you can might imagine this is far from ideal as we have to call Subscribe two times. This is where mergeMap comes to the rescue. MergeMap essentially is a combination of mergeAll and map. MergeAll takes care of subscribing to the ‘inner’ Observable so that we no longer have to Subscribe two times as mergeAll merges the value of the ‘inner’ Observable into the ‘outer’ Observable. This could look like this: This already is much better, but as you might already guessed mergeMap would be the best solution for this. Here’s the full example:
    234
    SwitchMap
    SwitchMap has similar behaviour in that it will also subscribe to the inner Observable for you. However switchMap is a combination of switchAll and map. SwitchAll cancels the previous subscription and subscribes to the new one. For our scenario where we want to do an API call for each item in the array of the ‘outer’ Observable, switchMap does not work well as it will cancel the first 3 subscriptions and only deals with the last one. This means we will get only one result. The full example can be seen here: ``` const getData = (param) => { return of(`retrieved new data with param ${param}`).pipe( delay(1000) ) } ``` // using a regular map from([1,2,3,4]).pipe( map(param => getData(param)) ).subscribe(val => val.subscribe(data => console.log(data))); ``` // using map and switchAll from([1,2,3,4]).pipe( map(param => getData(param)), switchAll() ).subscribe(val => console.log(val)); ``` // using switchMap from([1,2,3,4]).pipe( switchMap(param => getData(param)) ).subscribe(val => console.log(val)); While switchMap wouldn’t work for our current scenario, it will work for other scenario’s. It would for example come in handy if you compose a list of filters into a data stream and perform an API call when a filter is changed. If the previous filter changes are still being processed while a new change is already made, it will cancel the previous subscription and start a new subscription on the latest change. An example can be seen here: import { of, from, BehaviorSubject } from 'rxjs'; import { map, delay, switchAll, switchMap } from 'rxjs/operators'; ``` const filters = ['brand=porsche', 'model=911', 'horsepower=389', 'color=red'] const activeFilters = new BehaviorSubject(''); ``` ``` const getData = (params) => { return of(`retrieved new data with params ${params}`).pipe( delay(1000) ) } ``` ``` const applyFilters = () => { filters.forEach((filter, index) => { ``` ``` let newFilters = activeFilters.value; if (index === 0) { newFilters = `?${filter}` } else { newFilters = `${newFilters}&${filter}` } ``` activeFilters.next(newFilters) }) } // using switchMap activeFilters.pipe( switchMap(param => getData(param)) ).subscribe(val => console.log(val)); applyFilters() As you can see in the console getData is only logging once with all the params. This saved us 3 API calls.
    235
    ConcatMap
    The last example is concatMap. As you might expect, concatMap also subscribes to the inner Observable for you. But unlike switchMap, that unsubscribes from the current Observable if a new Observable comes in, concatMap will not subscribe to the next Observable until the current one completes. The benefit of this is that the order in which the Observables are emitting is maintained. To demonstrate this: import { map, delay, mergeMap, concatMap } from 'rxjs/operators'; ``` const getData = (param) => { const delayTime = Math.floor(Math.random() * 10000) + 1; return of(`retrieved new data with params: ${param} and delay: ${delayTime}`).pipe( delay(delayTime) ) } ``` ``` // using a regular map from([1,2,3,4]).pipe( map(param => getData(param)) ).subscribe(val => val.subscribe(data => console.log('map:', data))); ``` // using mergeMap from([1, 2, 3 ,4]).pipe( mergeMap(param => getData(param)) ).subscribe(val => console.log('mergeMap:', val)); // using concatMap from([1, 2, 3 ,4]).pipe( concatMap(param => getData(param)) ).subscribe(val => console.log('concatMap:', val)); The getData function has a random delay between 1 and 10000 milliseconds. If you check the logs you can see that the map and mergeMap operators will log whatever value comes back and don’t follow the original order. On the other hand the concatMap logs the values in the same value as they were started.
    236
    RxJs operators: | Map, mergeMap,switchMap,concatMap;
    Mapping data to the format you need is a common task. RxJS comes with a few very neat operators that help you get the job done. To recap: map is for mapping ‘normal’ values to whatever format you need it to be. The return value will be wrapped in an Observable again, so you can keep using it in your data stream. When you have to deal with an ‘inner’ Observable it’s easier to use mergeMap, switchMap or concatMap. Use mergeMap if you simply want to flatten the data into one Observable, use switchMap if you need to flatten the data into one Observable but only need the latest value and use concatMap if you need to flatten the data into one Observable and the order is important to you
    237
    List of HTTP status codes
    https://en.wikipedia.org/wiki/ List_of_HTTP_status_codes#4xx_Client_errors This is a list of Hypertext Transfer Protocol (HTTP) response status codes. Status codes are issued by a server in response to a client's request made to the server. It includes codes from IETF Request for Comments (RFCs), other specifications, and some additional codes used in some common applications of the HTTP. The first digit of the status code specifies one of five standard classes of responses. The message phrases shown are typical, but any human-readable alternative may be provided. Unless otherwise stated, the status code is part of the HTTP/1.1 standard (RFC 7231).[1] The Internet Assigned Numbers Authority (IANA) maintains the official registry of HTTP status codes.[2] All HTTP response status codes are separated into five classes or categories. The first digit of the status code defines the class of response, while the last two digits do not have any classifying or categorization role. There are five classes defined by the standard: 1xx informational response – the request was received, continuing process 2xx successful – the request was successfully received, understood, and accepted 3xx redirection – further action needs to be taken in order to complete the request 4xx client error – the request contains bad syntax or cannot be fulfilled 5xx server error – the server failed to fulfil an apparently valid request
    238
    links:Error Handling with Rxjs CatchError
    https://blog.angular-university.io/rxjs-error-handling/ https://www.positronx.io/angular-error- handling-tutorial-with-examples/ https://www.techiediaries.com/handle-angular-9-8-7-httpclient-errors-with-rxjs-catcherror-and-throwerror/ https://medium.com/angular-in-depth/expecting-the-unexpected-best-practices-for-error-handling-in-angular-21c3662ef9e4
    239
    links:Http Interceptors | and using multiple interceptors
    https: //angular.io/api/common/http/HttpInterceptor https: //ultimatecourses.com/blog/intro-to-angular-http-interceptors https: //medium.com/@swapnil.s.pakolu/angular-interceptors-multiple-interceptors-and-6-code-examples-of-interceptors-59e745b684ec https: //medium.com/angular-in-depth/top-10-ways-to-use-interceptors-in-angular-db450f8a62d6
    240
    links to read:Angular newsletters
    https://indepth.dev/
    241
    To catch synchronous exceptions in the code
    Catch them if you can To catch synchronous exceptions in the code, we can add a try/catch block. If an error is thrown inside try then we catch it and handle it. If we don’t do this, the script execution stops. ``` try { throw new Error('En error happened'); } catch (error) { console.error('Log error', error); } console.log('Script execution continues'); ```
    242
    Default error handler interface
    https://angular.io/api/core/ErrorHandler
    243
    ng generate class classaname
    https://angular.io/cli/generate
    244
    we can not inject in the Error Hanlder implementation constructor /global-error-handling-with-angular2 we need @Injectable() decorator for the class
    There is one problem though, since error handling is really important it needs to be loaded first, thus making it not possible to use dependency injection in the constructor to get other services such as the error handle api service to send the server our error details. As a result, we have to manually call the injector with the service name in the execution of the handleError function like: https://medium.com/@amcdnl/global-error-handling-with-angular2-6b992bdfb59c
    245
    Client-side errors
    On the client side, when something unexpected happens, a JavaScript Error is thrown. It has two important properties that we can use. message — Human-readable description of the error. stack — Error stack trace with a history (call stack) of what files were ‘responsible’ of causing that Error. Typically, the message property is what we show the user if we don’t write our error messages.
    246
    Server-side errors
    On the server-side, when something goes wrong, a HttpErrorResponse is returned. As with the JavaScript error, it has a message property that we can use for notifications. It also returns the status code of the error. These can be of different types. If it starts with a four (4xx), then the client did something unexpected. For example, if we get the status 400 (Bad Request), then the request that the client sent was not what the server was expecting. Statuses starting with five (5xx) are server errors. The most typical is the 500 Internal Server Error, a very general HTTP status code that means something has gone wrong on the server, but the server could not be more specific on what the exact problem is. With different kinds of errors, it is helpful with a service that parses messages and stack traces from them.
    247
    specify input parametes as multiple types
    https://stackoverflow.com/questions/ 12776625/can-i-specify -parameter-type-as-one-of-many-types -instead-of-any-type-in-typescr Typescript 1.4 introduced Union Types so the answer now is yes, you can. ``` function myFunc(param: string[] | boolean[] | number[]): void; Using other type than the ones specified will trigger a compile-time error. ``` If you want an array of multiple specific types, you can use Union Types for that as well: ``` function myFunc(param: (string|boolean|number)[]): void; Note that this is different from what OP asked for. These two examples have different meanings. ``` also in global error handler class: import { HttpErrorResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ErrorHandler } from '@angular/core'; @Injectable() export class GlobalErrorHandler implements ErrorHandler { /** * */ constructor() {} handleError(error: Error | HttpErrorResponse): void { console.log('From GLobal Error Handler'); throw error; } }
    248
    if you have catch error, or finalize in pipe, or three parameters for subscripion completion either in http request or on subscription in component the default errorHandler implementation will be overridden
    if you have catch error, or finalize in pipe, or three parameters for subscripion completion either in http request or on subscription in component the default errorHandler implementation will be overridden
    249
    file upload in angular
    http: //www.angulartutorial.net/2018/01/file-upload-validation-angular-4.html https: //stackoverflow.com/questions/49970970/angular-5-file-upload-failed-to-set-the-value-property-on-htmlinputelement https: //stackblitz.com/edit/angular-hhgm9w?file=src%2Fapp%2Fapp.component.html https: //medium.com/@amcdnl/file-uploads-with-angular-reactive-forms-960fd0b34cb5 https: //netbasal.com/how-to-implement-file-uploading-in-angular-reactive-forms-89a3fffa1a03
    250
    Custom control in angular
    https://netbasal.com/angular-custom-form-controls-made-easy-4f963341c8e2
    251
    Three Ways to Dynamically Alter your Form Validation in Angular
    https://netbasal.com/three-ways-to-dynamically-alter-your-form-validation-in-angular-e5fd15f1e946
    252
    xlsx package
    https: //www.npmjs.com/package/xlsx https: //stackoverflow.com/questions/24395693/how-to-set-cell-width-when-export-xlsx-files-with-js-xlsx https: //github.com/SheetJS/sheetjs/issues/1473
    253
    enums in typescript
    https://www.typescriptlang.org/docs/handbook/enums.html
    254
    add multiple elements to array
    https: //stackoverflow.com/questions/14723848/push-multiple-elements-to-array https: //www.tutorialspoint.com/how-to-add-multiple-objects-to-a-single-array-list-in-javascript
    255
    Setting Configuration files in angular
    https://www.google.com/search?q=configuration+setting+in+angular&rlz=1C1GCEU _enUS820US820&oq=configuration+ setting+in+angular&aqs=chrome.. 69i57j0i22i30i457.13998j0j7&sourceid=chrome&ie=UTF-8 https: //www.codemag.com/Article/1801021/Configuration-Settings-for-Angular-Applications https: //medium.com/most-wanted-experts/angular-application-configurations-best-practices-2e28514b9b4e https: //www.codeproject.com/Articles/1196924/Configuration-Settings-for-Angular-Applications https: //devblogs.microsoft.com/premier-developer/angular-how-to-editable-config-files/
    256
    Experimental warning for Node | just needed to upgrade node.js to 14.5 from 13.7
    (node: 3956) ExperimentalWarning: Conditional exports is an experimental feature. This feature could change at any time https: //github.com/nodejs/modules/issues/485 https: //nodejs.org/api/esm.html#esm_conditional_exports
    257
    update Node js version
    https: //phoenixnap.com/kb/update-node-js-version https: //nodejs.org/en/download/package-manager/ https: //nodejs.org/en/ https: //phoenixnap.com/kb/update-node-js-version
    258
    Dependencies
    https://angular.io/guide/build#configuring-commonjs-dependencies
    259
    ng lint
    https://angular.io/cli/lint ng lint Runs linting tools on Angular app code in a given project folder. ng lint [options] ng l [options] mode_edit codeDescription Takes the name of the project, as specified in the projects section of the angular.json workspace configuration file. When a project name is not supplied, it will execute for all projects. The default linting tool is TSLint, and the default configuration is specified in the project's tslint.json file.
    260
    npm fun
    https://docs.npmjs.com/cli/v6/commands/npm-fund
    261
    call to signature means having the return type
    https://stackoverflow.com/questions/25459136/what-does-it-mean-when-tslint-says-expected-callsignature-to-have-a-typedef
    262
    canDeactivateRouteGuard
    https://www.tektutorialshub.com/angular/angular-candeactivate-guard/