{"id":14966932,"url":"https://github.com/h3ar7b3a7/earlyangularprojects","last_synced_at":"2026-01-27T13:32:53.623Z","repository":{"id":41437189,"uuid":"331428106","full_name":"H3AR7B3A7/EarlyAngularProjects","owner":"H3AR7B3A7","description":"Some projects made while learning about Angular.","archived":false,"fork":false,"pushed_at":"2022-09-05T21:01:30.000Z","size":9816,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-01T18:35:20.978Z","etag":null,"topics":["angular","jest","karma","material","reactiveui","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/H3AR7B3A7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"security/.browserslistrc","support":null}},"created_at":"2021-01-20T20:48:21.000Z","updated_at":"2024-06-24T05:57:42.000Z","dependencies_parsed_at":"2022-08-10T02:24:05.515Z","dependency_job_id":null,"html_url":"https://github.com/H3AR7B3A7/EarlyAngularProjects","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/H3AR7B3A7%2FEarlyAngularProjects","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/H3AR7B3A7%2FEarlyAngularProjects/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/H3AR7B3A7%2FEarlyAngularProjects/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/H3AR7B3A7%2FEarlyAngularProjects/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/H3AR7B3A7","download_url":"https://codeload.github.com/H3AR7B3A7/EarlyAngularProjects/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239195129,"owners_count":19598032,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","jest","karma","material","reactiveui","typescript"],"created_at":"2024-09-24T13:37:10.324Z","updated_at":"2026-01-27T13:32:53.595Z","avatar_url":"https://github.com/H3AR7B3A7.png","language":"TypeScript","readme":"# Getting Started With Angular\n\n[Official Angular Pages](https://angular.io/)\n\nAngular is a TypeScript-based open-source web application framework led by the Angular Team at Google and by a community of individuals and corporations. Angular is a complete rewrite from the same team that built AngularJS.\n\n### Installation\n\n- **Install NPM \u0026 Node.js**: Download installer [here](https://nodejs.org/en/download/).\n- **Install Typescript**: npm install -g typescript\n- **Install Angular**: npm install -g @angular/cli\n\n### Interesting Libraries\n\n- ESLint\n\n\u003e ng add @angular-eslint/schematics\n\n- Material\n\n  \u003e ng add @angular/material\n\n- Flex Layout\n\n  \u003e npm i @angular/flex-layout\n\nSee: [Flexbox Layout Examples](https://tburleson-layouts-demos.firebaseapp.com/#/docs)\n\n- Bootstrap\n\n  \u003e ng add @ng-bootstrap/ng-bootstrap\n\n- Font-Awesome\n\n  \u003e npm i font-awesome\n\n### VSC Extensions:\n\n- Angular Essentials\n- Angular Language service\n- Angular Snippets\n- Nx Console\n- TSLint\n- Material Icon Theme\n\n## Creating a Project\n\nNavigate to the desired folder and use following commands:\n\n\u003e ng n name --routing --prefix prefix --style scss --strict  \n\u003e ng serve -o\n\n## Npm\n\nNpm is the default package manager.\n\nNpm keeps track of the specific dependencies of different packages in package-lock.json.\nIn older versions we had to use:\n\n\u003e npm shrinkwrap\n\nWe also had to use --save to add them to package.json:\n\n\u003e npm install packageName --save\n\nLuckily we no longer have to do either of these things. These are some of the things npm package manager learned from some of the alternatives.\n\n## Yarn\n\nYarn is an alternative package manager that has some advantages over npm:\n\n- Yarn caches every package it downloads so it never needs to download it again. It also parallelizes operations to maximize resource utilization so install times are faster than ever.\n- Yarn uses checksums to verify the integrity of every installed package before its code is executed.\n- Using a detailed, but concise, lockfile format, and a deterministic algorithm for installs, Yarn is able to guarantee that an install that worked on one system will work exactly the same way on any other system.\n\nTo change our package manager globally we use:\n\n\u003e ng config -g cli.packageManager yarn\n\nTo add packages we use:\n\n\u003e yarn add packageName\n\nTo find out why a package exists on your project:\n\n\u003e yarn why packageName\n\n# Typescript\n\n[Official Typescript pages](https://www.typescriptlang.org/)\n\nTypeScript is an open-source language which builds on JavaScript, one of the world’s most used tools, by adding static type definitions.  \nTypes provide a way to describe the shape of an object, providing better documentation, and allowing TypeScript to validate that your code is working correctly.\n\n## Let\n\nWe use 'let' instead of 'var' to make sure our variable doesn't leak outside the scope:\n\n```typescript\nlet i = 3;\nfor (let i = 0; i \u003c 10; i++){\n    ...\n}\n```\n\nThis will transpile to:\n\n```typescript\nvar i = 3;\nfor(var i_1 = 0; i_1 \u003c 10; i_1++\u003e){\n    ...\n}\n```\n\n## Const\n\nWe should prefer to use 'const' where ever possible to create constants, or variables that never change.\nThis goes only for the top level of the variable, and thus object properties can still be changed.\n\n## Types\n\nMost of the time Typescript is able to figure out what type a variable is supposed to hold through _Type Inference_. Even when we did not clearly state a variables type, TypeScript will not transpile if we assign it the wrong type of variable.\n\n### String\n\n```typescript\nconst brand: string = 'Chevrolet'\n```\n\n### Number\n\n```typescript\nconst age: number = 31\n```\n\n### Boolean\n\n```typescript\nconst isNegative: boolean = false\n```\n\n### Array\n\n```typescript\nconst brands: string[] = ['Ford', 'GM', 'Tesla']\n```\n\n### Any\n\n```typescript\nconst distances: any[] = ['1000km', 1000]\n```\n\n### Custom Type\n\n```typescript\ntype Pet = 'Cat' | 'Dog'\nconst pet: Pet = 'Cat'\n```\n\n### Enum\n\n```typescript\nenum Brands {\n  Ford,\n  GM,\n  Tesla,\n  Nio,\n}\nconst myCar: Brands = Brands.Tesla\nconst carAtIndex: string = Brands[1] // Result = GM\n\nenum Brands {\n  Ford = 1,\n  GM,\n  Tesla,\n  Nio,\n}\nconst carAtIndex: string = Brands[1] // Result = Ford\n\nenum DistanceFromSun {\n  Mercury = 57900000,\n  Venus = 108200000,\n  Earth = 149600000,\n  Mars = 227900000,\n  Jupiter = 227900000,\n  Saturn = 1427000000,\n  Uranus = 2871000000,\n  Neptune = 4497100000,\n}\n```\n\n### Void\n\nAs in other languages we use this type to annotate that a function does not return a value.\n\n## Functions\n\n### Optional Parameters\n\nWe can use optional params, but they have to go last:\n\n```typescript\nfunction greet(name: string, greeting?: string): string {\n  if (!greeting) {\n    greeting = 'Hello'\n  }\n  return greeting + ', ' + name\n}\n```\n\n### Default Parameters\n\nWith a default param we can simplify previous code snippet:\n\n```typescript\nfunction greet(name: string, greeting: string = 'Hello'): string {\n  return `${greeting}, ${name}`\n}\n```\n\nAlso note the **template string** in back-ticks with **string substitutions**.\n\n### Rest Parameters\n\nWith rest params we can define an unknown amount of parameters.\n\n```typescript\nfunction greetEveryone(greeting: string, ...names: string[]): string {\n  return greeting + ', ' + names.join(' and ') + '!'\n}\n```\n\n### Function Overloading\n\nJavaScript does not implement an elegant way to overload functions, so we need to write function declarations for each of the overloads before writing the general-purpose function that wraps the actual implementation:\n\n```typescript\nfunction hello(names: string): string {}\nfunction hello(names: string[]): string {}\nfunction hello(names: any, greeting?: string): string {\n    let namesArray: string[];\n    if (Array.isArray(names)){\n        namesArray = names;\n    } else {\n        namesArray = [names];\n    }\n    ...\n}\n```\n\nNotice that we had to check for the true type of the param of _any_ type.\n\n### Arrow Functions\n\nThe fat arrow function or Lambda:\n\n```typescript\nconst double = (x) =\u003e x * 2\n```\n\nBraces are required with multiple arguments:\n\n```typescript\nconst sum = (x, y) =\u003e x + y\n```\n\nCurly braces are required when containing statements:\n\n```typescript\nconst doubleOfSum = (x, y) =\u003e {\n  const sum = x + y\n  return sum * 2\n}\n```\n\nBut arrow functions also allows lexical scoping of _this_:\n\n```typescript\nfunction delayedGreeting(name): void {\n  this.name = name\n  this.greet = function () {\n    setTimeout(() =\u003e console.log('Hello ' + this.name), 0)\n  }\n}\n```\n\nIf we were to use the actual function instead of the arrow function this.name would be _Undefined_.\n\n## Common Typescript Features\n\n### Spread parameter\n\nWe can use spread parameters in arrays or objects to not have to repeat ourselves:\n\n```typescript\nconst oldArray = [1, 2]\nconst newValue = 3\nconst newArray = [...oldArray, newValue]\n```\n\nNotice how the original array did not change, we call this principle **immutability**. Instead of changing it we created a new state.\n\n### Generics\n\nIn collections or constructs like methods we can make use of generics to code behavior that we can employ, regardless of the type of data.\n\n```typescript\nfunction method\u003cT\u003e(arg: T): T {\n  return arg\n}\n```\n\nOr with an array of a generic type:\n\n```typescript\nfunction method\u003cT\u003e(arg: T[]): T[] {\n  return arg\n}\n```\n\nWe can either create an array of some type or extend the array to a custom type to pass a valid argument to this function.  \nWe can also say a generic type should adhere to some interface:\n\n```typescript\ninterface Shape {\n  area(): number\n}\nfunction allAreas\u003cT extends Shape\u003e(...args: T[]): number {\n  let total = 0\n  args.forEach((x) =\u003e {\n    total += x.area()\n  })\n  return total\n}\n```\n\nNow we can create multiple classes implementing the Shape interface with their own area() methods and pass them to allAreas().\n\n## Classes, Interfaces and Inheritance\n\n### Constructor Parameters with Accessors\n\nA class fully written out contains a lot of 'boilerplate' code:\n\n```typescript\nclass Car {\n  make: string\n  model: string\n\n  constructor(make: string, model: string) {\n    this.make = make\n    this.model = model\n  }\n}\n```\n\nTypescript makes writing this a breeze, by allowing accessors in the constructor params:\n\n```typescript\nclass Car {\n  constructor(public make: string, public model: string)\n}\n```\n\nTypescript will create the public fields and assignments for us.\n\n### Interfaces\n\nWe use interfaces as blueprints of code that define a particular schema. Artifacts (classes, function signatures, etc.) implementing an interface should comply with this schema.\n\n```typescript\ninterface Vehicle {\n  make: string\n}\n\nclass Car implements Vehicle {\n  make: string\n}\n```\n\nThis way we make sure every vehicle has the field 'make'. We use this to create consistency in our code.  \nInterfaces can also contain optionals:\n\n```typescript\ninterface Exception {\n  message: string\n  id?: number\n}\n```\n\nWe can do more with interfaces than just implement them and build more complex ones:\n\n```typescript\ninterface ErrorHandler {\n  exceptions: Exception[]\n  logException(message: string, id?: number): void\n}\n```\n\nOr define interfaces for standalone object types, useful to define a templated constructor or method signature:\n\n```typescript\ninterface ExceptionHandlerSettings {\n  logAllExceptions: boolean\n}\n```\n\nHere is an example of the implementation of these:\n\n```typescript\nclass CustomErrorHandler implements ErrorHandler {\n    exceptions: Exception[] = [];\n    logAllExceptions: boolean\n\n    constructor(settings: ExceptionHandlerSettings){\n        this.logAllExceptions = settings.logAllExceptions;\n    }\n    logException(message: string, id?: number): void{\n        this exceptions.push({message, id});\n    }\n}\n```\n\nWe can also **instantiate interfaces** in typescript, without involving any classes:\n\n```typescript\ninterface A {\n  a\n}\nconst instance = \u003cA\u003e{ a: 3 }\ninstance.a = 5\n```\n\nThis means you can create a **mocking library** very easily.\n\n### Interfaces and Mocking\n\nThis instantiation of interfaces helps mocking frameworks to mock our dependencies. What happens behind the curtains looks something like this...\n\nOur code:\n\n```typescript\ninterface AuthService {\n    isAuthenticated\n}\n\nclass Stuff {\n    constructor(private AuthService){}\n\n    execute(){\n        if(srv.isAuthenticated()){ console.log('access granted') }\n    } else { console.log('you do not have access') }\n}\n```\n\nMock:\n\n```typescript\nclass MockAuthService implements AuthService {\n  isAuthenticated() {\n    return true\n  }\n}\n\nconst srv = new MockAuthService()\nconst stuff = new Stuff(srv)\n```\n\nWe can instead simply create a mock by instantiating the interface instead:\n\n```typescript\nconst authServiceInstance = \u003cAuthService\u003e{}\n```\n\nHowever, **be aware** that you are responsible for adding required method(s), because it starts as an empty object.\n\n### Class Inheritance\n\nWe can also extend members and functionality from other classes using inheritance. In the following example Sedan inherits the member 'make'. Like in other OOP languages we can overwrite methods if needed and we can use the parent constructor using the super() method:\n\n```typescript\nclass Sedan extends Car {\n  model: string\n  constructor(make: string, model: string) {\n    super(make)\n    this.model = model\n  }\n}\n```\n\n## Decorators\n\nDecorators are a way to add metadata to class declarations for use by dependency injection or compilation directives. By creating decorators, we are defining special annotations (@Something) that may have an impact on the way our classes, methods or functions behave or just alter the data we define in fields or parameters.\n\n### Class Decorator\n\nHere is a simple example:\n\n```typescript\nfunction Banana(target: Function): void {\n  target.prototype.banana = function (): void {\n    console.log('We have bananas!')\n  }\n}\n\n@Banana\nclass FruitBasket {\n  constructor() {}\n}\n\nconst basket = new FruitBasket()\nbasket.banana()\n```\n\nWith a custom signature:\n\n```typescript\nfunction Banana(message: string) {\n  function Banana(target: Function) {\n    target.prototype.banana = function (): void {\n      console.log(message)\n    }\n  }\n}\n\n@Banana('Delicious bananas!!!')\nclass FruitBasket {\n  constructor() {}\n}\n```\n\n### Property Decorator\n\nCould be used to log log the values assigned to class fields when instantiating objects:\n\n```typescript\nfunction Jedi(target: Object, ke: string) {\n  let propertyValue: string = this(key)\n  if (delete this[key]) {\n    Object.defineProperty(target, key, {\n      get: function () {\n        return propertyValue\n      },\n      set: function (newValue) {\n        propertyValue = newValue\n        console.log(`${propertyValue} is a Jedi`)\n      },\n    })\n  }\n}\n\nclass Character {\n  @Jedi\n  name: string\n}\n\nconst character = new Character()\ncharacter.name = 'Luke'\n```\n\nOr when reacting to data changes:\n\n```typescript\nfunction NameChanger(callbackObject: any): Function{\n    return function(target: Object, key: string): void {\n        let propertyValue: string = this[key];\n        if (delete this[key]){\n            Object.defineProperty(target, key, {\n                get: function() {\n                    return propertyValue;\n                },\n                set: function(newValue){\n                    propertyValue = newValue;\n                    callbackObject.changeName.call(this, propertyValue);\n                }\n            });\n        }\n    }\n}\n\nclass Character{\n    @NameChanger({\n        changeName: function(newValue: string): void{\n            console.log(`You are now known as ${newValue}`);\n        }\n    });\n    name: string;\n}\n\nlet character = new Character();\ncharacter.name = 'Anakin';\n```\n\nThis will trigger the custom function 'changeName()' when the name property is changed.\n\n### Method Decorator\n\nIt is used to detect, log or intervene. Logging example:\n\n```typescript\nfunction Log() {\n  return function (\n    target,\n    propertyKey: string,\n    descriptor: PropertyDescriptor\n  ) {\n    const oldMethod = descriptor.value\n    descriptor.value = function newFunc(...args: any[]) {\n      let result = oldMethod.apply(this, args)\n      console.log(\n        `${propertyKey} is called with ${args.join(', ')} and result ${result}`\n      )\n      return result\n    }\n  }\n}\n\nclass Hero {\n  @Log()\n  attack(...args: []) {\n    return args.join()\n  }\n}\n\nconst hero = new Hero()\nhero.attack()\n```\n\n### Parameter Decorator\n\nUsed to look into the parameter value of functions or constructors and perform operations elsewhere, such as logging or replicating data:\n\n```typescript\nfunction Log(target: Function, key: string, parameterIndex: number) {\n  const functionLogged = key || target.prototype.constructor.name\n  console.log(\n    `The parameter in position ${parameterIndex} at ${functionLogged} has been decorated`\n  )\n}\n\nclass Greeter {\n  greeting: string\n\n  constructor(@Log phrase: string) {\n    this.greeting = phrase\n  }\n}\n```\n\n## Advanced Types\n\n### Partial\n\nObject that includes only _part_ of an interface:\n\n```typescript\ninterface Hero {\n    name: string;\n    power: number;\n}\n\nconst hero: Partial\u003cHero\u003e = {\n    name = 'Iron Man';\n}\n```\n\n### Record\n\nHow we create dictionaries in Typescript:\n\n```typescript\ninterface Hero {\n  powers: {\n    [key: string]: number\n  }\n}\n```\n\nOr with a Record:\n\n```typescript\ninterface Hero {\n  powers: Record\u003cstring, number\u003e\n}\n```\n\n### Union\n\nWe can mix types with unions:\n\n```typescript\ninterface Hero {\n  powers: number[] | Record\u003cstring, number\u003e\n}\n```\n\n### Nullable\n\nWe can allow Types to be null or undefined:\n\n```typescript\ninterface Hero {\n  powers: number[] | null | undefined\n}\n```\n\n_Note to check nullable values before using them!_\n**Optional chaining**:\n\n```typescript\nfor (let i = 0; i \u003c hero.powers?.length; i++){\n    ...\n}\n```\n\n### Modules\n\nExport from file 'my-service':\n\n```typescript\nexport class MyService {\n    getData() { ... }\n}\n```\n\nImport:\n\n```typescript\nimport { MyService } from './my-service'\n```\n\n# Angular\n\n## The CLI\n\n### Configuring Global CLI\n\n\u003e ng config -g schematics.@schematics/angular:component.style scss\n\nOn Windows the 'Global Config' file can be found here:\n\n\u003e C:\\Users\\\u003cUser\u003e\\.angular-config.json\n\n### Default templates\n\nOn Windows we can find the templates that are generated with 'ng n name' here:\n\n\u003e C:\\Users\\\u003cUser\u003e\\AppData\\Roaming\\npm\\node_modules\\@angular\\cli\\node_modules\\@schematics\\angular\\application\\files\\src\n\nWe can:\n\n- Modify the html/style templates that are present to our liking\n- Add our own default favicon\n- Add other default resources to our assets folder by appending them with '.template'\n- Create and customize different environments\n- Create additional file structures we always want to be present in our projects\n- ...\n\nWe can also make changes to the default package.json \u0026 README.md here:\n\n\u003e C:\\Users\\\u003cUser\u003e\\AppData\\Roaming\\npm\\node_modules\\@angular\\cli\\node_modules\\@schematics\\angular\\workspace\\files\n\n_My global files are included in this project as an example, feel free to take a look and copy or modify them to your needs._\n\n## Components\n\n### Create a Component\n\n\u003e ng generate component name\n\n--dry-run (Run without making changes to see what would happen)  \n--skip-tests (Don't generate spec.ts)  \n--inline-style (Don't generate stylesheet)  \n--inline-template (Don't generate html template)\n--flat (Generate without parent folder)\n\nExample component decorator:\n\n```typescript\n@Component({\n    selector: 'app-hero',\n    templateUrl: './hero.component.html',\n    styleUrls: ['./hero.component.css']\n})\n```\n\nTo render the template of the new component we add the selector to _app.component.html_:\n\n```html\n\u003capp-hero\u003e\u003c/app-hero\u003e\n```\n\n### Binding Components in Templates\n\nSee _[testProject](testProject)_ for examples of:\n\n- Variable Binding\n- Class Binding\n- Style Binding\n- Event Binding\n- Input Binding\n- Output Binding\n- Local References\n\n### Encapsulating CSS Styling\n\nViewEncapsulation enumeration values:\n\n- Emulated: Default, an emulation of native scoping in shadow DOM\n- Native: Only works in browsers that support shadow DOM\n- None: No encapsulation\n\nExample:\n\n```typescript\nimport { Component, ViewEncapsulation } from '@angular/core';\n\n@Component({\n    selector: 'app-hero',\n    templateUrl: './hero.component.html',\n    styleUrls: ['./hero.component.css'],\n    encapsulation: ViewEncapsulation.Emulated\n})\n```\n\n### Changing Detection Strategies\n\nEvery component has a _'change detector'_ that compares changed properties with their previous values. This can be a performance bottleneck for components that render hundreds of items in a list. In this case we might want to use the \\*_OnPush_ strategy which only triggers the change detection when the reference of _@Input_ properties change.\n\nExample:\n\n```typescript\nimport { Component, ChangeDetectionStrategy } from '@angular/core';\n\n@Component({\n    selector: 'app-hero',\n    templateUrl: './hero.component.html',\n    changeDetection: ChangeDetectionStrategy.OnPush\n})\n```\n\n## The Component Lifecycle\n\nAvailable lifecycle hooks:\n\n- OnInit\n- OnDestroy\n- OnChanges\n- DoCheck\n- AfterContentInit\n- AfterContentChecked\n- AfterViewInit\n- AfterViewChecked\n\n### The OnInit Interface\n\nThe _ngOnInit()_ method is called upon the initialization of a component. At this point all input bindings and data-bound properties have been set. The _OnInit_ hook can for example be used to initialize components with data from external sources.\n\n### The OnDestroy Interface\n\nThe _ngOnDestroy()_ method is called upon destruction of a component. Components get destroyed through using the _ngIf directive_ or by _routing_ to other components using a URI. When this happens it can be useful to use the OnDestroy interface to clean up:\n\n- Resetting timers \u0026 intervals\n- Unsubscribing from observable streams\n\n### The OnChanges Interface\n\nThe _ngOnChanges()_ method is called when the binding of a value changes. It accepts an object of type SimpleChanges as a parameter. The resulting objects holds a previousValue and currentValue, but also a boolean which tells us wether it is the 'first' change.\n\n## Directives\n\nDirectives are HTML attributes that extend the behavior or the appearance of standard HTML elements. When we apply them to an HTML element or even an Angular component, we can add custom behavior to it or alter its appearance. There are three types:\n\n- Components\n- Structural directives\n- Attribute directives\n\nBuilt in _structural directives_:\n\n- ngIf\n- ngFor\n- ngSwitch\n\nSee _[jestProject](jestProject)_ for more examples.\n\nTo create just an interface model:\n\n\u003e ng generate interface name --type=model\n\n### ngIf\n\nUsed for the conditional rendering of HTML elements in the DOM.\n\n```html\n\u003cp *ngIf=\"team === 'Avengers'; else noHero\"\u003e{{ name }} is an avenger!\u003c/p\u003e\n\u003cng-template #noHero\u003e\n  \u003cp\u003eNo avengers found\u003c/p\u003e\n\u003c/ng-template\u003e\n```\n\n### ngFor\n\nUsed for iterating through a collection of elements and rendering a template for each one.\n\n```html\n\u003cul\u003e\n    \u003cli *ngFor=\"let hero of listOfHeroes\u003e\n    {{ hero.name }}\n    \u003c/li\u003e\n\u003c/ul\u003e\n```\n\n### ngSwitch\n\nUsed as a switch statement evaluating some property and rendering the appropriate HTML element.\n\n```html\n\u003cng-container [ngSwitch]=\"hero.team\"\u003e\n  \u003cdiv *ngSwitchCase=\"'Avengers'\"\u003e{{ hero.name }} is an Avenger.\u003c/div\u003e\n  \u003cdiv *ngSwitchCase=\"'Justice League'\"\u003e\n    {{ hero.name }} is in the Justice League.\n  \u003c/div\u003e\n\u003c/ng-container\u003e\n```\n\n## Pipes\n\nPipes allow us to filter and map the outcome of our expressions on a view level. They transform data in the desired format and display the output in the template.\n\nSome default examples:\n\n```html\n\u003cp\u003e{{ 'Example' | uppercase }}\u003c/p\u003e\n\u003cp\u003e{{ 'Example' | lowercase }}\u003c/p\u003e\n\u003cp\u003e{{ 0.123 | percent }}\u003c/p\u003e\n\u003cp\u003e{{ 100 | currency }}\u003c/p\u003e\n\u003cp\u003e{{ 100 | currency:'EUR' }}\u003c/p\u003e\n\u003cp\u003e{{ listOfHeroes | slice:2:4 }}\u003c/p\u003e\n\u003cp\u003e{{ today | date }}\u003c/p\u003e\n\u003cp\u003e{{ today | date:'fullDate' }}\u003c/p\u003e\n\u003cp\u003e{{ hero | json }}\u003c/p\u003e\n\u003cp\u003e{{ delayedHero | async }}\u003c/p\u003e\n```\n\n## Custom Pipes\n\nTo create a pipe _in the current directory_:\n\n\u003e ng generate pipe name\n\nPipes are pure by default, which means they will not update when a value gets changed, only when a new value is assigned. So when we add an object to an existing array or change a value of an object and want it to be affected by the pipe we create a new array/object (immutability principle):\n\n```typescript\nlistOfHeroes: Hero[] = [...heroes, heroX];\n```\n\nTo change this behavior we can also make the pipe impure:\n\n```typescript\n@Pipe({\n    name: 'sort',\n    pure: false\n})\n```\n\nIf the object changes a lot and they are many, this can affect performance.\n\n## Custom Directives\n\nTo create a directive _in the current directory_:\n\n\u003e ng generate directive name\n\n## Modules\n\nSee _[ModulesAndStructure](ModulesAndStructure)_ for examples on the following topics.\n\nTo create a module:\n\n\u003e ng generate module name\n\n--dry-run (Run without making changes to see what would happen)  \n--flat (Generate without parent folder)  \n--routing (Generate routing module)\n\nThey contain:\n\n- Declarations: Registered components, directives and pipes\n- Imports: Other modules containing declarations to be used by this module\n- Exports: Artifacts available for other modules (aka the public API)\n- Providers: Provided services, accessible from any module\n- Bootstrap: Main component, 'AppModule'\n\n### Registering Components with a Module\n\nYou can do this by running the command inside the module folder or using the module option.\n\nUsing the module option:\n\n\u003e ng generate component cars/carList --module=cars\n\n### Exposing Module Features\n\nTo be able to add the the features template to the apps template using the selector we need to:\n\n- Add the component to the exports in the features module.ts.\n- Import the module in app.module.ts.\n\n### Module Separation\n\nBy functionality:\n\n- **Root** module: The main module, 'AppModule'\n- **Feature** modules: A set of functionalities (ex: Orders, Products, Customers, ...)\n- **Core** modules: Application wide artifacts (ex: Navbar, Footer, Loading spinner, ...)\n- **Shared** modules: Reusable artifacts imported by different feature modules\n\nBy loading:\n\n- **Eager** loaded modules: Declared in imports\n- **Lazy** loaded modules: Through navigation\n\n## Configuration \u0026 Environments\n\nWe can run commands in different environments by using the following option in the CLI:\n\n\u003e ng command --configuration=name\n\nWe can add other environments to the defaults (development and production) by creating the matching configuration files in the _environments folder_. The naming convention to follow here is: _environment.{name}.ts_.\n\nThe environment file exports an environment object. By default a boolean 'production' property is already set. We need to define all required properties in this object. For example the URL of the backend API will be set here.\n\nWhen we created the environment, we can define the appropriate configurations in the _angular.json_:\n\n```json\n\"configurations\": {\n    \"production\": {\n        \"fileReplacements\": [\n            {\n                \"replace\": \"src/environments/environment.ts\",\n                \"with\": \"src/environments/environment.prod.ts\"\n            }\n        ]\n    }\n}\n```\n\nWhen running **ng build --configuration=production** the CLI will replace the default environment file with the one for production.\n\n## Dependency Injection\n\nIn previous examples our data was tightly coupled to our component, meaning it was declared inside them.\n\n- In real world application our data is rarely static.\n- We only want our component to handle 'presenting' the data, and not be concerned on how to get the data.\n\nWe can generate a **service** that we can use to inject our data in any class that needs it.\n\n\u003e ng generate service cars/car\n\n### Share a Dependency Through Components\n\nAdd selector to parent template:\n\n```html\n\u003capp-favorite-cars\u003e\u003c/app-favorite-cars\u003e\n```\n\nAdd the service to providers in parent component:\n\n```typescript\n@Component({\n    selector: 'app-car-list',\n    templateUrl: './car-list.component.html',\n    styleUrls: ['./car-list.component.css'],\n    providers: [CarService]\n})\n```\n\n#### Restricting DI Down the Tree\n\nWe can restrict DI down to only one level by using the 'viewProviders' attribute:\n\n```typescript\n@Component({\n    selector: 'app-car-list',\n    templateUrl: './car-list.component.html',\n    styleUrls: ['./car-list.component.css'],\n    viewProviders: [CarService]\n})\n```\n\n#### Restricting Provider Lookup\n\nThe **@Host()** decorator will prevent bubbling up the hierarchy to look for the dependency, it will instead throw an exception.\n\n```typescript\nconstructor(@Host() private carService: CarService) { }\n```\n\nThe **@Optional()** decorator will prevent this error.\nThe **@SkipSelf()** and **@Self()** decorators will respectively make the injector skip or check the local injector of the current component. When skipping it will start looking higher in the hierarchy.\n\n#### Overriding Providers\n\nThe provider argument we used before was a shorthand for:\n\n```typescript\nproviders: [{ provide: CarService, useClass: CarService }]\n```\n\nThe useClass property overwrites the initial implementation. It could also take a factory function that returns one of multiple services depending on a condition:\n\n```typescript\nexport function carFactory(isFavorite: boolean){\n    return () =\u003e {\n        if (isFavorite) {\n            return new FavoriteCarService();\n        }\n        return new CarService();\n    };\n}\n...\nproviders: [{provide: CarService, useFactory: carFactory(true)}]\n```\n\nIf the 2 services also inject other dependencies into their constructor, we have to add them to the **deps** property of the provide object literal:\n\n```typescript\nproviders: [\n  { provide: CarService, useFactory: carFactory(true), deps: [HttpClient] },\n]\n```\n\nAnd inject it into the factory:\n\n```typescript\nexport function carFactory(isFavorite: boolean) {\n  return (http: HttpClient) =\u003e {\n    if (isFavorite) {\n      return new FavoriteCarService()\n    }\n    return new CarService()\n  }\n}\n```\n\n### Dependency Injection of Values\n\nWhen the dependency we want to provide is not a class, but a value, we can use the **useValue** syntax:\n\n```typescript\nexport interface AppConfig {\n    title: string,\n    version: number\n}\n\nexport const appSettings: AppConfig = {\n    title: 'My app'\n    version: 1.0\n;}\n```\n\nWe can't pass an interface to providers, so we create an **InjectionToken**:\n\n```typescript\nexport const APP_CONFIG = new InjectionToken\u003cAppConfig\u003e('app.config');\n...\nproviders: [{provide: APP_CONFIG, useValue: appSettings}]\n...\nconstructor (@Inject(APP_CONFIG) config: AppConfig){\n    this.title = config.title;\n    this.version = config.version;\n}\n```\n\n## Asynchronous Data Services\n\nStrategies:\n\n- Callback\n- Promise\n- Observables\n\n### Callback Hell\n\n```typescript\ngetRootFolder(folder =\u003e {\n    getAssetsFolder(folder, assets =\u003e {\n        getPhotos(assets, photos =\u003e {\n            ...\n        })\n    })\n})\n```\n\n### Promises\n\n```typescript\ngetRootFolder().then(getAssetsFolder).then(getPhotos)\n```\n\nLimitations:\n\n- They cannot be canceled\n- They are immediately executed\n- They are one time operations, no easy retry\n- They respond with only one value\n\n### Observables\n\nObservables will emit values over a period of time.\nTo create an observable:\n\n- Operator \"of\"\n- Keyword \"new\" Observable\n\n_It is good practice to name observable variables ending with \"$\"._\n\nObservables maintain a list of observers and inform them of data changes.\n\n- **Subscribe** : We can subscribe to an observable to follow multiple changes.\n- **toPromise** : We can use it to get a promise (single change).\n- **pipe** : We can pipe observed changes before subscribing to them.\n  The pipe method allows for multiple params (from 'rxjs/operators') manipulating data like a recipe.\n\n### Reactive Functional Programming\n\nA programming paradigm for reactive programming (asynchronous dataflow programming) using the building blocks of functional programming (e.g. map, reduce, filter). FRP has been used for programming graphical user interfaces (GUIs), robotics, games, and music, aiming to simplify these problems by explicitly modeling time.\n\n### Angular In Memory Web API\n\nAn in-memory web api for Angular demos and tests (not for production) that emulates CRUD operations over a REST API. It intercepts Angular Http and HttpClient requests that would otherwise go to the remote server and redirects them to an in-memory data store that you control.\n\n- Install the package\n\n  \u003e npm install angular-in-memory-web-api --save-dev\n\n- Generate a service\n\n  \u003e ng g s services/data --skip-tests\n\n- Make the DataService class implement InMemoryDbService\n- Implement the 'createDb' function and make it return an array (with or w/o data)\n- Add HttpClientInMemoryWebApiModule.forRoot(DataService) to the imports in the module.ts\n\n_We use .forRoot to implement the service as a singleton for the whole application._\n\n### HttpClientModule\n\nThe HttpClientModule provides a variety of Angular services that we can use to handle asynchronous HTTP communication.\n\nThe HttpClient service has methods representing all the possible HTTP verbs and return observable streams we can subscribe to.\n\n### Auth Interceptor\n\nWe can create a service and implement HttpInterceptor, or we can use:\n\n\u003e ng g interceptor auth\n\nThat implements the method:\n\n```typescript\nintercept(req: HttpRequest\u003cany\u003e, next: HttpHandler): Observable\u003cHttpEvent\u003cany\u003e\u003e {\n    return next.handle(req)\n}\n```\n\nAnd add a provider to the module:\n\n```typescript\nproviders: [\n    {\n        provide: HTTP_INTERCEPTORS,\n        useClass: AuthInterceptorService;\n        multi: true\n    }\n],\n```\n\n### Handling HTTP Errors\n\nWe can pipe our HTTP requests to catch errors using catchError:\n\n```typescript\nimport { catchError, retry } from 'rxjs/operators'\n...\ngetHeroes(): Observable\u003cHero[]\u003e {\n    return this.http.get\u003cHero[]\u003e(heroesUrl).pipe(\n        retry(2),\n        catchError((error: HttpErrorResponse) =\u003e {\n            console.error(error)\n            return throwError(error)\n        })\n    )\n}\n```\n\n_We can also easily add some retry logic._\n\n### Cleaning Up Resources\n\n- Unsubscribe from observables manually\n- Use the _async_ pipe\n\n## Libraries\n\nTo create a library:\n\n\u003e ng g library libraryName\n\nTo add components to our library:\n\n\u003e ng g c name --project libraryName\n\nWe should not forget to build our library:\n\n\u003e ng build libraryName\n\nTo add 3d party libraries or our own previously created ones:\n\n\u003e ng add libraryName\n\n## Routing\n\nHTML 5 Style:\n\n- LEverages HTML 5 history pushState\n- Default\n- More natural url\n- Requires url rewriting\n\nHash-based:\n\n- Leverages url fragments\n- Does not require url rewriting\n- Set by using the option:\n\n```\n{ useHash: true }\n```\n\n## Production\n\nThe angular CLI command to build our application used to te a parameter --prod to create a production build, because the default value was --dev.\n\nHowever, now the default creates a production build:\n\n\u003e ng build\n\nBy default lazy loaded modules get loaded on demand. We can change the strategy of our application in regards of when to load our lazy loaded modules.\n\nFor example, in our app.module we add:\n\n```typescript\n@NgModule({\n    imports: [\n        ...\n        RouterModule.forRoot(appRoutes, {preloadingStrategy: PreloadAllModules})\n        ...\n    ]\n})\n```\n\nWe can also create our own (more complex) preloading strategies.\n\n## Testing\n\n### Testing With(out) Testbed\n\nWhen Angular CLI generates components it also generates tests in \\*.spec.ts. These contain some boilerplate implementing a testbed for template testing, like in [this default example](jestProject/src/app/heroes/heroes.component.spec.ts). When we aren't testing against the template however, we can speed up testing by not using the testbed like in [this faster example](testProject/src/app/hero/hero.component.spec.ts).\n\n### Common commands\n\n\u003e ng test  \n\u003e npm test  \n\u003e ng test --watch false  \n\u003e npm test --watch false  \n\u003e ng test --code-coverage  \n\u003e ng test --karma-config karma.conf.js --watch false\n\nTo always get code coverage, edit _angular.json_:\n\n```json\n\"test\": {\n    \"options\": {\n        \"codeCoverage\": true\n    }\n}\n```\n\nTo run tests on _FireFox_ browser:\n\n\u003e npm install karma-firefox-launcher\n\nTo run tests on _Edge_ browser:\n\n\u003e npm install karma-edge-launcher\n\nTo run tests on _Chromium-Edge_ browser:\n\n\u003e npm install -D @chiragrupani/karma-chromium-edge-launcher\n\nAnd edit _karma.conf.js_:\n\n```json\nplugins: [\n    require('karma-firefox-launcher'),\n    // require('karma-edge-launcher'),\n    require('@chiragrupani/karma-chromium-edge-launcher'),\n    ]\n...\nbrowsers: ['Chrome','Edge','Firefox']\n```\n\nOr don't edit browsers array and run individually:\n\n\u003e ng test --browsers Edge  \n\u003e ng test --browsers Firefox\n\n### General Concepts\n\n- Tests\n  - Unit Tests\n    - Isolated Unit Tests\n    - Integrated Unit Tests (including template)\n      - Shallow Test\n      - Deep Tests (including children)\n  - End-to-end Tests\n- AAA\n  - Arrange\n  - Act\n  - Assert\n- Mocking\n  - Mocking objects to mimic their behavior without their full functionality\n\n### Jasmine\n\nJasmine is the default unit testing framework in Angular.\n\nMain functions:\n\n- describe()\n- beforeEach()\n- it()\n- expect()\n  - Matchers\n    - toBe()\n    - toContain()\n    - toBeDefined()\n\n### Karma\n\nKarma is the command line test runner. It can launch multiple browsers to run our tests depending on how it is configured.\n\n### Protractor\n\nProtractor was the default end-to-end testing framework in Angular, up until Angular 12.\nIt is no longer recommended or even included, because there are better third party alternatives.\n\n## Testing with Other Frameworks\n\n### Jest\n\n[Full Migration Manual](https://www.amadousall.com/how-to-set-up-angular-unit-testing-with-jest/)\n\nAutomated migration:\n\n\u003e ng add @briebug/jest-schematic\n\nCommon commands:\n\n\u003e ng test  \n\u003e npm test  \n\u003e ng test --coverage  \n\u003e npx jest --coverage  \n\u003e ng test --watch  \n\u003e npx jest --watch  \n\u003e ng test --watchAll  \n\u003e npx jest --watchAll\n\n### Mocha\n\n[Full Migration Manual](https://www.radzen.com/blog/testing-angular-webpack-mocha/)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh3ar7b3a7%2Fearlyangularprojects","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fh3ar7b3a7%2Fearlyangularprojects","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fh3ar7b3a7%2Fearlyangularprojects/lists"}