Angular Theory
limjy
Posted on April 17, 2021
Summary of Angular theory stuff for myself.
Some stuff to know
HTML DOM
HTML Document Object Model.
DOM is object-orientated representation of webpage which can be modified with scripting language like JS. Further reading
TOC
Angular Intro
npm + typescript
- NPM and node_modules folder
- package.json file
- package.json VS package.lock
- What is Typescript?
- Advantages of angular CLI
angular CLI questions
Angular Architecture questions
- What is the architecture of Angular?
- What are directives in Angular?
- Component & Module in Angular
- What are decorators in angular
- What is a template in Angular?
- What is Data Binding in Angular?
- How is a SPA achieved in Angular?
- What is routing in Angular?
- How to implement routing in angular?
- What is lazy-loading?
- How to implement lazy loading?
- What are services in Angular?
- Service VS Component
- What is dependency Injection
- How to implement dependency injection
- Benefits of Dependency Injection
Children stuff (ViewChild, ViewChildren, ContentChild, ContentChildren)
- ViewChild & ViewChildren
- Template reference variable
- What is content projection?
- ContentChild & ContentChildren
- Static flag
- ViewChild, ViewChildren VS ContentChild, ContentChildren
Angular Lifecycle questions
- Importance of component lifecycle?
- Events & sequence of component lifecycle?
- constructor VS ngOnInit?
HTTP
Passing Data
Pipe
- What is Angular Pipe?
- How to make custom pipe in Angular?
- Change Detection in Angular pipe
- Pure VS impure angular pipe
RxJS
- Synchronous VS Asynchronous
- What is RxJS?
- What are Observables & observers?
- Importance of subscribe in RxJS
- How to unsubscribe?
- Concept of operators
What is angular
Javascript framework.
Main help:
Helps bind view (HTML) to model (object). this helps developer implement MVC framework. Pure JS requires lots of code.
Main features:
- SPA. angular helps developer implement single page application with routing. (url will change but only 1 index.html)
- Dependency Injection. (Angular helps developer instantiate components) eg. to inject service into component just put it into constructor method.
Angular VS AngularJS
tbh im not very sure about this, I try not to work with AngularJS lmao
- Javascript VS Typescript
- CLI Builder
- can use Angular CLI to build components & services
- lazy-loading
- load only certain modules when needed. loading is only done when user navigates to route of respective module see more
What are directives in Angular?
Instructions in HTML that tells angular how to transform the HTML DOM
3 main directives (SAC)
- Component Directives
- Structural Directives
- Attribute Directives
Take note: a component is technically a directive
Component Directives
directives with templates. its like user control
A component is technically a directive. @Component
extends the @Directive
.
e.g. declare a custom component my-grid. component directive is then <my-grid></my-grid>
More information in documentation
Structural Directives
Change structure of elements (add / remove DOM)
eg. NgIf, NgFor NgSwitch (switch case for ngif)
Attribute Directive
Change behaviour & appearance of elements
eg. NgStyle, NgClass
Read more in this article
NPM & node_modules folder
NPM = node pacakge manager.
Helps make installization of JS framework libraries easy.
node_modules = folder where all packages are installed.
It also acts like a cache. when developer imports libraries without specific path nodeJs will look at node_modules folder
Taken from sitepoint & SO
global VS local
package.json file
states all the JS references (i.e. dependencies of the project, library name). So developer can quickly install all dependencies at one shot with npm install
.
node_modules can be re-created from scratch by doing npm install
package.json VS package-lock.json
package.json record minimum version of libraries your application requires. It also defines project properties, author etc.
package-lock only used to lock dependencies to specific version number. It records exact version of each installed package.
What is Typescript?
superset of Javascript.
- adds types to JavaScript
- Object-oriented programming environment which compiles to JS
This results in
- less errors
- better code quality / productivity ???
** at the end of the day, TS will be compile to JS**
more information on guru99
- errors are pointed out at compile time (code needs to be compiled)
- TS uses concepts like types and interfaces to describe data
- TS needs compilation. must compile to JS.
Importance / Advantages of angular CLI
Helps developer generate boiler plate code as opposed to starting from scratch
- generate ready made project
ng new my-app
(make src files, module file) - generate ready-made schematics (eg. components / services / directives)
ng generate service/component
documentation
Importance of Component & Module in Angular
Components are the main building blocks in angular. Each component consists of :
- HTML template (declares what renders on page)
- typescript class that defines behaviour
- CSS selector that defines how component is used in a template
- CSS styles applied to template From documentation
Component VS Module
Component:
- controls view (html)
- communicate with other components and services to bring functionality to applucation
Modules are:
- logical groups of components
Reference: SO answer
What is Decorator(Annotation / Metadata) in angular
tells Angular what kind of class it is.
Above the class declaration
eg. @Component
-> Angular Component. @NgModule
-> Angular Module
** may also be asked how to create component and module in angular) **
must be decorators when declaring components and modules in angular
What is a Template in Angular?
HTML view of Angular where you can write directives
There are two ways you can write templates:
- inline (define it in
@Component({template: <<here>>})
directive) - separate HTML file (define it in component templateUrl)
Further reading here
What is Data Binding in Angular?
How component and view communicate with each other.
Documentation and more details
- Interpolation ------
{{expression}}
- property binding-----
[target]=expression
- event binding--------
(target)=statement
- two-way binding-----
[(ngModel)]
interpolation
one-way from component to view
Data flows from component to view. can stick it with HTML (one-way)
property
one-way biding from component.
Data flow from component to viewsets specific element property.
event binding
one-way. from event / view to component.
event in view triggers a function in component. Listends for an element change event
two-way binding
two-way. combines property binding with event binding
set event in component. if some event happens in view it can trigger function in component.
e.g. most commonly used in template forms
More details in documentation
For two-way binding to work, @Output
must use pattern inputChange
where input
is name of @Input
property
e.g.
export class SizerComponent {
@Input() size: number | string;
@Output() sizeChange = new EventEmitter<number>();
resize(delta: number) {
this.size = Math.min(40, Math.max(8, +this.size + delta));
this.sizeChange.emit(this.size);
}
}
using the two-way binding looks lie this:
<app-sizer [(size)]="fontSizePx"></app-sizer>
Explain architecture of Angular?
Angular consists of 7 main building blocks:
- Template (HTML view)
- Component (binds view an model)
- Binding (how component & template talk to each other)
- Module (groups components logically)
- Directives (change style / behaviour of DOM)
- Service (share common logic across the project project)
- Dependency Injection (injects instances into constructor) (e.g. injecting services into component - just put into component constructor)
Further explanation in documentation
What is SPA?
Single page application
A Single page application is a web application /website taht ineracts with uer by dynamically rewriting current web page with new data from webserver. wiki
This means the main UI gets loaded once and the other features are loaded on demand / depending on user actions.
In production, this means that there is just 1 index.html file with CSS bundle and JavaScript bundle.
This is advantageous especially when there is rich client-side functionality. SPA can load more quickly since full page reloads are rare.
e.g. page with header, footer, drawer. in SPA only the stuff in between is loaded instead of the entire page. This gives performance improvements
More information about SPA on angular university blog
How to implement SPA in Angular
Routing
Angular routing is a simple collection with two things:
- URL
- Component to load when URL is called
helps to define navigation for angular application. It maps URL-like paths to views instead of pages. So when user moves from one screen / url to another, the application loads components not an entirely new page.
What is routing in Angular
In Angular, routes comprise of :
- path (URL path)
- Component
- (optional) redirectTo path
Routes map a URL path to a component.
It helps users navigate from one view to another as users perform tasks on application
Helps developer respect SPA since only components in page are changing, entire page is not reloaded.
Taken from: pluralsight & smashingmagazine
How to implement routing in angular.
- define collection of routes in angular --> map url paths to components
- define router outlet --> where the component will be displayed
- [routerLink] in HTML OR this.router.navigate(url) in TS file --> allows user to navigate to different route / view
What is lazy loading
Loading on demand.
Loading only the necessary HTML, CSS & JS files when needed. Loading other components only when needed (i.e. when user performs certain actions)
How to implement lazy loading?
- Divide project into separate modules
- declare
loadChildren
property in route object
What are services in Angular?
Service helps developer share common logic / common functionality across components
Service VS Component
From documentation
Components is to enable the user experience & nothing more
Component should: present properties and methods for data binding to mediate between template (view) & application logic (model)
Components should delegate other tasks (o.e. fetching data from server, validating user input) to a service.
The tasks in service can also be shared with other components vis dependency injection
What is dependency Injection?
application design pattern
Developer does not need to create object instances (no need to instantiate service let service: ExampleService = new ExampleService()
instead, Angular injects is via the constrcutr
export class ExampleComponent{
constructor (private service: ExampleService) {
this.service.doSomething();
}
}
taken from documentation
How to implement dependency Injection in Angular?
There are 3 ways to provide a service
- root service is provided at root level, angular creates a single, shared (i.e. singleton) instance of service & injects it into any class asking for it.
Injectable root decorator is provided in service class
@Injectable({
providedIn: 'root',
})
this is auto-generated with ng generate service
TO only provide service to certain module change root
to ExampleModule
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'any',
})
export class UserService {
}
With providedIn: any
all eagerly loaded instance share singleton instance, but lazily loaded modules each get their own unique instance
- provide in module
register service in
providers
array in NgModule
@NgModule({
providers: [
ExampleService,
Logger
],
...
})
If NgModule is root AppModule,
ExampleService
will be singleton and available throughout the app.
Reference
Importing service in AppModule
AND lazily loaded module, the app can generate multiple instance of a service.
- Component level registering provider at component level, you get a new instance of service with each new instance of component
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
Further reading in documentation
Benefits of Dependency Injection
Decouples class dependencies.
can change dependencies of service class without changing code in all component classes. If instantiation of service class is in component, must change all the service instantiation code.
i.e. just change arguments in service constructor. no need to change anywhere else
ng serve VS ng build
ng serve
- builds angular application in memory
ng build
- builds application in harddisk. put all the compiled code in the /dist
folder
--prod flag?
--prod
flag ensures you build applciation for production. compresses JS files, removes comments. makes application ready for production.
Importance of component lifecycle?
directives have lifecycle too
tldr;
Developers can tap into key events of component lifecycle and write custom code by implementing lifecycle hook interfaces. (eg. ngOnInit()
)
Greater details in documentation
Component instance has lifecycle when angular instantiates component class & renders component view till angular destroys component and removes rendered template from DOM.
Dev can use lifecycle hook methods to tap into key events of lifecycle to init new instances / clean up before deletion of instances.
events & sequence of component life cycle?
Here is a great medium article by Shivani that goes in-depth into the angular lifecycle.
Angular Documentation offers list of lifecycle event sequence
Two types of events
- Events fired when component is first loaded
- Events fired on change detection
List of lifecycle events
(events called ONCE are italicized)
- constructor (more of a typescript event, not an angular event)
- ngOnChanges (also called when data bound input property
@Input
changes). This event happens very frequently -
ngOnInit (data bound properties displayed on screen / sets component's
@Input
properties) - ngDoCheck() (fires immediately after ngOnChanges() on every change detection run)
-
ngAfterContentInit (after Angular projects external content into component's view) related to
<ng-check>
- ngAfterContentCheck (check content projected)
- ngAfterViewInit (after angular initializes component's views & child views)
- ngAfterViewChecked (after angular checks component's view & child views)
- ngOnDestroy (cleanup before angular destroys component)
three parts
- kick start event (change detection) (ngOninit, ngDoCheck)
- projected content event fires (ngAfterContentInit, ngAfterContentChecked)
- events of component view fires (ngAfterViewInit, ngAfterViewChecked)
constructor VS ngOnInit()?
- constructor - typescript concept, invoked by typescript
- ngOnInit - angular concept / event, invoked by angular framework
Sequence:
- constructor is fire.
- view and component initialized, binding happens
- ngOnInit (after component is initializes, access to DOM elements)
Constructor:
- initialize class variables
- dependency injection
ngOnInit:
- access to class variables
- access to
@Input
variables
Accessing, @Input
or from constructor will give undefined
.
More information in this SO answer
@ViewChild
only access in ngAfterViewInit
ViewChild & ViewChildren
@ViewChild
: Reference ONE HTML element / DOM element in the component
@ViewChildren
: Reference a collection of elements
If multiple elements detected by @ViewChild
, it will only reference the first element.
Template Reference Variable
Template variables help developer use data from one part of template in another part of template
<input #phone placeholder="phone number" />
<!-- lots of other elements -->
<!-- phone refers to the input element; pass its `value` to an event handler -->
<button (click)="callPhone(phone.value)">Call</button>
To use template reference variable with ViewChild
<div #div1> this div </div>
@Viewchild('div1',{static: false}) div: ElementRef
Further reading here
What is content projection?
Projection: project HTML content / component content from parent to child.
<ng-content></ng-content>
Allows you to insert a shadow DOM as Input to a component.
@Input
only allows you to pass simple string / objects to components. <ng-content>
allows you to pass things HTML elements, another component.
<app-component>
<h1>Header</h1>
<p>paragraph</p>
</app-component>
Multi content projection: content projection slot
GreetComponent
<div class="container">
<ng-content> </ng-content>
<ng-content select="h1"></ng-content>
<p>welcome text</p>
<ng-content select=".content"></ng-content>
</div>
Parent Content
<div>
<greet>
<h3> everything else </h3>
<h1> Header </h1>
<span class="content"> something </span>
</greet>
</div>
output after content projection is
<div>
<div class="container">
<h3> everything else </h3>
<h1> Header </h1>
<p>welcome text</p>
<span class="content"> something </span>
</div>
</div>
Content Child & Content Children
access projected content
CardComponent.html
<div class="card">
<ng-content select="header"></ng-content>
<ng-content select="content"></ng-content>
<ng-content select="footer"></ng-content>
</div>
CardComponent.ts
@ContentChild("header") cardContentHeader: ElementRef;
ParentComponent.html
<card>
<header><h1 #header>Angular</h1></header>
<content>One framework. Mobile & desktop.</content>
<footer><b>Super-powered by Google </b></footer>
</card>
tektutorialshub provides a concise write-up
Static flag
static is false as default behaviour.
static is false because we would like query to be resolved every change detection
Angular documentation & SO describes the flag in greater details
ViewChild, ViewChildren, ContentChild, ContentChildren
ViewChild: access DOM elements from its own view
ContentChild: access DOM elements from another view, access DOM elements projected by someone else
(e.g. @ContentChild
is on CardComponent.ts, but the project content is from ParentComponent.html)
ViewChildren: collection of ViewChild
ContentChildren: collection of ContentChildren
Make HTTP calls in Angular
- import HttpClient from
@angular/common/http
- import HttpModule in Angular Module
- create HttpClient object via dependency injection
constructor(public http:HttpClient)
- make post / get class with HttpClient
this.http.post(URL, data).subscribe(res => successfunc(res), err => errfunc(err)
- subscribe to Http.post / Http.get. Subscribe takes 2 inputs: success function and error function
Need of Subscribe function
Provide success / error methods if HTTP calls are successful / fail.
Also, if there is no async pipe, subscribe is needed for an observable to execute
Handling errors in HTTP calls
- error callback of subscribe method
-
catchError
function in pipe. (catchError must return a new observable or throw an error) when throwing new error, error thrown will propate to subscriber More details on tekturotials
The second method achieves separation of concern in Angular
Additionally,
Chaining multiple observables (one after another
-
catchError
keeps observable alive. If inner observable has errors, outer observable will still continue (coz it received an observable) Combinging multiple observables (execute multiple observables) - allows arrays of observables to complete. Else if only 1 observable fail, all will fail, with
catchError
it will allow observable to complete and emit something.
Pass Data between components & routes
Parent Child component
@Input
: Parent -> child
@Output
: Child -> parent
@ViewChild
:Data between routes -> Routing Query Params
this.route.navigate(['url'],
{queryParams: {
name: 'myname'
}
});
- Services more of global data / storing more of sharing global data via singleton service
- create service
- inject service into components
access service data
Browser
*global data *
Local Storage / temp storage
Good practice to pass data using services
Sharing data VS passing data
If you are just passing data from one component to another, should avoid using service / global variables.
Other components may modify global variables. Code can become quite messy.
What is the need for Angular Pipes?
Pipes transform data on Angular UI expressions
Angular has some inbuilt pipes:
- AsynPipe : read object from asynchronous source (impure by default)
- JsonPipe: convert object to json string
- KeyValuePipe: can use in ngFor to iterate keys and values of object
- DatePipe: fomat date
- CurrencyPipe: number -> currency string
Example:
<p>The hero's birthday is {{ birthday | date:"MM/dd/yy" }} </p>
You can also chain pipes (will implement first pipe then second pipe to the output of first pipe)
{{ birthday | date | uppercase}}
How to make custom pipes in Angular?
- Use
@Pipe
to mark class as a pipe - Implement PipeTransform interface
- Implements transform method.
@Pipe({name: 'uselessPipe'})
export class uselessPipe implements PipeTransform {
transform(value: string, before: string, after: string): string {
let newStr = `${before} ${value} ${after}`;
return newStr;
}
}
{{ user.name | uselessPipe:"Mr.":"the great" }}
Change detection in angular pipe.
Data is primitive input value (string, number) OR object reference as input (Date / Array)
Angular executes pipe whenever it detects change for the input value of referenceChange something inside a composite object (e.g. month of a date, element of array, object property)
useimpure
pipe
Referenced from Angular documentation
Detecting pure changes to primitives and object references
Angular pipes are pure by default. Angular executes pipe only when it detects pure change to input value. Pure change is either:
- change to pimitive input value (
string
,number
,boolean
,symbol
) - changed object reference (
Date
,Array
,Function
,Object
)
In Pure pipe, Angular ignore changes within component object (eg. new added elemtn of existing array) because object reference did not change.
Example:
<div *ngFor="let hero of (heroes | flyingHeroes)">
{{hero.name}}
</div>
@Pipe({ name: 'flyingHeroes' })
export class FlyingHeroesPipe implements PipeTransform {
transform(allHeroes: Hero[]) {
return allHeroes.filter(hero => hero.canFly);
}
}
If user adds flying heroes, it will not be updated becuase reference to the array has not changed so angular does not update display. there are two ways to cirucmvent this
- change object reference replace array with new array containing new changed elements, input new array to pipe.
- make pipe detect impure changes set pure flag to false
@Pipe({
name: 'flyingHeroesImpure',
pure: false
})
What is change detection
Mechanism by which Angular sychronizes state of application UI with state of data
When component data is updated (e.g. from user event/ application logic), values bound to DOM properties in the view can change. The change detector is responsible for updating the view to reflect the current data model.
Reference: Angular documentation
Synchronous VS Asynchronous
Synchronous code is executed in sequence.
When one statement is executing nothing else can happen.
Asynchronous code doesn’t have to wait – your program can continue to run.
Asynchronous code is hard to achieve in Synchronous JS, developer is unsure how long code will take to finish (how long will it take to download image from API?)
So code like this:
let response = fetch('myImage.png'); // fetch is asynchronous
let blob = response.blob();
// display your image blob in the UI somehow
blob may be undefined.
Async JS has 2 main code styles:
- callbacks (old-styles)
- promise (new-style)
Async JS has two models: ( more details on RxJS
- Pull mode (consumer is king, consumer decides when it receives data from producer, producer is unaware when data will be delivered)
- Push model (producer is king, it determines when to send data to consumer)
Promises & observable follow the push model.
Promise (producer) delivers resolved value to registered callbacks (consumer)
more information here and on MDN
What is RxJS?
RxJS stands for Reactive Extensions for JavaScript
It is to handle asynchronous data streams
eg. async data source(HTTP data, timer) may take 1 second or 15 seconds to come. Then application should have listener
(e.g. http response, data comes in small time intervals)
RxJs helps you to handle asynchronous data streams easily.
What are Observables & observers?
Observable is a Push system for Javascript. It is a producer of multiple values "pushing" them to observers (consumers).
Observable can give multiple values either synchronously or asynchronously.
this freecodecamp article has a very comprehensive introduction
Observable has 4 main stages
- Creation
- Subscription
- Executing
- Disposing
Importance of subscribe in RxJS
Each call to observable.subscribe
triggers its own indepdendent set up for that given subscriber.
RxJS: starts an "Observable execution" an deliver values / events to observer of execution.
Angular: Observable instance only begins publishing values when someone subscribes to it.
How to unsubscribe (Destroy phase of Observable)
Taken from RxJS documentation
const subscription = observable.subscribe(x => console.log(x));
subscription.unsubscribe();
Since Observable exeuctions may be infinite and its common for observer to abort execution in finitetime, we need API for cancelling execution. When execution is stopped / cancelled, we can avoid wasting computation power / memory resources.
Explain concept of operators with sample code
Operators are functions.
There are 2 types of operators:
- Pipeable operator takes in observable as input and output is also an observable. pre-processing logic, can transform data in observable.
- creation operator can be called as standalone functions to create new Observable
Taken from RxJS documentation
Posted on April 17, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024