Angular Architecture/Best Practices Flashcards

1
Q

software requirements

A

Node js, Angular CLI, VS code

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

Architecture Considerations

A

APP OVERVIEW - what is the application for, what are the goals, how is the client going to use it, what are the business and strategic benefits
APP FEATURES
DOMAIN SECURITY - are we using roles on the server side, groups, claims; how are they going to be communicated to angular app; how is angular going to communicate with our api, is it going to use token based or ldap with active directory
DOMAIN RULES - are they going to run on client side or server side. we need to run on both sides is good for validations. there were might be some number crunching ones, which might need api call and run on the server
LOGGING: when error in front end application
api or integrate with cloud
it helps in bug support and also have good statistics about the app
SERVICE/COMMUNICATION: how angular app is going to talk to the server
normally it is http/https
if your app might have real time data considerations then web sockets might be
not just thinking about data exchange between front end and back end but thinking about between service and components is helpful
DATA MODEL: api to angular; what are we passing to components
are we getting what we want from the api. in many cases data models with api give lot of data, we might only need subset of the data;
we might need to think if we are going to use viewmodel, models only the component needs
FEATURE COMPONENTS: what are our feature components and how are we going to structure our feature components
component commucation -
we might need to know key features upfront
SHARED FUNCTIONALITY- any 3 rd party components that we are going to use
are we going to use them directly or use a wrapper
shared in just one app or use across app; then we think about libraries

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

Architecture planning Template

A

https://docs.google.com/presentation/d
/1jrkbbB3eRtTOrbkaljQxLuypHsdUHDl3_
4uFFnHTSNo/edit#slide=id.p4

https: //codewithdan.me/angular-architecture-planning
https: //codewithdan.me/angular-architecture-planning-example

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

Domain Security

A

using tokens
using HttpInterceptor could be used to set auth header
what is the back end that issues token, and refresh tokens

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

Domain Rules

A

validation
Route guard for not to access without login
validate credentials

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

Logging

A
Azure app insights
angular service for logging
Handle errors based on different environment dev/stage/prod
i used  ngx-logger
nlog - graylog
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Services/communication

A
restful services -on back for this project node.js is being used. it could be java asp.net core, php
Angular services below:
Data service : use http client ; for customer/orders and login/logout(auth)
Sorting Service
Filtering Service
Logger Service
Mediator/bus if needed
Component to component communication

HttpInterceptor will set token for HTTP requests if token GET/PUT/POST/DELETE/PATCH - to set header

Use PATCH - to update specific properties - one or two properties

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

Data Models

A

Application Models/Interface

Create class or just use interface on the client side

if we use interface, there is zero impact on the bundle size for production
it is better to opt for interfaces unless the classes are more specialized; like if model has properties and models

if you are just using the data from the server or using the object to scale to a smaller object then interfaces are just fine on client side

Interface is great for intellisense or code help

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

How to reduce the bundle size

A

How to reduce the bundle size

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

Feature Components

A

decide what are angular components needed for features of the app

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

Shared Functionality

A
Toast
Modal Dialog
Google map
pager
Menu
Grid/cards

are these just feature used once or used in multiple feature components

this decides where to pull these in the folder hierrachy

if they are going to used by other applications then we could have a shared library

any 3 rd party components like 
prime Ng
Ng Bootstrap
Angular Material
ag-grid
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Take time for architecture it helps

A

you will be so much ahead in planning the application architecture
The folder layout
the reuse of code
we might change, as we are still in the initial phase

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

angular style guide

A
https://angular.io/guide/styleguide
coding conventions
naming rules
application sturcture
organizing modules
creating and using components
creating and using services
life cycle hooks
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Other considerations

A

Accessibilty - may be design consideration
i18n - Internationalization
Environments-
CI/CD
CDN/Container/Server - how are we deploying code to production
course on containerizing angular applications with docker
Unit testing- built in cli tools, karma test runner
End to end testing - protractor or Cypress
this might impact your design; the testers might prefer to have id on all the tags to make it easy to find
API’s - backend where the security happens; data validation
Performance of the application
Documentation

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

Organizing Features

A

Do structure the app such that you can LOCATE code quickly, IDENTIFY the code at glance, keep the FLATTEST structure you can, and TRY to be DRY (Do not repeat yourself)

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

LIFT

A

LOCATE CODE QUICKLY-
easy to structure the folder structure; once we get bundles it does not matter

IDENTIFY THE CODE AT A GLANCE-
how we name our files like
feature.component.ts
data.service.ts
canactivate.guard.ts = for route guards

KEEP THE FLATTEST STRUCTURE YOU CAN-
do not keep nested folders

Try to be DRY:
like we could use services to reuse
we could reuse directives and components

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

Organizing files - convention based - may be not recommended if there are multiple features

A

like putting all the components in one folder
putting all the services in one folder
like MVC pattern

Follow strict naming conventions
Related code may be separated
can result in a lot of files in a folder in larger applications

views would be different places

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

Organizing files - Feature based - Recommended and CLI does by default

A

May be you could have Feature folder like Customers
and have many components like edit,grid,cards
that are part of the feature

if there are too many then you could have subfolder called components like feature- Customer - Components - put all the components related

it has one extra layer in the es2015 import statement

Features are organized into their own folders
Features are self-contained
Easy to find everything related to a feature

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

Organizing files - Feature based -how to implement

A

use angular cli to generate initial feature folder/component ; you could even flatten without creating sub folders

Minimum of one Module per feature (as appropriate) - it helps in lazy loading ; it helps in features to be self-contained; it could be imported at the root module or some other feature if needed
;it is good for maintainence

Avoid Deeply nested folders

Flatten Feature hierrachies - application might have hierrachies like Course-exercise-lab but your code should have exercise folder, course folder, items folder instead of having them in hierarchy
Flatten out top level features as much as possible; this will reduce the need to add ../,../ in the code
if you have nested features that is okey, but be cautious about how deeply you want to nest
Flattening makes - imports to be easier, refactor to be easier, easy to find components

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

Feature Modules

A

let us assume we have customer feature and orders feature

ng g c customer = it creates customer component with a folder created at the top level

people normally add this feature in the root module; there is nothing wrong in it as the app grows and grows and gets more feature;

we have one module, we can not use lazy loading and the features are no longer self-contained

usually we could have one module per feature but often instructor has 2

Feature has routing; so we have feature routing module defined with in a module in the feature itself
customers-routing.module.ts that would be imported into module for this feature customer.module.ts

if you have complex subfeatures, you would want them to be self-contained, if the portion of the team does it. root module does not need to worry about it

so we are going to have feature-routing module and feature module

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

Angular Style Guide-Single responsibility

A

Apply the single responsibility principle (SRP) to all components, services, and other symbols. This helps make the app cleaner, easier to read and maintain, and more testable.

Do define one thing, such as a service or component, per file.

Consider limiting files to 400 lines of code.

Why? One component per file makes it far easier to read, maintain, and avoid collisions with teams in source control.

Why? One component per file avoids hidden bugs that often arise when combining components in a file where they may share variables, create unwanted closures, or unwanted coupling with dependencies.

Why? A single component can be the default export for its file which facilitates lazy loading with the router.

The key is to make the code more reusable, easier to read, and less mistake prone.

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

ASG - Small functions

A

Do define small functions

Consider limiting to no more than 75 lines.

Why? Small functions are easier to test, especially when they do one thing and serve one purpose.

Why? Small functions promote reuse.

Why? Small functions are easier to read.

Why? Small functions are easier to maintain.

Why? Small functions help avoid hidden bugs that come with large functions that share variables with external scope, create unwanted closures, or unwanted coupling with dependencies.

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

ASG -Naming

Do follow a pattern that describes the symbol’s feature then its type. The recommended pattern is feature.type.ts.

A

Naming conventions are hugely important to maintainability and readability. This guide recommends naming conventions for the file name and the symbol name.

General Naming Guidelines
Style 02-01
Do use consistent names for all symbols.

Do follow a pattern that describes the symbol’s feature then its type. The recommended pattern is feature.type.ts.

Why? Naming conventions help provide a consistent way to find content at a glance. Consistency within the project is vital. Consistency with a team is important. Consistency across a company provides tremendous efficiency.

Why? The naming conventions should simply help find desired code faster and make it easier to understand.

Why? Names of folders and files should clearly convey their intent. For example, app/heroes/hero-list.component.ts may contain a component that manages a list of heroes.

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

ASG-Separate file names with dots and dashes

A

Do use dashes to separate words in the descriptive name.

Do use dots to separate the descriptive name from the type.

Do use consistent type names for all components following a pattern that describes the component’s feature then its type. A recommended pattern is feature.type.ts.

Do use conventional type names including .service, .component, .pipe, .module, and .directive. Invent additional type names if you must but take care not to create too many.

Why? Type names provide a consistent way to quickly identify what is in the file.

Why? Type names make it easy to find a specific file type using an editor or IDE’s fuzzy search techniques.

Why? Unabbreviated type names such as .service are descriptive and unambiguous. Abbreviations such as .srv, .svc, and .serv can be confusing.

Why? Type names provide pattern matching for any automated tasks.

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

Self-contained Features - do not put everything in app.module

A

with module, all the components and the routing module

self contained feature let different members of a team work on given feature and own it . they are incharge of routing, any services

we just need to import the customer/feature module into the root module i.e, app.module.ts

we need not need to know any details about the feature

exception is if we are lazy loading, we need to define the route and own the root module

any child route or submodules in the customer module, we need not know anything about it. we could just import them

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

Lazy loading

A

unless you use lazy loading; all the modules are eagerly loaded that means all the modules and their associated components, directives, pipes and services must be downloaded from the server when the user first visits the application

This takes lot of time

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

Eager loading

A

eagerly loaded that means all the modules and their associated components, directives, pipes and services must be downloaded from the server when the user first visits the application

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

Asychronous routing

A

https://csharp-video-tutorials.blogspot.com/2018/12/lazy-loading-in-angular.html

loads the feature modules lazily on demand . This can significantly reduce the initial load time of your application

We want to lazily load EmployeeModule. To lazy load a module, it has to meet 2 requirements.

All the routes in the angular module that you want to lazy load should have the same route prefix

const appRoutes: Routes = [
{
path: ‘employees’,
children: [
{ path: ‘’, component: ListEmployeesComponent },
{ path: ‘create’, component: CreateEmployeeComponent },
{ path: ‘edit/:id’, component: CreateEmployeeComponent },
]
}
];

The module should not be referenced in any other module. If it is referenced, the module loader will eagerly load it instead of lazily loading it.
Our application already meets the first requirement. All our EmployeeModule routes have the same route prefix i.e employees.
we are removing the employee module reference in app.module.ts
we remove it in the imports on the top and imports section as well

EmployeeModule that we want to lazy load is referenced in the AppModule. So please delete the EmployeeModule references in the AppModule (app.module.ts)

we could check all the references by rightclicking on the module name and find all references

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

Eager loading - in the network tab; there is lot of data loaded and the number of request are more

A

Eager loading - in the network tab; there is lot of data loaded and the number of request are more

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

use loadChildren property for lazy loading

A

in app.module.ts

{path:’employees’,loadchildren:’./employee/
employee.module#EmployeeModule’}

after hash it is the Employee Module class name

in Employee Routing module:
const appRoutes: Routes = [
{
path: ‘employees’,
children: [
{ path: ‘’, component: ListEmployeesComponent },
{ path: ‘create’, component: CreateEmployeeComponent },
{ path: ‘edit/:id’, component: CreateEmployeeComponent },
]
}
];

so the URL needs employees name twice
localhost:4200/employees/employees

we could remove the path:'employees' in the employee module
After you remove the 'employees' parent route, the routes should look as shown below.

const appRoutes: Routes = [
{ path: ‘’, component: ListEmployeesComponent },
{ path: ‘create’, component: CreateEmployeeComponent },
{ path: ‘edit/:id’, component: CreateEmployeeComponent },
];

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

with lazy loading

A

https://www.youtube.com/watch?v
=75XFBIKLPQY

https://csharp-video-tutorials.blogspot.com
/2018/12/lazy-loading-in-angular.html

load time will be lower; transferred size of data
we could see all in network in chrome developer tools

with lazy loading the modules are loaded on demand
we could see request for module load when navigated to the route
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

about feature module

A
it has routing module - with does not have anything in the path
the routing module is imported into about module
in the imports - we have RouteModule.forchild(appRoutes)

import all the components in the feature routing module:
import { AboutComponent } from ‘./about.component’;

const routes: Routes = [
{ path: ‘’, component: AboutComponent }
];

@NgModule({
  imports: [ RouterModule.forChild(routes) ],
  exports: [ RouterModule ]
})
export class AboutRoutingModule {
  static components = [ AboutComponent ];
}

we could import the static variale in the feature module:

import { NgModule } from ‘@angular/core’;

import { AboutRoutingModule } from ‘./about-routing.module’;

@NgModule({
imports: [ AboutRoutingModule ],
declarations: [ AboutRoutingModule.components ]
})
export class AboutModule { }

it is not loaded into app.module.ts but loaded into app-routing.module.ts with lazy loading

{path:’about’,loadchildren:’app/about/about.module#AboutModule’}

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

Core and Shared Modules - DRY code - Do not Repeat Yourself code -CORE MODULES

A

Core Module:
Core folder should contain singleton services shared throughout app

Services that are specific to a feature can go in the feature’s folder. we could create folder called services in the feature folder and this services is imported in the feature module. in this case the services is not used else where or injected else where in the application

example: LogginService; ErrorService - which intercepts the errors in general; DataService-one specific to customers and one specific to orders

we could call it Core or some people call it Common; but what matters is how we are organizing the code and have everyone on the same page

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

Core and Shared Modules - DRY code - Do not Repeat Yourself code -SHARED MODULES

A

Shared Modules -
Reusable components, pipes, directives

example- CalendarComponent
AutoCompleteComponent
may be custom grid that could be used through out the app

will this widget be used only in this app or used across apps? if it is so generic and could be used across applications then we should be creating angular library

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

Core and Shared Modules importing

A

Shared Modules may be imported multiple times into RootModule, Feature Modules

Core Module - it is imported only once into the root module (app module)

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

Preventing Reimport of Core

Core should only be imported into the root/app module

A
export function throwIfAlreadyLoaded (parentModule:any, moduleName:string){
if(parentModule){
throw new Error('${moduleName} has already been loaded. Import core modules in the AppModule only.')
}
}


Core Module:
import {throwIfAlreadyLoaded } from ‘./import.guard’
export class CoreModule{
constructor(@Optional() @SkipSelf() parentModule:CoreModule)
{
throwIfAlreadyLoaded(parentModule,’CoreModule’);
}
}

in constructor we are having dependency injection
@Optional(): A constructor parameter decorator that marks a dependency as optional; it is okey if there is nothing for this to inject
@SkipSelf()- go to the parent injector and see if we can inject a Core Module

A constructor parameter decoarator that tells the DI framework that dependency resolution should start from the parent injector

skipping self and going up to the parent

we hope that there is no parent module; this way we could have core module not imported into parent module

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

Using the Base Class: CoreModule can derive from EnsureModuleLoadedOnceGuard

A
export class EnsureModuleLoadedOnceGuard { 
constructor(targetModule: any) { if (targetModule) { throw new Error('${targetModule.constructor.name} has already been loaded. Import this module in the AppModule only.'); 
} 
} 
} 
Alternative Aoproach - Base Class An alternative to throwlfAlreadyLoaded is to convert it into a class 
----
import { EnsureModuleLoadedOnceGuard } from './ensure-module-loaded-once.guard'; 
export class CoreModule extends EnsureModuleLoadedOnceGuard { 
constructor(@Optional() @SkipSelf() parentModule: CoreModule) { super(parentModule); 
} 

if there is parent module that means it is bad, that measns core module is already imported from someother module and we do not want that

using class instead of function if there are other module that needed to be loaded in one particular place the appModule

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

General folders in Core Folder

A

Growler(type of toast message), Interceptors,modal, navbar, overlay, Services like auth.service, logger, trackby and other services and strategies for lazy loading

each of the above have their own module
as there is lot going on with them
it helps in self-contained, test them, use them on their own

if it is simple them then import them into core directly instead of creating module for them

core usually has services but any components that are used only once could go in here

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

Core folder also has components to use in app-component;

Core - is for single usage

A
//type of toast message
 //modal dialog to reuse in the whole app
Loading  

all these components are needed only single time in the app, like singleton. they do not have to be

anything in the core is used one time in the application
people should remember to not use these selectors for the components in multiple places in the application

some people put the components in shared folder

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

Shared folder - all here could be reused

A

■ directives ■ filter-textbox
map N pagination N pipes • interfaces.ts • mocks.ts ✓ router.animations.ts • shared.module.ts
map component - used multiple times in the app

all the above could be reused many times

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

Creating a Custom Library

A

if one of your shared module, you want to put in on npm or internal npm to be used by other applications

$ ng new my-project //this creates workspace with one project
$ ng generate library my-lib //custom shared library
Creating a Custom Library:
Angular CLI provides library functionality
The tsconfig file will be updated to look for library reference
Build the library before trying to use it in the workspace

library creates a separate project adds into the existing workspace
so we could test the library with out having to publish into npm, just by using our web project

ng build my-lib //to build the library

now we could test the project

tsconfig. json = it adds path s to the dist folder of the project where we going to build; typescript looks at this file when you try to build
angular. json = it has workspace and the two projects that we have created

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

Publish a custom library

A

package.json file will be used to publish to npm

npm publish = this publishes to npm but it needs login

if you are publishing to local npm then you might need path

$ ng build my-lib $ cd dist/my-lib $ npm publish
Publishinc a Custom Liorary
Build your library for production
Publish to npm or to an internal npm
https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry

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

library project

A

it has component, module and service samples created

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

Consuming a custom library

A

we import into the web project app.module.ts in the array

then the src/public_api = of library gets imported; this exposes all the component, services in the library

we could replace it with package name ; like acme-shared

we could use the library directly in the web project with tag

we need to then bulid the acme-shared project

ng build acme-shared –watch and not the root project

then ng serve -o

then we could push npm

we have created dist folder for the library, we could see the package.json in the folder which has the version name and the name of the package that we will be publishing

we need to run publish with npm command in dist - shared folder

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

when to go with custom project library

A

if we see that some widgets are being reused in many apps
then we could creaetd libaray instead of creating them in shared folders

then npm install custom shared package

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

Widget - Shared or Feature

A

widget - like menu, calendar,auto complete
if a widget is used by many component then we put it in Shared Module
if a widget is used only in a specific feature component then we put it in Feature Module

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

Feature/Child Componet

A

this goes into Feature Module either feature or child to a feature

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

Services

A
if reusable put it in core module
if a particular service is only use by specific feature then it goes into Feature module
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
49
Q

Routed components

A

the path defined to a specific component, it goes in routing module

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

Routing module

A

this will be imported into the feature module

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

Pipes

A

in shared module

if only a feature uses a pipe then put in feature module

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

Exporting of Feature Module

A
Feature module is a stand alone, it is usually imported into Root module and it does not need to know anything.
we will not be exporting anything typically from Feature Module
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
53
Q

Routing Module

A

we will importing routing functionality and export that

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

Core Module

A
this is going to imported into root module this will not have any exports
Exception is that if we put single use components like menu that should be used one time in the app; in this case we need to export that component
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
55
Q

Shared Module

A

it needs exports; if we need to import in any of the modules

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

Shared library

A

we could import when needed in feature module or in the shared module

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

Container - Presentation pattern for components

A

if there is a big component then we break it down to child components
Container component - which has mutiple presentation component
Container component manages the state (interact with service/store); it is boss/manager

Presentation component - presnts/renders the state

the presentation component do not get the state; they just get what container component gives to them

Container components gets the data; it might possibily render something as well like heading; but it will hand the data down to presentation component for UI

child components - do not know how to get the data or how to interact with store; they are just presentation component

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

Container - Presentation pattern for components- Child Routes and Components

A
Tool bar or Tabbed interface
customer:
/customers/44
Child : /customers/44/edit
child:/customers/44/details

const routes: Route = [
path: ‘customers/:id’, component: CustomerComponent, children: [
{ path: ‘edit’, component: CustomerEditComponent },
{ path: ‘details’, component: CustomerDetailsComponent },
]
}
];
do not build components, very big; break them into child components

if child component has lot of data having a separate child route will help to load the data only on demand

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

working with Container/Presentation components or Parent and Child components

A

Pass state from container —> presentation using input properties
Communicate from presentation -> container using output properties
Set change detection strategy to OnPush in presentation components
Consider cloning complex types
Use child routes as appropriate

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

we are using input properties to call the child components

A

in customer componnet html

    <div>

    </div>
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
61
Q

using router for child components

A

instead of input properties on parent component, we will have router outlet

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

in the container- presentation pattern

A

we load all the data at once and show and hide based on the need

we do not have separate routes

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

in the parent- child pattern

A

we have routes set up and we are going to load the child data only on demand when the route is reached

we could bookmark exact route with this way

also if we have lot of data then it is better to load them on demand by using routes

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

Data transfer from component to template

A

Property binding [] or Interpolation {} = from component code to Template

Event Binding = to get data from Template to Component

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

Data Transfer from Container to Presentation

A

Service –> Container Component –> Presentation

component(@Input () )

66
Q

Data Transfer from Presentation to Container

A

Service –> Presentation component (Output()) –>Container Component

output() property uses event emitter which emits the data up to the subscriber the container - then it might interact with the service to send that data

67
Q

challenges with input and output properties

A

if we have multi layer

Service ->Container –> Presentation –>Presentation

in this case it might be challenging

68
Q

input properties in usage

A

in Parent/Container component:
setting property:
export class CustomerComponent implements OnInit {
customer: any;

constructor() {}

  ngOnInit(): void {
    this.customer = {
      name: 'john',
      address: {
        city: 'Newyork',
      },
    };
  }

passing the value to customerDetail component from html:

<p>customer works!</p>

>

Customer Detail component:
export class CustomerDetailComponent implements OnInit {
@Input() CustomerDetail: any;

in html:

<p>customer : {{ CustomerDetail.name }}</p>

in appcomponent.html:

69
Q

output properties in usage

A

in customer component:

<p>customer works!</p>

customer : {{ CustomerDetail.name }}

70
Q

child/presentation component should not change the data or state

A

child/presentation component should not change the data or state

if the user changes at that level it is fine we could use output properties but usually it is the job of the parent/container component

71
Q

Change Detection Strategy On Push

A

OnPush causes change detection to run when:

  1. An input property reference changes
  2. An output property/EventEmitter or DOM event fires 3. Async pipe receives an event
  3. Change detection is manually invoked via ChangeDetectorRef

if we push data in or out then we want the UI to update

this protects us from accidentally updating the state and updating the UI

72
Q

OnPush Benefits:

A

OnPush Benefits:

  1. Performance (component isn’t checked until OnPush conditions are met)
  2. Prevent the presentation component from updating state it should get from the container/parent

it is better to have onPush on all the presentation components or child components

When using OnPush detectors, then the framework will check an OnPush component when any of its input properties changes, when it fires an event, or when an observable fires an event Victor Savkin (Angular Team)

sort is an event, then it will fire the onPush change detection strategy; it

73
Q

ChangeDetectionStrategy.OnPush,

A

@Component({
selector: ‘app-customer-detail’,
templateUrl: ‘./customer-detail.component.html’,
styleUrls: [’./customer-detail.component.scss’],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerDetailComponent implements OnInit {
@Input() CustomerDetail: any;
@Output() CustomerNameChange = new EventEmitter();
constructor() {}

ngOnInit(): void {
this.CustomerDetail.name = ‘peter in onit’;
this.CustomerDetail.name = ‘peter in onit new’;
setTimeout(() => {
this.CustomerDetail.name = ‘peter in timeout’;
}, 2000);
}

we could initialize values in onInit lifecycle but we are setting a delay to simulate the change later on inthe code which does is not allowed

74
Q

Pass by Value and Pass by Reference
Pass by Value = change detected
Pass by Reference = changes are not detected as the object by itself is still in the same memory location

A

value type = primitive types like number, string, boolean, null, undefined, symbol

if our container component is updating a value type then the change detection mechanism would catch that and update the child UI

in service:
 addCustomer() : Observable {
    let id = this.customers[this.customers.length - 1].id + 1;
    this.customers.push({
      id: id,
      name: 'New Customer ' + id,
      city: 'Somewhere',
      age: id * 5
    });
    this.customersSubject$.next(this.customers);
    return of(this.customers);
  }

we are adding element to the array but the array itself did not change so change detection does not work

export class CustomersListComponent implements OnInit {
  @Input() customers: Customer[];
since the input did not change the UI did not change

if pass the object by reference, anything in the object changes, that is not going to be reflected in the presentation component.
if we change a property of the customer object, that too will not be reflected in the UI because the outer object did not change its memory location

75
Q

Cloning Technique

A

Cloning is the process of making an exact copy of an object

Cloning Techniques:
Json.Parse() and Json.stringify() – simple
Custom
Immutable.js - library designed for it

immutable approach, we do not change the object. but we always make a fresh copy

76
Q

ngOnChanges()

A

Respond when Angular sets or resets data-bound input properties. The method receives a SimpleChanges object of current and previous property values.

Note that this happens very frequently, so any operation you perform here impacts performance significantly. See details in Using change detection hooks in this document.

Called before ngOnInit() and whenever one or more data-bound input properties change.

it detects when a new object is coming in through the input property

77
Q

Communication Between Container - Presentation and Service

A
  1. Container component passes data to presentation component using input property
  2. User changes data
  3. Output property emits customer to container
  4. Container talks with service to update customer object
  5. Container gets updated version of customer from service
78
Q

ngOnchanges catch point

A

if the object in memory has not changed then ngOnchanges is not going to fire

if the object does not change its reference, if just the property of object chagnes, then it is not detected with ngOnChanges

79
Q

Cloning Technique in action with JSON.parse; it is deep copy

A

in service

getCustomers():Observatble{
const custs= JSON.parse(JSON.stringify(this.customers));
return of(custs);
{

getCustomer(id:number):Observable{

return this.getCustomers()
.pipe(
map(custs=>{
const fiteredCusts = custs.filter(cust=>cust.id===id);
if (filteredCusts)
{
const cust= fitleredCusts[0];
return JSON.parse(JSON.stringify(cust)) as customer;
}

}

)
)
}

with dates it will not work

80
Q

ngOnChange

A

it detects when an change is made with the input property

if the service/container/ and both of the presentation has reference to the objects and we updated the properties but we did not change; so ngOnChange is not fired

the object in memory did not change but just the property inside it did

81
Q

Cloning Technique in action with custom srevice

A
getCustomers() : Observable
{
const custs = this.clonerservice.deepClone(this.customers);
return of(custs); 
}

this service uses 3 rd party NPM package called clone
it deals with dates

this is very light weight solution regarding the bundle size when we go to production, this is minimal library

82
Q

cloner.service.ts = for cloning the object; npm install clone

A

import { Injectable } from ‘@angular/core’;
import * as clone from ‘clone’;

@Injectable({
    providedIn: 'root'
})
export class ClonerService {
    deepClone(value) {
        return clone(value);
    }

}

there are different cloning techniques but here we are using clone

83
Q

cloning with immutable.js ; when there are lot of things immutable or clonable

A

impor {List, Map, fromJS} from ‘immutable’;
npm install immutable
this is from facebook
List object to work with arrays
Map object to work with key value pairs
from JS - can do a deep copy and create it to map, we could convert it into a normal javascript object

84
Q

cloning with immutable.js example

A
getCustomers() : Observable{
const custs = this.immutableCustomers.toArray();
return of(custs);
}

Note that toArray() “shallowly converts” the colelction to an Array. usr toJS() to deeply convert the collection to an array

85
Q

cloning with immutable.js example for customers

A

getCustomer(id:number):Observable{

return this.getCustomers()
.pipe(
map(custs=>{
const fiteredCusts = custs.filter(cust=>cust.id===id);
if (filteredCusts)
{
const cust= fitleredCusts[0];
return fromJS(cust).toJS() as cusomer;
}

}

)
)
}

fromJs, converts to javascript object of type any; under the cover it is called map and then it is converted to Javascript object using toJS(); it is a way to clone cast it to customer to return observable

86
Q

with immuatble js or any cloning strategy;

using ngOnChanges to detect input property changes

A

in component.ts:
@Input() customer:any;

ngOnChanges(changes: SimpleChanges)
{
if(changes['customer'])
{
const cust= changes['customer'].currentvalue as customer;
this.addTax(cust);
this.logMessage.Push({title:'customer chagned',value:cust});
}
}

usually the methods like addTax, is better to handle at the service level instead of component level

87
Q

@Input() with getter or setter in es2015

A

we could call the set block in the ngOnChanges() but the reference to the object needs to be changed

changes are usually not shown thinking that the outer object did not change

88
Q

Component Inheritance - it is not preferrable

A

save you lot of code and maintainable

the base component will not have template but it will have component code including functions and ofcourse the input and outputs

widget 1 and widget 2 will inherit from it

it is not preferrable but if you feel that there is lot of duplication especially with the input and output properties then it makes more sense

89
Q

Component Inheritance in action- base component

A

import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter, OnChanges, SimpleChanges } from ‘@angular/core’;

@Component({
selector: ‘app-base-component’,
template: ‘’,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class BaseComponent implements OnInit, OnChanges {
@Input() label: string;

  private _value: string;
  @Input() get value() {
      return this._value;
  }
  set value(val: string) {
      if (val &amp;&amp; val !== this._value) {
        this.isDirty = true;
      }
      this._value = val;
      this.valueChange.emit(val);
  }
  @Input() isDirty = false;
  @Output() valueChange = new EventEmitter();

constructor() { }

ngOnInit() {
}

  ngOnChanges(changes: SimpleChanges) {
    if (changes['value']) {
      console.log('Value changed ', changes['value'].currentValue);
    }
  }

}

90
Q

Component Inheritance in action - in child/widget component

A

import { Component, OnInit } from ‘@angular/core’;
import { BaseComponent } from ‘../base-component/base-component.component’;

@Component({
selector: ‘app-widget1’,
templateUrl: ‘./widget1.component.html’,
styleUrls: [’./widget1.component.css’]
})
export class Widget1Component extends BaseComponent implements OnInit {

constructor() {
super();
}

ngOnInit() {
}

}

in html:

<h3>{{ value }}</h3>

{{ label }}

91
Q

Cloning when to use

A

if you are getting fresh data from service from server; then we do not need to clone; as it is always a new object; same thing with post put delete;

we do not need to clone as long as the object chagnes;

in cases where we are calling the server and caching the data for a while, while the user edits or even lookup data; then we need to look for cloning

92
Q

Structuring components overview

A

Break complex components into child components
Use the container -3 presentation pattern where possible
Container retrieves state and presentation components render Use OnPush on presentation components Leverage cloning/immutable data when appropriate Use component inheritance sparingly (when it makes sense)

93
Q

Component Communication challenges

A

1: if deeply nested components need to communicate
2: if we want to communicate with one or more components at the same time

in the above cases using @Input and @Output might be challenging

we could use event bus or observable service techniques, both use rxjs subjects

this could also be used to communicate between services

94
Q

Component communication with Event Bus

A

Event Bus Mediator pattern
Angular service acts as the middleman between components
Components don’t know where data is coming from by default
Loosely coupled Relies on subject/observable

95
Q

Component communication with Observable Service

A

Observer pattern
Angular service exposes observable directly to components
Components know where data is coming from
Not as loosely coupled as event bus
Relies on subject/observable

96
Q

RxJS Subjects

A

Subject
BehaviorSubject
ReplaySubject
AsyncSubject

http://reactivex.io/documentation/subject.html

97
Q

RxJS Subjects -Subject

A

Subjects provide one or more data values to listeners
Listeners subscribe and get the data
if another component subscribes, they are not going to get all the data as the first component

with subject, you are going to get the data only that is emitted after subscribed and do not get the previously emitted data

98
Q

RxJS Subjects -BehaviorSubject

A

if a subscriber comes later in the game, they could still get the previous emitted data

the later subscribers could get the last emitted value from before; and going forward will get all ot them

this is powerful when you want to keep components uptodate when they subscribe later

99
Q

RxJS Subjects -ReplaySubject

A

BehaviorSubject is a type of replay subject
it replays the last value emitted to any new subscribers

it could also replay all of the previous values if you like

it is more like caching any data that is being sent out; so that any component subscribe still can get the data

new value emitted will be sent to all the components

this is helpful when you want to send stream of data for the late subscribers in the game

we could control how much of the new data to be sent

100
Q

RxJS Subjects -AsyncSubject

A

we want only the last value as the subject complete
there might be multiple values sent out but we are only interested in uptodate value

though there are values emitted continuously and component is subscribed, we are only going to receive the last value before the subject completes

used in any case only the last relevant data

101
Q

Subjects in action

A

import { Subject, BehaviorSubject, ReplaySubject,
AsyncSubject, Observable } from ‘rxjs’;

export class SubjectService {

customers = [];
intervalIds = [];
private subject$: Subject;
subjectObservable$: Observable;

private behaviorSubject$;
behaviorSubjectObservable$: Observable;

private replaySubject$: ReplaySubject;
replaySubjectObservable$: Observable;

private asyncSubject$: AsyncSubject;
asyncSubjectObservable$: Observable;

all the subjects are private and all the observables are public (default in typescript, if you do not specify any)

$ sign in the name, is just a naming convention to say that we are going to have a stream of data

importing subjects; defining subjects which exposes observables
all these subjects are pushing a new item into array of customers

we want the subject to be private, because any component could subscribe to a subject, if we expose they can not only subscribe but do anythign that they want to the subject. we do not want that to happen. Instead from the subject we expose an observable

webpage is echoing the latest

<h2>Status: {{ status }}</h2>

  <div class="row">
    <div class="col-md-3">
      <h4>Subject</h4>
      <ul>
        <li>{{ data.length }}</li>
      </ul>
    </div>
    <div class="col-md-3">
      <h4>BehaviorSubject</h4>
      <br>
      <ul>
        <li>{{ data.length }}</li>
      </ul>
    </div>
    <div class="col-md-3">
      <h4>ReplaySubject</h4>
      <br>
      <ul>
        <li>{{ data.length }}</li>
      </ul>
    </div>
    <div class="col-md-3">
      <h4>AsyncSubject</h4>
      <br>
      <ul>
        <li>{{ data.length }}</li>
      </ul>
    </div>
  </div>
102
Q

initializing subjects

A

initSubjects() {

this. subject$ = new Subject();
this. subjectObservable$ = this.subject$.asObservable();

this. behaviorSubject$ = new BehaviorSubject(this.customers);
this. behaviorSubjectObservable$ = this.behaviorSubject$.asObservable();

this. replaySubject$ = new ReplaySubject();
this. replaySubjectObservable$ = this.replaySubject$.asObservable();

this.asyncSubject$ = new AsyncSubject();
this.asyncSubjectObservable$ = this.asyncSubject$.asObservable();   }

we are not sending subjects directly; but we are saying them as observable
if you subscribe to it, it will look like normal observable subscription

export interface ICustomer{
name:string;
city:string;
}

103
Q

pushing with subjects

A
// simulate array getting new data from a data source
    let intervalId = setInterval(() => {
      let len = this.customers.length;
      this.customers.push({
        name: 'Customers ' + len,
        city: 'City ' + len
      });
      let clone: ICustomer[] = JSON.parse(JSON.stringify(this.customers));
      this.subject$.next(clone);
      this.behaviorSubject$.next(clone);
      this.replaySubject$.next(clone);
      this.asyncSubject$.next(clone);
  if (this.customers.length > 5) {
    this.asyncSubject$.complete();
  }
}, 3000);

this.intervalIds.push(intervalId);   }

we are using setInterval, which runs every 3 seconds
we are pushing a new customer every time
cloning the object of customer array
then push the customer to any subscribers with next; will pass the appropriate data

104
Q

consuming/subscribing to subjects in component

A

constructor(private subjectService: SubjectService) { }

//inject subject service

import { Component, OnInit, OnDestroy } from ‘@angular/core’;

import { SubjectService } from ‘../core/services/subject.service’;
import { SubSink } from ‘subsink’;

@Component({
  selector: 'app-subjects',
  templateUrl: './subjects.component.html',
  styles: [`
    .status {
      color: red;
    }`
  ]
})
export class SubjectsComponent implements OnInit, OnDestroy {
  status: string;
  subjectObservableData = [];
  behaviorSubjectObservableData = [];
  replaySubjectObservableData = [];
  asyncSubjectObservableData = [];
  timeoutIds = [];
  subsink = new SubSink();

constructor(private subjectService: SubjectService) { }

ngOnInit() { }

start() {
this.subjectService.start();
this.runAction(‘Calling SubjectService start()’, null, null);
this.runAction(‘Subscribing to Subject’, ActionType.subject, 2000);
this.runAction(‘Subscribing to BehaviorSubject (6 seconds after subject)’, ActionType.behaviorSubject, 8000);
this.runAction(‘Subscribing to ReplaySubject (10 seconds after subject)’, ActionType.replaySubject, 13000);
this.runAction(‘Subscribing to AsyncSubject (12 seconds after subject)’, ActionType.asyncSubject, 15000);
}

runAction(actionText: string, actionType: ActionType, delay: number) {
let action: () => void;
switch (actionType) {
case ActionType.subject:
action = () => {
this.subsink.sink = this.subjectService.subjectObservable$.subscribe(custs => {
this.subjectObservableData.push(custs);
})
};
break;

  case ActionType.behaviorSubject:
    action = () => {
      this.subsink.sink = this.subjectService.behaviorSubjectObservable$.subscribe(custs => {
        this.behaviorSubjectObservableData.push(custs);
      })
    };
    break;

  case ActionType.replaySubject:
    action = () => {
      this.subsink.sink = this.subjectService.replaySubjectObservable$.subscribe(custs => {
        this.replaySubjectObservableData.push(custs);
      })
    };
    break;
      case ActionType.asyncSubject:
        action = () => {
          this.subsink.sink = this.subjectService.asyncSubjectObservable$.subscribe(custs => {
            this.asyncSubjectObservableData.push(custs);
          })
        };
        break;
    }
    // update status and perform action
    let timeoutId = setTimeout(() => {
      this.status = actionText;
      if (action) {
        console.log('in')
        action();
      }
    }, (delay) ? delay : 0);
    this.timeoutIds.push(timeoutId);
  }
  ngOnDestroy() {
    this.subsink.unsubscribe();
    for (let id of this.timeoutIds) {
      clearInterval(id);
    }
  }

}

enum ActionType {
  subject,
  behaviorSubject,
  replaySubject,
  asyncSubject
}
105
Q

Showing subject value in the Subject component UI

A

<h1>Using RxJS Subjects</h1>

All of the functionality for this demo is in core/subject.service.ts and the subjects folder. Click Start to begin.
<br></br><br></br>

Start

<h2>Status: {{ status }}</h2>

  <div class="row">
    <div class="col-md-3">
      <h4>Subject</h4>
      <ul>
        <li>{{ data.length }}</li>
      </ul>
    </div>
    <div class="col-md-3">
      <h4>BehaviorSubject</h4>
      <br>
      <ul>
        <li>{{ data.length }}</li>
      </ul>
    </div>
    <div class="col-md-3">
      <h4>ReplaySubject</h4>
      <br>
      <ul>
        <li>{{ data.length }}</li>
      </ul>
    </div>
    <div class="col-md-3">
      <h4>AsyncSubject</h4>
      <br>
      <ul>
        <li>{{ data.length }}</li>
      </ul>
    </div>
  </div>

<br></br>
<strong>Subject</strong>
Only subscribers receive data
<br></br><br></br>
<strong>BehaviorSubject</strong>
Note how this picks up the last value emitted event though it subscribed after the value was sent out. That’s because
BehaviorSubject allows an initial value to be sent to an observer as they subscribe.
<br></br><br></br>
<strong>ReplaySubject</strong>
Note how this stays in sync with everything above even though it subscribes 10 seconds after the subject. That’s because
it’s replaying everything up to that point from a cache it maintains.
<br></br><br></br>
<strong>AsyncSubject</strong>
This only plays the last item before it completes - nothing before that. It “completes” in the data service once the
customers array length is greater than 5.
<br></br><br></br>

106
Q

Event Bus Service

A

Event bus is going to allow us to send data between different components, it is type of mediator or middle man

Event bus can send data between multiple components
Follows the mediator pattern
Uses RxJS Subject
Component

Component going to subscribe to an event of the event bus;
we are going have customer selected event

another component is going to raise an event, may be when a customer is selected and send those details to the Event bus. This component does not know who is listening at all

the first component will be able to get the data and use it

107
Q

using Event bus and emitting data from component

A

import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectionStrategy, SimpleChanges } from ‘@angular/core’;
import { Customer } from ‘../../shared/interfaces’;
import { EventBusService, EmitEvent, Events } from ‘../../core/services/event-bus.service’;

@Component({
selector: ‘app-customers-list’,
templateUrl: ‘./customers-list.component.html’,
styleUrls: [ ‘./customers-list.component.css’ ],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CustomersListComponent {
@Input() customers: Customer[];
@Output() customerSelected = new EventEmitter();
logMessages: string[] = [];

constructor(private eventbus: EventBusService) { }

ngOnChanges(simpleChanges: SimpleChanges) {
if (simpleChanges[‘customers’]) {
this.logMessages.push(‘ngOnChanges Fired: Customers changed’);
}
}

  selectCustomer(cust: Customer) {
    // send to parent via output property
    // note: could use eventbus as well if desired but output property
    // would be the preferred method for passing data to am immediate parent
    this.customerSelected.emit(cust);
    // Send customer to any eventbus listeners listening for the CustomerSelected event
    this.eventbus.emit(new EmitEvent(Events.CustomerSelected, cust));
  }

}

108
Q

using Event bus and subscribing data from a component that needs data

A
export class AppComponent implements OnInit {
  customers: Customer[];
  customer: Customer;
  eventbusSub: Subscription;
  customersChangedSub: Subscription;

constructor(private eventbus: EventBusService, private dataService: DataService) {}

  ngOnInit() {
    //Example of using an event bus to provide loosely coupled communication (mediator pattern)
    this.eventbusSub = this.eventbus.on(Events.CustomerSelected, cust => (this.customer = cust));
    //Example of using BehaviorSubject to be notified when a service changes
    this.customersChangedSub = this.dataService.customersChanged$.subscribe(custs => (this.customers = custs));
  }
  ngOnDestroy() {
    // AutoUnsubscribe decorator above makes these calls unnecessary
    // this.eventbusSub.unsubscribe();
    // this.customersChangedSub.unsubscribe();
  }
109
Q

Creating an Observable Service

A

This provides more control over where the data is emitted from and what is being emitted

it is more of publish-Subscribe pattern or observable pattern

we expose observable to anyone that want to subscribe,as the data changes we will emit that by calling next on our subject, that data will flow down to listeners

Observable services can send data to observers/subscribers
Follows the observer pattern
Provides a simple way to keep multiple observers (components, services) up-to-date
Service can use RxJS Subject objects and observables

110
Q

Creating an Observable Service - example

A
private customersSubject$ = new BehaviorSubject(this.customers);
  customersChanged$ = this.customersSubject$.asObservable();

we are exposing the subject as observable; here we are using BehaviorSubject, so all the subscribers will be able to get the last value that was sent to earlier subscribers

on addCustomer()- we are emitting the observable
  addCustomer() : Observable {
    let id = this.customers[this.customers.length - 1].id + 1;
    this.customers.push({
      id: id,
      name: 'New Customer ' + id,
      city: 'Somewhere',
      age: id * 5
    });
    this.customersSubject$.next(this.customers);
    return of(this.customers);
  }

Complete example:
import { Injectable } from ‘@angular/core’;

import { Observable, of, BehaviorSubject } from ‘rxjs’;
import { map } from ‘rxjs/operators’;

import { Customer, Product } from ‘../../shared/interfaces’;
import { ClonerService } from ‘./cloner.service’;
import { List } from ‘immutable’;

@Injectable({
  providedIn: 'root'
})
export class DataService {
  customers: Customer[] = [
    {
      id: 1,
      name: 'John Doe',
      city: 'Phoenix',
      age: 42
    },
    {
      id: 2,
      name: 'Jane Doe',
      city: 'Seattle',
      age: 30
    },
    {
      id: 3,
      name: 'Michelle Thompson',
      city: 'Orlando',
      age: 22
    }
  ];
  products: Product[] =  [
    {
      id: 1,
      name: 'Basketball',
      price: 29.99
    },
    {
      id: 2,
      name: 'XBox',
      price: 249.99
    },
    {
      id: 3,
      name: 'Nintendo Switch',
      price: 249.99
    },
    {
      id: 4,
      name: 'Bat',
      price: 29.99
    },
    {
      id: 5,
      name: 'Glove',
      price: 29.99
    },
    {
      id: 6,
      name: 'Cell Phone',
      price: 799.99
    },
    {
      id: 7,
      name: 'Cell Phone Service',
      price: 49.99
    },
    {
      id: 8,
      name: 'Laptop',
      price: 999.99
    },
    {
      id: 9,
      name: 'Bluetooth Speaker',
      price: 69.99
    },
    {
      id: 10,
      name: 'TV',
      price: 1599.99
    }
  ];

immutableCustomers = List();
immutableProducts = List();

  private customersSubject$ = new BehaviorSubject(this.customers);
  customersChanged$ = this.customersSubject$.asObservable();

constructor(private cloner: ClonerService) { }

  getCustomers() : Observable {
    // Use the following code if using immutable.js
    // return of(this.immutableCustomers.toJS());
    return of(this.customers);
  }
  getProducts() : Observable {
    // Use this for immutable.js
    // return of(this.immutableProducts.toJS());
    return of(this.products);
  }
  addCustomer() : Observable {
    let id = this.customers[this.customers.length - 1].id + 1;
    this.customers.push({
      id: id,
      name: 'New Customer ' + id,
      city: 'Somewhere',
      age: id * 5
    });
    this.customersSubject$.next(this.customers);
    return of(this.customers);
  }
  addCustomerClone() : Observable {
    return this.addCustomer().pipe(
      map(custs => {
        return this.cloner.deepClone(custs);
      })
    )
  }

addCustomerImmutable() : Observable {
let id = this.immutableCustomers[this.immutableCustomers.size - 1].id + 1;
this.immutableCustomers.push({
id: id,
name: ‘New Customer ‘ + id,
city: ‘Somewhere’,
age: id * 5
});
this.customersSubject$.next(this.customers);
return of(this.immutableCustomers.toJS());
}

  addProduct(newProduct: Product) {
    this.products.push({
      id: this.products.length,
      name: newProduct.name,
      price: +newProduct.price
    });
    return of(this.products);
  }

}

111
Q

Using an Observable Service

A

just subscribing to the data

first inject the service and then subscribe to it

 //Example of using BehaviorSubject to be notified when a service changes
    this.customersChangedSub = this.dataService.customersChanged$.subscribe(custs => (this.customers = custs));

here maintainance is easy as the data chagnes and the emitting of the observable are happening at the same place unlike Bus service

app.component.ts

import { Component, OnInit } from ‘@angular/core’;

import { EventBusService, Events } from ‘./core/services/event-bus.service’;
import { Customer } from ‘./shared/interfaces’;
import { Subscription } from ‘rxjs’;
import { DataService } from ‘./core/services/data.service’;
import { AutoUnsubscribe } from ‘ngx-auto-unsubscribe’;

@AutoUnsubscribe()
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  customers: Customer[];
  customer: Customer;
  eventbusSub: Subscription;
  customersChangedSub: Subscription;

constructor(private eventbus: EventBusService, private dataService: DataService) {}

  ngOnInit() {
    //Example of using an event bus to provide loosely coupled communication (mediator pattern)
    this.eventbusSub = this.eventbus.on(Events.CustomerSelected, cust => (this.customer = cust));
    //Example of using BehaviorSubject to be notified when a service changes
    this.customersChangedSub = this.dataService.customersChanged$.subscribe(custs => (this.customers = custs));
  }
  ngOnDestroy() {
    // AutoUnsubscribe decorator above makes these calls unnecessary
    // this.eventbusSub.unsubscribe();
    // this.customersChangedSub.unsubscribe();
  }
}
---
in html:
  <strong class="pull-right circle">
    {{ customers.length }}
  </strong>
112
Q

Observable Service Pros and Cons

A

Pros:
Simple to use -subscribe/unsubscribe
Data source is known (simplifies maintenance)
Easy to share data between different layers of an application

Cons:
Not as loosely coupled as an event bus (coupling between observable and observer)
Subject variations can be challenging to master
Must remember to unsubscribe

113
Q

unsubscribe from observable

A

ngOnDestroy = unsubscirbe

114
Q

Unsubscribing in ngOnDestroy

A
export class MyComponent implements OnInit, OnDestroy ( eventbusSub: Subscription; constructor(private eventbus: EventBusService) { ngOnInit() f this.eventbusSub = this.eventbus.on(Events.CustomerSelected, (cust => this.customer = cust)); 
} 
} 
ngOnDestroy() { if (this.eventbusSub) { this.eventbusSub.unsubscribe(); 
} 

Each observable subscription must be assigned to a property
Subscribe from observables in ngOnDestroy

if a component has several subscriptions, this could be cumbersome

115
Q

Unsubscribing using @AutoUnsubscribe() decorator

A

it is an npm package
it automatically iterates through all the properties, finds all the subscription types and when ngOnDestroy is called, it destroys all subscriptions

we need to have subscription properties and empty ngOnDestroy(){}

@AutoUnsubscribe() 
export class MyComponent implements OnInit, OnDestroy { 
eventbusSub: Subscription; constructor(private eventbus: EventBusService, private dataService: DataService) { } ngOnInit() { this.eventbusSub = this.eventbus.on(Events.CustomerSelected, (cust => this.customer = cust)); 
} 
ngOnDestroy()
 { 
// No need to manually unsubscribe 
} 
} 
Must add ngOnDestroy() 
Usinc the AutoUnsubscribe Decorator 
Component subscriptions can automatically be unsubscribed https://github.comiNetanelBasalingx-auto-unsubscribe
116
Q

using subSink npm for unsubscribing

A
export class MyComponent implements OnInit, OnDestroy { 
subs = new SubSink(); 
constructor(private eventbus: EventBusService, private obsService: ObsService)
 { } 

ngOnInit()
{
this.subs.sink = this.eventbus.on(Events.CustomerSelected, (cust => this.customer = cust)); this.subs.sink = this.obsService.subscribe(…);
}
ngOnDestroy() { this.subs.unsubscribe(); } }

Using SubSink :
Add multiple subscription objects to subsink and call its unsubscribe() function in ngOnDestroy()
https://github.com/wardbellisubsink
this way we do not need multiple names for different subscriptions, it puts all of them into single collection

117
Q

using take or untill for unsubscribing observables

A

using take or untill for unsubscribing observables

118
Q

Component Communication Summary

A

RxJS subjects provide a flexible way to communicate between components
BehaviorSubject returns the last emitted value to new subscribers
An event bus can be used for loosely coupled communication
An observable service exposes uses a subject to expose an observable
Unsubscribe from observables (pick a technique that works for you)

119
Q

The need for State Management

A

if the app is very simple then we could use with services and there is no need for State Management

when the application is complex; and similar thing like updating customer object is being done at multiple places then it is better to use state management

120
Q

State Management Goals

A

Single Source of Truth = so we are not updating state in multiple places and avoiding debugging nightmare

Predictable = we want things to be predictable

Immutable = you need to go to one place, if you need to change the state but the state itself never changes, we always create a new state

Track state changes = for better debugging; we could see before and after and see what action causes the state changes

121
Q

Different types of states

A

Application State = application itself may have some state
it might have some urls passed to it
some security information or other types of things that are needed

Session State = unique to the user,
user preferreces
or settings for user

Entity State = actual data used in the application or entity state
like the customers, order, invoices what ever it might be that the application is working with and displaying and collecting data; as the end users are interacting with the application

122
Q

State Management Options

A

Service = using services for state management
NgRx = using NgRx
ngrx-data = simplified version of NgRx; it is an extension that wraps NgRx functionality and makes it much easier to work with, with much code
Observable Store = this builds up on the observable service that we discussed with subjects; but adds statemanagement into the mix; it notifies different subscribers as the state chagnes

OTHER STATE MANAGEMENT OPTIONS- not discussed here
Akita
Ngxs
MobX

123
Q

State Management with Angular Services

A

if we want to perform reusable calculation on the front end, validation, or may be talk to the server through http client. we would use angular service to do that

A service is typically a class with a narrow, well-defined purpose. It shoulc do something specific and Co it well.

https://angular.io/guide/architecture-services

for simple apps - services are good enough for managing state

124
Q

State Management with Angular Services - simple way

A

Component 1 < – Service –> Component 2

Simplest approach
Inject Service where needed
Provide notifications using a subject (provides notification to the subscribers)

as we are working with components that need data, using services are great; as they provide one place to go, very good for maintenance, good for change request, reuse

125
Q

State Management with Angular Services - Challenges

A

if we have a component interacting with multiple services and if a customer is updated in multiple place this might cause problems

we could mitigate this by having every service talk to Store which stores the session data; in this case the STORE is the centralized data location

we need to make sure that every developer is using the store and we are not mutating the store objects somewhere else

126
Q

State Management with NgRx

A

NgRx Store provides reactive state management for Angular apps inspired by Redux. Unify the events in your application and derive state using RxJS. https://ngrx.io

127
Q

NgRx

A

Redux + RxJS = NgRx
Single source of truth for state
Immutable data = data is not mutated in multiple locations
Provide consistency across a team
Diagnostic tool to watch store = it provides great debugging experience; it uses Redux tool, that lets you to watch store and see changes to your state, as it flows through out your application

128
Q

Basic NgRx State Flow

A

Store = responsible for storing the state of our application; it could be application state, session state or entity state

in order to interact with the Store and the State, we are going to use actions
actions are going to be passed to Reducers

Reducer are translators, they take the action, act upon it and they are going to interact with the store state

we could get data back to the component through selectors$

FLOW= components sends an Actions
Actions goes to Reducers
Reduce is going to modify the state in the store
Then we get the data from selector

129
Q

NgRx State Flow - General use case - where we talk to server

A

we might need to talk to the server to get data as well

if a Component needs customers info:
Component sends GetCusomer to Store Action
This action triggers an Effect (we have to write the code for it)
Effect integrates with the server and get the data from the server
Effect send the appropriate action that we now have the data
This goes from Action to the Reducers
Reducer updates the State Store
The selectors$ get the data back to the component

NgRx and the different features it providers satisfies all the goals for the State Management
it provides predictable pattern that everyone on the team can follow

it creates lot of complexity, as we are going to have lot of code in the application

if everyone on the team has good understanding of the pattern and different pieces involved in it then it is good option; if not things might get complicated

130
Q

NgRx inAction

A
we need to install the below packages
@ngrx/effects
@ngrx/entity
@ngrx/store
@ngrx/store-devtools

we will find them in package.json

we are going to have Store folder, with actions, effects, reducers, services

when customer component needs data
it is going to inject our store and the store is going to have our entity state
we are also injecting the selectors, because as the store changes. we want to subscribe to that so that this component could get those changes and push them down to a child component (in this case, it is the customer list)
we are also monitoring when are the customers loading, that way we could show the spinner very easily

export class CustomersComponent implements OnInit { title = ‘Customers’;
customers$: Observable;
loadings: Observable;
constructor( private store: Store, private customerSelectors: CustomerSelectors)
{
this.customers$ = this.customerSelectors.customers$; this.loading$ = this.customerSelectors.loading$;
}
ngOnInit() {
this.getCustomers():
}

getCustomers()
{
this.store.dispatch(new CustomerAction.GetCustomers()):
}

we are going to call getCustomers()
this is going to dispatch an action to the store
getCustomers()
{
this.store.dispatch(new CustomerAction.GetCustomers()):
}

GetCustomer, it is a simple action that implements interface called Action

GetCustomerSuccess - when the success occurs
GetCustomerError = when error occured

export class GetCustomers implements Action 
{
readonly type = GET CUSTOMERS;
 } 
export class GetCustomersSuccess implements Action { readonly type = GET_CUSTOMERS_SUCCESS; constructor(public readonly payload: Customer()) {} 
} 

export class GetCustomersError implements Action {
readonly type = GET_CUSTOMERS_ERROR; constructor(public readonly payload: any) {}
}

Customer Reducer:
export function reducer( state = initialState, action: CustomerActions.AllCustomerActions ): CustomerState {

switch (action.type) {
case CustomerActions.ADD_CUSTOMER:
{
return { …state, loading: true }

case CustomerActions.ADD_CUSTOMER_SUCCESS: { return
{
…state,
loading: false,
customers: (…state.customers, { …action.payload}]
case CustomerActions.ADD_CUSTOMER_ERROR:
{
return { …state, loading: false };
}
the reducer function takes the state and the action to perform
case CustomerAction.GET_CUSTOMERS:{
return
{…state, loading:true}
}
here reducer is going to take a state and make a new object and set the loading property to true
this is going to interact with the store; specifically the state in the store

Effect:
@Effect( getCustomers4: Observable = this.actions$ ,pipe( ofType(CustomerActions.GET_CUSTOMERS),
switchMap(() => toAction( this.customerDataServic.getCustomers(), CustomerActsons.GetCustomersSuccess, CustomerActsons.GetCustomersError
)
)
);
effect monitors for specific action when that ction occurs, it calls the service

constructor(private http: HttpClient) {}
getCustomers(): Observable
{
return this.http.get(‘${this.apiUrlBase)lcustomers’) .pipe( catchError(this.handleError()) );
this returns the data

then getCustomerSuccess action is going to be passed to the action;

the reducer updates the store

customer-selector:
this subscribes to the store

const getAllCustomers = createSelector(
getCustomerState,
(state:CustomerState) => state.customers
);

this is grabbed in the component
this.customers$=this.customerSelectors.customers$;

in customer; it is observable
customers$:Observable;

we are passing it to the child with input property:

<div>

</div>

using async pipe as it is observable

we always dispactch an action from the component
reducer is going to get called
effects may get called
Store gets updated
selectors return the data back

as long as everyone is dispatching from the component, everyone will have a consistent way to work with the components

131
Q

Redux DevTools in chrome

A

allow to replay the state at different points in the application load process
we could see the payloads
and see different tasks that occured

132
Q

ngrx-data

A

ngrx-data is an NgRx extension that offers a gentle introduction to ngrx/redux without the boilerplate.
https://github.com/ngrx
ngrx-data - it is a wrapper around NgRx
you do not need to write all teh boilerplate code for actions, effects, reducers and selectors;
it makes one of code for entity; like order, invoice
then we write service that acts as a gateway for the entity to get the data
we could customer ngrx data; if we need to get deeper into ngrx reducer or call to service

instead of dispatching to the store, we use ngrx-data service
component - will call the ngrx-data-service ; behind the scenes it will communicate with action, reducers, effect, selectors
it will update the state store
once that is one, we will subscribe to the observable

133
Q

ngrx-data in action -Component

A

instead of injecting a store in the component, we inject the customer service

export class CustomersComponent implements OnInit { title = ‘Customers’;
customers$: Observable;
loading$: Observable;

constructor(private customerService: CustomerService)
{
this.loading$= this.customersService.loading$;
}

ngOnInit()
{
this.getCustomers();
}

getCustomers()
{
this.customers$=this.customersService.getAll();
}

getAll is out of the box

this is is like standard angular where you have injected the service in the constructor

134
Q

ngrx-data in action - Service

A

import { Injectable from s@angular/core;
import { EntityCollectionServiceBase, EntityCollectionServiceElementsFactory from
import { Customer} from ‘../core/model/customer’;

 @Injectable({ProvidedIn: 'root' })
 export class CustomersService extends EntityCollectionServiceBase {
constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory)
 {
super('Customer', serviceElementsFactory); 
} }
we are extending with Customer entity
and calling the base class with super keyword and pass the name of the entity

there is no code to call the server through http client, it will do that for you out of the box as long as you configure entities

135
Q

ngrx-data in action - model

A

ngrx-data in action - model

export class Customer{
id:number;
name:string;
city:string;
orderTotal:number;
}
Order model:
export class Order{
id:number;
customerId:number;
orderItems:OrderItem[];
}
export class OrderItem{
id:number;
productName:string;
itemCost:number;
}
136
Q

ngrx-data in action - store - Entity MetaData.ts

A

import {EntityMetadataMap} from ‘ngrx-data’;

const entityMetadata: EntityMetadataMap={
Customer:{}, //this is one line of code per entity
Order:{}
};

const pluralNames= { };

export const entityConfig={
entityMetadata,
pluralNames
};

we register the entity with the entityConfig

137
Q

ngrx-data in action - app-store.module.ts

A
const apiRoot = environment.apiUrlBase + '/';
 const defaultDataServiceConfig: DefauttDataServiceConfig = {
 root: apiRoot, 
entityHttpResourceUrls: {
 Customer:{ entityResourceUrl: apiRoot + 'customers/', collectionResourceUrl: }
Order:{ entityResourceUrl: apiRoot + 'orders/', collectionResourceUrl: apiRoot 
} ;
@NgModule({
 imports: [
 StoreModule.forRoot({}),
 EffectsModule.forRoot([]), NgrxDataModule.forRoot(entityConfig), environment.production ? [] : StoreDevtoolsModule.instrument() 
], providers: [ { provide: DefaultDataServiceConfig, useValue: defaultDataServiceCon 
})
 export class AppStoreModule 

storeModule and EffectsModule are part of normal NgRx
but with NgrxDataModule - we are registering our entities

138
Q

ngrx-data in action on orders component

A
Export class OrdersComponent implements Onlnit { 
orders$: Observable; toading$: Observable
139
Q

ngrx-data in action - it has Redux Dev tools

A

ngrx-data in action - it has Redux Dev tools

140
Q

Observable Store - state management

A

Observable Store provides a simple way to manage state in a front-end application while achieving many of the key goals offered by more complex state management options.
https://github.com/DanWahlin/Observable-Store

141
Q

Observable Store Goals

A
Single source of truth 
State is read-only/immutable 
Provide state change notifications to any subscriber 
Track state change history 
Minimal amount of code required 
Works with any library/framework
142
Q

Observable Store working

A

Component is going to call into angular service
this service is going to extend observable store; it is npm package
it is going to maintain state and get simple api for interacting with the api
you could call getState or SetState
it also tracks the state

as component calls in the service interacts with the store

if you want to interact with the server, you use http client;

There are no actions, reducers, effects

it is single store that multiple services could read and write from

the store is immutable, you are always getting a fresh copy when updates are made

143
Q

observable store

A

observable service was a way to exchange data between components

observable store is like observable service with an api like history tracker, to track chagnes, get state and update state

144
Q

observable Store in action

A

npm package @codewithdan/observable-store

@Injectable({
providedIn: ‘root’
})

export class CustomersService extends ObservableStore { 
apiUrl = 'api/customers'; 
constructor(private http: HttpClient) 
{ 
super({ trackStateHistory: true }); //calling base class to set tracking
 } 

getAll()
{

const state= this.getState();// comes from observable store

//pull from store cache

if(state&amp;&amp; state.customers)
{
console.log(this.stateHistory);
return of(state.customers);
}
//does not exist in store , so fetch the data 
else{
return this.fetchCustomers()
.pipe(
catchError(this.handleError)
);
}
}
private fetchCustomers(){
return this.http.get(this.apiurl)
.pipe(
map(customers=> {
this.setstate({customers},CustomersStoreAction.GetCustomers); // it has type of action performed with Enum
return customers;
{),
catchError(this.handleError)
);
}
}
it extends the observableStore and sets the StoreState on which entities to store
---
export interface StoreState{
customers: Customer[];
customer:Customer;
orders:Order[];
} // what ever you want to store we define here

in the component:

getcustomers()
{
this.customers$= this.customersService.getAll();
}

in the console ; it show the state properties; begin state and end state

145
Q

Choosing a state Mangement option

A

use Services - with simple applications that are not complex
which do not have lot of local state; may be your application only talks to the server for everything it does
in that case you might not need to store lot of state, you may not need immutable nature of state management

Medium Complex apps - ngrx-data/Observable store fits well
it gives the power of ngrx with out introducting lot of code;

if you have multiple components that needs to be notified as something happens; both these options allow subscribing to the state

Medium to Complex app = if you understand Redux and overall pattern provided by NgRx
and okey to introducing quite a bit of boiler plate code in the app
everyone on the team should understand the pattern

if everyone ok with boilerplate code
if several team members copy and paste the code; then question if that is the way to go

146
Q

State Management option

A

Measure Twice - cut once

try practicing before implementing

147
Q

Function vs Pipes

A

Functions gets called mutiple times

Function calls made from a template are invoked every time a change occurs (no caching); it is always a fresh call

they are called lot more especially if you have other type of filters like text boxes, dropdown etc. they are causing properties to change in the component

{{ addTax(product.price) | currency }}
we could replace this with PIPE
A Pure Pipe returns the same result give the same inputs

148
Q

Pure Pipe

A

A Pure Pipe returns the same result give the same inputs

Pipes are only called when the inputs are changed. other properties in the component might be changing but that will not impact

instead of function, we are going to create a custom pipe (addtax)
{{ product.price | addtax | currency }}

addtax is a function, but because the main functionality is in the transform function of the pipe, other things that are changing in the component are not going to cause the transform function to be called over and over again

when user types in a text box, or user selects a dropdown

149
Q

Function and Pipes in action

A

Function and Pipes in action

{{ produt.name }}
{{ addTax(product.price) | currency }}

addTax(price:number){
console.log(‘addTax() function called’);
return price + (price* this.tax);
}

any change to a input element like textbox, as the page is changing, angular calls these methods multiple times
it might cause performance issues

if the inputs to the pipe transform function do not change, then it does not need to be recalled

import {Pipe, PipeTransform} from ‘@angular/core’;
@Pipe({
name: ‘addtax’
})

export class AddTaxPipe implements PipeTransform{
transform(price:number):number{
if(price)
{
return this.getTotalPrice(price);
}
return price;
}
getTotalPrice(price:number)
{
console.log('addtax pipe called');
let total = price + (price *0.8);
return total;
}
}

if the inputs to the binding in the pipe does not change then the pipe functions are not called multiple times

150
Q

Using a Memo Decorator on pipes - cache result based on inputs passed into pipe transform()

A

it is an open source package

it enhances caching of a pipe’s transform() function when a primitive value is passed; like number or string

it will monitor the input value and see the output; the output value is cached; if it sees an input for the first time it calculates but if it sees it again, it knows the input and gets the cached output value

import memo from memo-decorator’;

@Pipe({name: 'addtaxmemo'})
export class AddTaxMemoPipe implements PipeTransform{
@memo()
transform(value:any, args?:any):any{
//retun product.price+tax;
}

}

{{ product.price | addtaxmemo | currency}}

you have to be cautious about it as it is caching in memory; if you have enormous amount of data

if there is less data, it helps in speeding up the calculations which are complex

it is better to do these calculation in the service or server side if possible, but sometimes you might not have the data you need so you might do it on the angular or front end

151
Q

HttpClient and RxJS operators

A

May be you might need to talk to two different apis at the same time

like GetPerson - from personAPI- to get the ID and URL
then use the ID to GetAddress from AddressAPI to get the address

152
Q

RxJs tap

A

tap is a RxJS pipeable operator that returns identical Observable as source Observable and can be used to perform side effect such as logging each values emitted by source Observable. tap is declared as following.
public tap(nextOrObserver: Observer | function, error: function, complete: function): Observable tap has three optional parameters.
nextOrObserver: A normal Observable object to perform side effect.
error: Callback for errors in source Observable.
complete: Callback for completion of the source.

Find the sample example.
of(1, 2, 3, 4).pipe(
 tap(el => console.log("Process "+ el),
	err => console.error(err),
	() => console.log("Complete")
 ),
 filter(n => n % 2 === 0)
).subscribe(el => console.log("Even number: "+ el));
153
Q

using tap

A
getCharacters() {
    return this.http.get(this.baseUrl + 'people')
      .pipe(
        tap(res => {
          console.log('Before getCharacters map');
        }),
        map(res => {
          return res['results'];
        }),
        tap(res => {
          console.log('After getCharacters map');
        })
      );
  }
154
Q

forkJoin in rxjs

A

import { forkJoin, of, from } from ‘rxjs’;

 getCharactersAndPlanets() {
    return forkJoin(
      this.getCharacters(),
      this.getPlanets()
    )
    .pipe(
      map((res) => {
        return { characters: res[0], planets: res[1] };
      }),
      catchError(error => of(error))
    );
  }
 getCharacters() {
    return this.http.get(this.baseUrl + 'people')
      .pipe(
        tap(res => {
          console.log('Before getCharacters map');
        }),
        map(res => {
          return res['results'];
        }),
        tap(res => {
          console.log('After getCharacters map');
        })
      );
  }
  getPlanets() {
    return this.http.get(this.baseUrl + 'planets')
      .pipe(
        tap(res => {
          console.log('Before getPlanets map');
        }),
        map(res => {
          return res['results'];
        }),
        tap(res => {
          console.log('After getPlanets map');
        })
      );
  }

if we want to call both the observables at the same time

in the component:
charactersAndPlanets: { characters: any[], planets: any[]};
// Get both characters and planets at same time
// Uses forkJoin
this.dataService.getCharactersAndPlanets()
.subscribe(data => this.charactersAndPlanets = data);

155
Q

Switch Map - when we have the observable, when we know that we need to finish it with some updated information from another observable

A
getCharactersAndHomeworlds() {
    return this.http.get(this.baseUrl + 'people')
      .pipe(
        switchMap(res => {
          // convert array to observable
          return from(res['results']);
        }),
        // concatMap((person: any) => {
        mergeMap((person: any) => { 
            return this.http.get(person['homeworld'])
              .pipe(
                map(hw => {
                  person['homeworld'] = hw;
                  return person;
                })
              );
        }),
        toArray()
      );
  }

we are getting the people and updating the homeworld with another call

in the component:
  characterWithHomeworld$: Observable;
  // Get character and its homeworld
    // Uses switchMap
    this.characterWithHomeworld$ = 
      this.dataService.getCharacterAndHomeworld();

Here we are getting the observable instead of mapping the data to the property in the component: and using async in the html

<h2>People and Homeworlds</h2>
<ul>
  <li>
    <span>{{ char.name  }} ({{ char.homeworld.name }})</span>
  </li>
</ul>
156
Q

MergeMap

A

get all the characters and their home worlds

 getCharactersAndHomeworlds() {
    return this.http.get(this.baseUrl + 'people') //we are getting array
      .pipe(
        switchMap(res => {
          // convert array to observable
          return from(res['results']); //converting array to observable
        }),
        // concatMap((person: any) => {
        mergeMap((person: any) => { 
            return this.http.get(person['homeworld'])
              .pipe(
                map(hw => {
                  person['homeworld'] = hw;
                  return person;
                })
              );
        }),
        toArray() //convertting the whole result set to array
      );
  }

in component:
charactersWithHomeworld$: Observable;
this.charactersWithHomeworld$ = this.dataService.getCharactersAndHomeworlds();

in html:
<h2>People and Homeworlds</h2>
<ul>
  <li>
    <span>{{ char.name  }} ({{ char.homeworld.name }})</span>
  </li>
</ul>

Note that MergeMap wont gurantee that the order of the people is preserved as they are returned. Use concatMap i f you want the original order of people perserved

it is more like us writing loop of all people, but rxjs is doing it for us

we are calling toArray(), because we do not want each of the results to be pushed to the subscribers one by one; instead all to be passed in one go

157
Q

forkJoin switchMap, MergeMap

A

these help in making parallel calls to the api instead of serial calls

158
Q

Security - Cross-Origin Resource sharing (CORS)

A

our angular app may call app in different domain or same domain with different port; which is cross origin

CORS allows a browser to call a different domain or port
Enable on the server as needed, it depends on server side technology used; it is not done on angular
Limit allowed domains, headers and methods; to what is needed

if it is public api you might say * for allowing

159
Q

Security - Cross site Request Forgery (CRSF)

A

someone sending request to your website

but
Enable CSRF on the server if using cookie authentication
Angular will read a token from a cookie set by the server and add it to the request headers
only the same domain can set this request header
bad site can not set the request header;
when the request is made to the server, if the request head was not there it will be blocked
in angular you could change the cookie if needed
Change the cookie/header name as appropriate for your server

https://angular.io/guide/http#security-xsrf-protection

server will validate the header value

Note that a simple POST request can be used for CSRF attack

160
Q

Security - Route guard

A

Route guard - used to direct the user to login screen or some other page, if they do not have proper security credentials as dictated by the server

may be they are not in the proper role or group

there is no such thing as security in the browser, the server is ultimate source of security for routes, api

Define route guards needed by application based on user or group/role

Keep in mind that route guards do not “secure” an application

Rely on the server to secure data, API etc

161
Q

Security - Sensitive Data

A

Anyone can access the browser developer tools to view variables, local/session storage, cookies etc

Do not store sensitive data like secrets used to call an api, keys that are important, passwords in the browser

when you are calling a 3rd party api and you are calling directly from angular you need to pass the key and the secret inorder to call it
some people will pass that secret to angular, store it and angular will have it locally as it calls your api. anybody wants could get that secret

if an api requires a secret to be passed. consider calling it through a middle-man service that you own
which has the secrets

Use JWT token where possible for server authentication (set appropriate TTL expiration for token). we do not need a cookie containers; we could use this for authentication and authorization

additional:
authentication on Server
authorization like roles/groups
HTTPS - we would want from angular to api
what if api calls another api, if we want end to end or point to point calls

162
Q

HTTP Interceptors

A

HTTP Interceptors