Angular Flashcards
Pre-requisites for running angular app
install node.js, that is what angular CLI runs with
Creating new app
ng new appname –defaults = to create app with defaults
cd folder
npm start
new app with single typescript file
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
@component -decorator
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
Directives in angular
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.
Creating a new Directive
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>
Directives
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
npm start
it looks at package.json; script - sees that start - refers to ng serve and runs that command
Changing port that angular runs from 4200
npm start – –port 4201 ; it builds the application
http://localhost:4201/
Structure of application - src - app folder
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
spec.ts
to test your components
assets folder
if you have images or fonts put them here; it will automatically deploy for you
files index.html and main.ts
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
package.json
our dependencies for the application lives and the scripts
angular is listed here as we are using it
scripts like npm start are listed
AppModule.ts
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 { }
AppComponent.ts
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>
creating a component
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
dry run
ng g c heroes -d
ngOnInit()
for start up code
Interpolation
Display models with {{model}}
<div> Hello {{hero.name}} </div> - this is read only data
one way property binding
<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
attribute binding
<div></div>
if there is no DOM property then we use attribute binding
Two-way data binding
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
Event binding
Execute when an event occurs , wrap with ()
(target)=”expression” or on-target=”expression”
No
if the button is clicked onNo() function is executed
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
Rendering a list ; structural director; *ngFor
{{ hero.FirstName }}
{{ hero.LastName }}
heroes - this is a an array in angular
<ul>
<li>{{hero.name}}</li>
</ul>
similarly we could have table and ngFor on tr element
*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 <div> you selected {{selectedHero.firstName}} </div> if selectedHero = null or does not have value then does not show up or undefined if selectedHero has value or truthy
Class Binding
for styles class binding; we could use the dot syntax or class binding syntax [class.active]="isActive" ; class="{classname: expression}" <div></div>; if isActive is true then apply active class
<div class="btn"></div> if isActive is true then apply foo class if isDisabled is true then apply bar class
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
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” } ]
<pre> {{heroes | json}}</pre> [ { "id": 10, "name": "John" }, { "id": 20, "name": "Peter" }, { "id": 30, "name": "Saint" } ] Pre - maintains the spacings
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: ` <p> heroes works! </p>
<div> <ul> <li>{{hero.name}}</li> </ul> </div> <div> you selected {{selectedValue}} </div> `, 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; }
}
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
@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 } }
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
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
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';
ngx-logger
https: //www.npmjs.com/package/ngx-logger
https: //onthecode.co.uk/angular-logging-made-easy-with-ngx-logger/
src/Environments/environment
for prod or dev
angular.json
this has file replacements during the production release
“fileReplacements”: [
{
“replace”: “src/environments/environment.ts”,
“with”: “src/environments/environment.prod.ts”
}
],
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.
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.
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
}),
To run angular app locally with production settings
ng serve –configuration=production.
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
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.
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.
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.
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)
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’;
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 } //
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.
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.
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.
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
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.
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.
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 } //
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
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.
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
<h1>Angular Router</h1>
<a>Crisis Center</a>
<a>Heroes</a>
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.
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.
using $ may be string interpolation in angular
this.logger.log(${this.route.outlet} is the router outlet
);
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.
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.
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);
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.
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.
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.
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.
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
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.
JavaScript Promises Versus RxJS Observables
https://coryrylan.com/blog/javascript-promises-versus-rxjs-observables
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
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 = ''; } });
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.
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
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.
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:
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.
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.
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
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
<img></img>
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
<p>[ngClass] binding to the classes property making this blue</p>
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
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.
WORKSPACE CONFIG FILES .editorconfig
Configuration for code editors. See EditorConfig.
WORKSPACE CONFIG FILES .gitignore
Specifies intentionally untracked files that Git should ignore.
WORKSPACE CONFIG FILES README.md
Introductory documentation for the root app.
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.
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.
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.
WORKSPACE CONFIG FILES src/
Source files for the root-level application project.
WORKSPACE CONFIG FILES node_modules/
Provides npm packages to the entire workspace. Workspace-wide node_modules dependencies are visible to all projects.
WORKSPACE CONFIG FILES tsconfig.json
Default TypeScript configuration for projects in the workspace.
WORKSPACE CONFIG FILES tslint.json
Default TSLint configuration for projects in the workspace.
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.
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.
APP SUPPORT FILES app/
Contains the component files in which your application logic and data are defined. See details below.
APP SUPPORT FILES assets/
Contains image and other asset files to be copied as-is when you build your application.
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
APP SUPPORT FILES favicon.ico
An icon to use for this application in the bookmark bar.
by default it is A for angular apps
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<link></link> tags here manually.
it has <app-root></app-root> which loads the application
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.
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.
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.
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.