DEV Community

loading...

Angular Theory

jing profile image limjy Updated on ・18 min read

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

angular CLI questions

Angular Architecture questions

Children stuff (ViewChild, ViewChildren, ContentChild, ContentChildren)

Angular Lifecycle questions

HTTP

Passing Data

Pipe

RxJS

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:

  1. SPA. angular helps developer implement single page application with routing. (url will change but only 1 index.html)
  2. 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

  1. Javascript VS Typescript
  2. CLI Builder
  3. can use Angular CLI to build components & services
  4. lazy-loading
  5. 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)

  1. Component Directives
  2. Structural Directives
  3. 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 :

  1. HTML template (declares what renders on page)
  2. typescript class that defines behaviour
  3. CSS selector that defines how component is used in a template
  4. CSS styles applied to template From documentation

Component VS Module

Component:

  1. controls view (html)
  2. communicate with other components and services to bring functionality to applucation

Modules are:

  1. 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:

  1. inline (define it in @Component({template: <<here>>}) directive)
  2. 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

  1. Interpolation ------ {{expression}}
  2. property binding-----[target]=expression
  3. event binding--------(target)=statement
  4. 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);
  }
}
Enter fullscreen mode Exit fullscreen mode

using the two-way binding looks lie this:

<app-sizer [(size)]="fontSizePx"></app-sizer>
Enter fullscreen mode Exit fullscreen mode

Explain architecture of Angular?

Angular consists of 7 main building blocks:

alt text

  1. Template (HTML view)
  2. Component (binds view an model)
  3. Binding (how component & template talk to each other)
  4. Module (groups components logically)
  5. Directives (change style / behaviour of DOM)
  6. Service (share common logic across the project project)
  7. 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:

  1. URL
  2. 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 :

  1. path (URL path)
  2. Component
  3. (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.

  1. define collection of routes in angular --> map url paths to components
  2. define router outlet --> where the component will be displayed
  3. [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?

  1. Divide project into separate modules
  2. 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
alt text
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();
  }
}
Enter fullscreen mode Exit fullscreen mode

taken from documentation

How to implement dependency Injection in Angular?

There are 3 ways to provide a service

  1. 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',
})
Enter fullscreen mode Exit fullscreen mode

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 {
}
Enter fullscreen mode Exit fullscreen mode

With providedIn: any all eagerly loaded instance share singleton instance, but lazily loaded modules each get their own unique instance
alt text

  1. provide in module register service in providers array in NgModule
@NgModule({
  providers: [
  ExampleService,
  Logger
 ],
 ...
})
Enter fullscreen mode Exit fullscreen mode

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.

  1. 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 ]
})
Enter fullscreen mode Exit fullscreen mode

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

  1. Events fired when component is first loaded
  2. Events fired on change detection

alt text

List of lifecycle events
(events called ONCE are italicized)

  1. constructor (more of a typescript event, not an angular event)
  2. ngOnChanges (also called when data bound input property @Input changes). This event happens very frequently
  3. ngOnInit (data bound properties displayed on screen / sets component's @Input properties)
  4. ngDoCheck() (fires immediately after ngOnChanges() on every change detection run)
  5. ngAfterContentInit (after Angular projects external content into component's view) related to <ng-check>
  6. ngAfterContentCheck (check content projected)
  7. ngAfterViewInit (after angular initializes component's views & child views)
  8. ngAfterViewChecked (after angular checks component's view & child views)
  9. ngOnDestroy (cleanup before angular destroys component)

three parts

  1. kick start event (change detection) (ngOninit, ngDoCheck)
  2. projected content event fires (ngAfterContentInit, ngAfterContentChecked)
  3. events of component view fires (ngAfterViewInit, ngAfterViewChecked)

constructor VS ngOnInit()?

  1. constructor - typescript concept, invoked by typescript
  2. ngOnInit - angular concept / event, invoked by angular framework

Sequence:

  1. constructor is fire.
  2. view and component initialized, binding happens
  3. ngOnInit (after component is initializes, access to DOM elements)

Constructor:

  1. initialize class variables
  2. dependency injection

ngOnInit:

  1. access to class variables
  2. 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>
Enter fullscreen mode Exit fullscreen mode

To use template reference variable with ViewChild

<div #div1> this div </div>

@Viewchild('div1',{static: false}) div: ElementRef
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Parent Content

<div>
  <greet>
    <h3> everything else </h3>
    <h1> Header </h1>
    <span class="content"> something </span>
  </greet>
</div>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

reference

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> 
Enter fullscreen mode Exit fullscreen mode

CardComponent.ts

@ContentChild("header") cardContentHeader: ElementRef;
Enter fullscreen mode Exit fullscreen mode

ParentComponent.html

<card>
  <header><h1 #header>Angular</h1></header>
  <content>One framework. Mobile & desktop.</content>
  <footer><b>Super-powered by Google </b></footer>
</card>
Enter fullscreen mode Exit fullscreen mode

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

  1. import HttpClient from @angular/common/http
  2. import HttpModule in Angular Module
  3. create HttpClient object via dependency injection constructor(public http:HttpClient)
  4. make post / get class with HttpClient this.http.post(URL, data).subscribe(res => successfunc(res), err => errfunc(err)
  5. 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

  1. error callback of subscribe method
  2. 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

  1. Parent Child component
    @Input : Parent -> child
    @Output : Child -> parent
    @ViewChild:

  2. Data between routes -> Routing Query Params

this.route.navigate(['url'],
  {queryParams: {
    name: 'myname'
    }
   });
Enter fullscreen mode Exit fullscreen mode
  1. Services more of global data / storing more of sharing global data via singleton service
  2. create service
  3. inject service into components
  4. access service data

  5. 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:

  1. AsynPipe : read object from asynchronous source (impure by default)
  2. JsonPipe: convert object to json string
  3. KeyValuePipe: can use in ngFor to iterate keys and values of object
  4. DatePipe: fomat date
  5. CurrencyPipe: number -> currency string

Example:

<p>The hero's birthday is {{ birthday | date:"MM/dd/yy" }} </p>
Enter fullscreen mode Exit fullscreen mode

You can also chain pipes (will implement first pipe then second pipe to the output of first pipe)

{{ birthday | date | uppercase}}
Enter fullscreen mode Exit fullscreen mode

How to make custom pipes in Angular?

  1. Use @Pipe to mark class as a pipe
  2. Implement PipeTransform interface
  3. 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" }}
Enter fullscreen mode Exit fullscreen mode

Change detection in angular pipe.

  1. 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 reference

  2. Change something inside a composite object (e.g. month of a date, element of array, object property)
    use impure 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:

  1. change to pimitive input value (string, number, boolean, symbol)
  2. 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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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

  1. change object reference replace array with new array containing new changed elements, input new array to pipe.
  2. make pipe detect impure changes set pure flag to false
@Pipe({
  name: 'flyingHeroesImpure',
  pure: false
})
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

blob may be undefined.
Async JS has 2 main code styles:

  1. callbacks (old-styles)
  2. promise (new-style)

Async JS has two models: ( more details on RxJS

  1. Pull mode (consumer is king, consumer decides when it receives data from producer, producer is unaware when data will be delivered)
  2. 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

  1. Creation
  2. Subscription
  3. Executing
  4. 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();
Enter fullscreen mode Exit fullscreen mode

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:

  1. Pipeable operator takes in observable as input and output is also an observable. pre-processing logic, can transform data in observable.
  2. creation operator can be called as standalone functions to create new Observable

Taken from RxJS documentation

Discussion (0)

pic
Editor guide