<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ng-conf</title>
    <description>The latest articles on DEV Community by ng-conf (@ngconf).</description>
    <link>https://dev.to/ngconf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F272124%2Fdc3c2f21-9b44-4055-a636-42f503a49237.jpg</url>
      <title>DEV Community: ng-conf</title>
      <link>https://dev.to/ngconf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ngconf"/>
    <language>en</language>
    <item>
      <title>Angular architecture matters: Monorepo</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Wed, 15 Sep 2021 15:52:00 +0000</pubDate>
      <link>https://dev.to/ngconf/angular-architecture-matters-monorepo-2n11</link>
      <guid>https://dev.to/ngconf/angular-architecture-matters-monorepo-2n11</guid>
      <description>&lt;p&gt;Sergio Ausin | ng-conf | Feb 2019&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F540%2F1%2AjVGw66Ku1K2HslRGKcQT2w.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F540%2F1%2AjVGw66Ku1K2HslRGKcQT2w.jpeg" alt="a meme. the image is Chuck Norris giving a thumbs up, the text reads "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whenever you start a new project, one of the first decisions we made is the structure of our code base. This is important because we do not want to have spaghetti code, features breaking when code changes... A few years ago, I worked in a project that comprises several apps with shared libraries. At first, everything was fine: apps were very small, few requirements; but every small app converts into a big one. The problem appeared when the first critical bug was reported. The typical steps to solve any bug were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify the cause&lt;/li&gt;
&lt;li&gt;Patch the affected code&lt;/li&gt;
&lt;li&gt;Build a new version of the library. We used semantic versioning&lt;/li&gt;
&lt;li&gt;Upload it to the private NPM repository&lt;/li&gt;
&lt;li&gt;Update &lt;strong&gt;every app&lt;/strong&gt; using the library&lt;/li&gt;
&lt;li&gt;Verify that everything is working as intended (launch e2e tests, unit tests, etc.)&lt;/li&gt;
&lt;li&gt;Finally, we released a new version of the apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Obviously, if something went wrong we have to repeat some of these steps. This process may be a pain in the ass when you have to update several applications. On the other hand, you also have to be aware of the applications that are using the affected library. I wasted a lot of time upgrading libraries, so I decided to look for a better way to deal with this problem: the monorepository. The main advantages of this approach are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same library version for every app&lt;/li&gt;
&lt;li&gt;Ease of maintenance: when you update a shared library, you update it for all apps.&lt;/li&gt;
&lt;li&gt;No conflicts between versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach is followed by Google and Facebook, among others. So, if you did not know it, you should give it a try! To help us with this task, the guys from Nrwl have created NX.&lt;/p&gt;

&lt;h3&gt;
  
  
  NX by Nrwl
&lt;/h3&gt;

&lt;p&gt;NX is an extension for the @angular/cli that implements the monorepo-style development. It provides a set of code generators, libraries, linters…&lt;/p&gt;

&lt;p&gt;For example, we can create an application with layered architecture: logic, user interface, etc. The picture below shows an example of layered architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F398%2F1%2AB-CqxVvZrC4kKSmCRIzYtA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F398%2F1%2AB-CqxVvZrC4kKSmCRIzYtA.png" alt="Image of a monorepo folder setup. "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Monorepo folder structure
&lt;/h6&gt;

&lt;p&gt;In the libs folder, there is a “three level” directory tree.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First level: the name of the apps. Inside this directory, there are the libs that our app will use&lt;/li&gt;
&lt;li&gt;Second level: the use case/page directory&lt;/li&gt;
&lt;li&gt;Third level: the “layer” directory. There are some typical libraries that I use: core for services, user-interface for components and a routing library &lt;strong&gt;which is lazy loaded&lt;/strong&gt; by the app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture follows these rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A core library must not import a user interface library&lt;/li&gt;
&lt;li&gt;A core library must not import a routes library&lt;/li&gt;
&lt;li&gt;A user interface library must not import a routes library&lt;/li&gt;
&lt;li&gt;A shared library must not import a non-shared library&lt;/li&gt;
&lt;li&gt;A use case library must not import another use case library&lt;/li&gt;
&lt;li&gt;A library must not import an app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To be consistent and make sure that we are following correctly the layered architecture, NX provides us a lint rule: “nx-enforce-module-boundaries”. To make it works, we have to set up some tags in every library. Those tags are set up in the nx.json file:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;{&lt;br&gt;
  "npmScope": "ngconf",&lt;br&gt;
  "implicitDependencies": {&lt;br&gt;
    "angular.json": "&lt;em&gt;",&lt;br&gt;
    "package.json": "&lt;/em&gt;",&lt;br&gt;
    "tsconfig.json": "&lt;em&gt;",&lt;br&gt;
    "tslint.json": "&lt;/em&gt;",&lt;br&gt;
    "nx.json": "*"&lt;br&gt;
  },&lt;br&gt;
  "projects": {&lt;br&gt;
    "web-app": {&lt;br&gt;
      "tags": []&lt;br&gt;
    },&lt;br&gt;
    "web-app-e2e": {&lt;br&gt;
      "tags": []&lt;br&gt;
    },&lt;br&gt;
    "web-app-home-core": {&lt;br&gt;
      "tags": [&lt;br&gt;
        "scope:home",&lt;br&gt;
        "type:core"&lt;br&gt;
      ]&lt;br&gt;
    },&lt;br&gt;
    "web-app-home-user-interface": {&lt;br&gt;
      "tags": [&lt;br&gt;
        "scope:home",&lt;br&gt;
        "type:user-interface"&lt;br&gt;
      ]&lt;br&gt;
    },&lt;br&gt;
    "web-app-home-routes": {&lt;br&gt;
      "tags": [&lt;br&gt;
        "scope:home",&lt;br&gt;
        "type:routes"&lt;br&gt;
      ]&lt;br&gt;
    },&lt;br&gt;
    "web-app-workshops-core": {&lt;br&gt;
      "tags": [&lt;br&gt;
        "scope:workshops",&lt;br&gt;
        "type:core"&lt;br&gt;
      ]&lt;br&gt;
    }&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h6&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  &lt;a href="https://gist.github.com/Stronhold/c6e506988e05763d4d6a547953cd31c3#file-nx-json" rel="noopener noreferrer"&gt;nx.json&lt;/a&gt; hosted by GitHub&lt;br&gt;
&lt;/h6&gt;

&lt;p&gt;For this example, I have used the tags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scope: for the use case&lt;/li&gt;
&lt;li&gt;Type: for the layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we have set up correctly our nx.json file, we have to add the “nx-enforce-module-bundaries” rule to our tslint.json file.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;{&lt;br&gt;
  ...&lt;br&gt;
  "rules": {&lt;br&gt;
    ... // other tslint rules&lt;br&gt;
    "nx-enforce-module-boundaries": [&lt;br&gt;
      true,&lt;br&gt;
      {&lt;br&gt;
        "allow": [],&lt;br&gt;
        "depConstraints": [&lt;br&gt;
          {&lt;br&gt;
            "sourceTag": "scope:shared",&lt;br&gt;
            "onlyDependOnLibsWithTags": [&lt;br&gt;
              "scope:shared"&lt;br&gt;
            ]&lt;br&gt;
          },&lt;br&gt;
          {&lt;br&gt;
            "sourceTag": "scope:home",&lt;br&gt;
            "onlyDependOnLibsWithTags": [&lt;br&gt;
              "scope:home",&lt;br&gt;
              "scope:shared"&lt;br&gt;
            ]&lt;br&gt;
          },&lt;br&gt;
          {&lt;br&gt;
            "sourceTag": "type:core",&lt;br&gt;
            "onlyDependOnLibsWithTags": [&lt;br&gt;
              "type:core"&lt;br&gt;
            ]&lt;br&gt;
          },&lt;br&gt;
          {&lt;br&gt;
            "sourceTag": "type: user-interface",&lt;br&gt;
            "onlyDependOnLibsWithTags": [&lt;br&gt;
              "type:core"&lt;br&gt;
            ]&lt;br&gt;
          }&lt;br&gt;
        ]&lt;br&gt;
      }&lt;br&gt;
    ]&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h6&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  &lt;a href="https://gist.github.com/Stronhold/15d68429a8420bbab617861d8880e17a#file-tslint-json" rel="noopener noreferrer"&gt;tslint.json&lt;/a&gt; hosted by GitHub&lt;br&gt;
&lt;/h6&gt;

&lt;p&gt;With this simple configuration we achieve the following goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Home libraries can import home and shared libs&lt;/li&gt;
&lt;li&gt;Core libraries can only import core libraries&lt;/li&gt;
&lt;li&gt;user-interface libraries can only import core libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try to import a user-interface library from a core lib you will see the following error message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A project tagged with “type:core” can only depend on libs tagged with “type:core”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  To sum up
&lt;/h4&gt;

&lt;p&gt;NX enforces quality and consistency when we develop our apps. It gives us some good practices that we should follow when we are developing our apps!&lt;/p&gt;




&lt;h2&gt;
  
  
  EnterpriseNG is coming November 4th &amp;amp; 5th, 2021.
&lt;/h2&gt;

&lt;p&gt;Come hear top community speakers, experts, leaders, and the Angular team present for 2 stacked days on everything you need to make the most of Angular in your enterprise applications.&lt;br&gt;
Topics will be focused on the following four areas:&lt;br&gt;
   • Monorepos&lt;br&gt;
    • Micro frontends&lt;br&gt;
   • Performance &amp;amp; Scalability&lt;br&gt;
   • Maintainability &amp;amp; Quality&lt;br&gt;
Learn more here &amp;gt;&amp;gt; &lt;a href="https://enterprise.ng-conf.org/" rel="noopener noreferrer"&gt;https://enterprise.ng-conf.org/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>nrwlnx</category>
    </item>
    <item>
      <title>Become an Angular contributor: Where to Start</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Mon, 30 Aug 2021 22:11:23 +0000</pubDate>
      <link>https://dev.to/ngconf/become-an-angular-contributor-where-to-start-50hh</link>
      <guid>https://dev.to/ngconf/become-an-angular-contributor-where-to-start-50hh</guid>
      <description>&lt;p&gt;Michael Prentice | ng-conf | Feb 2019&lt;/p&gt;

&lt;p&gt;This is part 1 of a multi-post guide to contributing to Angular open source projects.&lt;/p&gt;

&lt;p&gt;There are many personal and professional &lt;a href="https://hackernoon.com/benefits-of-contributing-to-open-source-2c97b6f529e9" rel="noopener noreferrer"&gt;benefits to contributing to open source&lt;/a&gt; software projects. These may include an enhanced learning experience, the emotional feedback of helping a community, or establishing your public profile and building a reputation.&lt;/p&gt;

&lt;p&gt;If you have attended &lt;a href="https://www.2021.ng-conf.org/" rel="noopener noreferrer"&gt;ng-conf&lt;/a&gt; (or another &lt;a href="https://angular.io/events" rel="noopener noreferrer"&gt;Angular Community Conference&lt;/a&gt;) or have spoken to a past attendee, you may have seen or heard about the amazing, inclusive Angular community. You may have felt a desire to get more involved or to help give back to the community. This series of posts will help you do that while reducing some of the unknowns and concerns that many new contributors first encounter.&lt;/p&gt;

&lt;h4&gt;
  
  
  What and Where?
&lt;/h4&gt;

&lt;p&gt;The first issue that many new contributors run into is that they have a desire to help, but they don’t know where to start.&lt;/p&gt;

&lt;p&gt;When a new contributor looks at the &lt;a href="https://github.com/angular/" rel="noopener noreferrer"&gt;Angular organization on GitHub&lt;/a&gt;, it can be a bit intimidating. There are 189 repositories that span AngularJS (version 1.x), Angular (version 2+), Testing, Builds, Tooling, Documentation, and Components.&lt;/p&gt;

&lt;p&gt;Throughout this series of posts, we’re going to break this down and disambiguate these repositories… In this first post, we’ll provide focus on the core Angular Framework repository and its related packages. In future posts, we’ll cover the Angular CLI, Material Components, and provide details about some of the ancillary repositories and naming patterns.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AAY9eWitW5HAPjmClkOPUJA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AAY9eWitW5HAPjmClkOPUJA.jpeg" alt="image of 5 people joining hands in a cheer pile over a work desk. the angular logo is in the foreground over their hands"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Contributing to Angular (original &lt;a href="https://pixabay.com/photos/team-team-building-success-computer-3373638/" rel="noopener noreferrer"&gt;background&lt;/a&gt;, &lt;a href="https://angular.io/assets/images/logos/angular/angular.png" rel="noopener noreferrer"&gt;foreground&lt;/a&gt;)
&lt;/h6&gt;

&lt;h4&gt;
  
  
  The angular/angular Repository
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;URL:&lt;/strong&gt; github.com/angular/angular&lt;/p&gt;

&lt;h4&gt;
  
  
  Description
&lt;/h4&gt;

&lt;p&gt;This repository hosts the Angular Framework, its core packages, and documentation.&lt;/p&gt;

&lt;p&gt;The core packages are found in the &lt;code&gt;[packages/&lt;/code&gt; directory](&lt;a href="https://github.com/angular/angular/tree/master/packages" rel="noopener noreferrer"&gt;https://github.com/angular/angular/tree/master/packages&lt;/a&gt;) and they include:&lt;/p&gt;

&lt;h4&gt;
  
  
  animations
&lt;/h4&gt;

&lt;p&gt;Code related to animating HTML elements using CSS. &lt;a href="https://angular.io/guide/animations" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  bazel
&lt;/h4&gt;

&lt;p&gt;Code related to building Angular using the open source &lt;a href="https://bazel.build/" rel="noopener noreferrer"&gt;Bazel build system&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  benchpress
&lt;/h4&gt;

&lt;p&gt;Code related to End-to-End Performance testing of Angular using benchmarking. &lt;a href="https://github.com/angular/angular/blob/master/packages/benchpress/README.md" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  common
&lt;/h4&gt;

&lt;p&gt;Code related to &lt;a href="https://angular.io/guide/pipes" rel="noopener noreferrer"&gt;common pipes&lt;/a&gt; (JSON, date, async, etc.), directives (&lt;code&gt;*ngIf&lt;/code&gt;, &lt;code&gt;*ngFor&lt;/code&gt;, &lt;code&gt;ngStyle&lt;/code&gt;, &lt;code&gt;ngPlural&lt;/code&gt;, etc.), location and path strategies, and internationalization (localization, date/number/currency formatting, etc.)&lt;/p&gt;

&lt;h4&gt;
  
  
  compiler-cli
&lt;/h4&gt;

&lt;p&gt;Code related to the &lt;code&gt;ngcc&lt;/code&gt; and &lt;code&gt;ngtsc&lt;/code&gt; compiler Command Line Interfaces (CLIs)&lt;/p&gt;

&lt;h4&gt;
  
  
  compiler
&lt;/h4&gt;

&lt;p&gt;Code related to the Angular compiler including Ahead of Time (AOT), Just In Time (JIT), internationalization, parsers (templates, expressions, CSS), the view compiler, and compiler utilities&lt;/p&gt;

&lt;h4&gt;
  
  
  core
&lt;/h4&gt;

&lt;p&gt;Code related to Change Detection, &lt;a href="https://angular.io/guide/dependency-injection" rel="noopener noreferrer"&gt;Dependency Injection&lt;/a&gt;, renderers, the linker, sanitization, metadata, and the View&lt;/p&gt;

&lt;h4&gt;
  
  
  elements
&lt;/h4&gt;

&lt;p&gt;Code related to packaging &lt;a href="https://angular.io/guide/architecture-components" rel="noopener noreferrer"&gt;Angular components&lt;/a&gt; as &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements" rel="noopener noreferrer"&gt;Custom Elements&lt;/a&gt;. &lt;a href="https://angular.io/guide/elements" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  forms
&lt;/h4&gt;

&lt;p&gt;Code related to integrating Angular with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form" rel="noopener noreferrer"&gt;Forms&lt;/a&gt; using a &lt;a href="https://angular.io/guide/forms" rel="noopener noreferrer"&gt;template-based&lt;/a&gt; or &lt;a href="https://angular.io/guide/reactive-forms" rel="noopener noreferrer"&gt;Reactive&lt;/a&gt; style. &lt;a href="https://angular.io/guide/forms-overview" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  http
&lt;/h4&gt;

&lt;p&gt;Code related to integrating Angular applications with backend APIs using the HTTP protocol. &lt;a href="https://angular.io/guide/http" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  language-service
&lt;/h4&gt;

&lt;p&gt;Code related to the Angular Language Service which provides enhanced support for editors that provide code completion, error highlighting, hints, and code navigation. &lt;a href="https://angular.io/guide/language-service" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  platform-*
&lt;/h4&gt;

&lt;p&gt;Code related to specific platforms that Angular supports including &lt;a href="https://angular.io/guide/universal" rel="noopener noreferrer"&gt;Server Side Rendering&lt;/a&gt; (server), &lt;a href="https://angular.io/guide/browser-support" rel="noopener noreferrer"&gt;web browsers&lt;/a&gt; (browser, browser-dynamic), and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers" rel="noopener noreferrer"&gt;Web Workers&lt;/a&gt; (webworker, webworker-dynamic)&lt;/p&gt;

&lt;h4&gt;
  
  
  router
&lt;/h4&gt;

&lt;p&gt;Code related to the Angular Router. &lt;a href="https://angular.io/guide/router" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  service-worker
&lt;/h4&gt;

&lt;p&gt;Code related to using &lt;a href="https://developers.google.com/web/fundamentals/primers/service-workers/" rel="noopener noreferrer"&gt;Service Workers&lt;/a&gt; with Angular. &lt;a href="https://angular.io/guide/service-worker-intro" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  upgrade
&lt;/h4&gt;

&lt;p&gt;Code related to upgrading or downgrading modules to migrate from AngularJS to Angular. &lt;a href="https://angular.io/guide/upgrade" rel="noopener noreferrer"&gt;Guide&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Documentation
&lt;/h4&gt;

&lt;p&gt;Additionally, this repository hosts &lt;a href="https://github.com/angular/angular/tree/master/aio" rel="noopener noreferrer"&gt;the code for the primary documentation site&lt;/a&gt;: &lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;angular.io&lt;/a&gt; (abbreviated &lt;code&gt;aio&lt;/code&gt; in the repository). If you want to help with the documentation, you’ll need to follow the &lt;a href="https://github.com/angular/angular/blob/master/aio/README.md" rel="noopener noreferrer"&gt;AIO Developer Guide&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Contribution Guide
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://github.com/angular/angular/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;Angular Contribution Guide&lt;/a&gt; covers a lot of topics including where to &lt;a href="https://stackoverflow.com/questions/tagged/angular" rel="noopener noreferrer"&gt;submit questions&lt;/a&gt;, where to &lt;a href="https://github.com/angular/angular/blob/master/CONTRIBUTING.md#submit-issue" rel="noopener noreferrer"&gt;submit bugs&lt;/a&gt;, how to &lt;a href="https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-missing-a-feature" rel="noopener noreferrer"&gt;submit feature requests&lt;/a&gt;, how to &lt;a href="https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-a-pull-request-pr" rel="noopener noreferrer"&gt;create pull requests&lt;/a&gt;, and how to join the &lt;a href="https://gitter.im/angular/angular" rel="noopener noreferrer"&gt;live community chat&lt;/a&gt; for real-time help. It also covers coding standards, Git commit message guidelines, and details about signing a Contributor License Agreement (CLA).&lt;/p&gt;

&lt;p&gt;Additionally, you can join or participate in the Angular mailing list via &lt;a href="https://groups.google.com/forum/#!forum/angular" rel="noopener noreferrer"&gt;Google Groups&lt;/a&gt;. The mailing list is a good place to ask questions that you might have before submitting a bug or feature request.&lt;/p&gt;

&lt;h4&gt;
  
  
  Help with new issues
&lt;/h4&gt;

&lt;p&gt;Contribution is not only about making source code updates. One great way to start contributing is to comment on newly reported issues that you are knowledgeable about. This includes helping provide reproductions on &lt;a href="https://stackblitz.com/" rel="noopener noreferrer"&gt;StackBlitz&lt;/a&gt; or debugging someone’s problem locally to see if you can reproduce it. It may also include doing some research and reviewing the API docs to see if the issue reported is using the API properly and if it has the proper syntax. If you aren’t ready to start fixing bugs or updating docs, this is a great way to learn while contributing to the community.&lt;/p&gt;

&lt;h4&gt;
  
  
  Help with pull request reviews
&lt;/h4&gt;

&lt;p&gt;If you are an experienced developer or if you want to move beyond helping others with issues, you can help by reviewing pull requests. In many cases, it is helpful just to politely ask someone to explain why they took a specific approach. Sometimes when a pull request author explains their approach to a reviewer, they realize that there is a better way that they had previously not considered. Other times they realize that they did not consider certain edge cases. The pull request author’s responses and discussion can help you learn more about the project and better equip you for making source code contributions.&lt;/p&gt;

&lt;p&gt;If you have questions about any of these topics, please leave a comment and I will do my best to provide an answer for you.&lt;/p&gt;

&lt;h4&gt;
  
  
  Good First Issues
&lt;/h4&gt;

&lt;p&gt;You can find issues that are good for new contributors &lt;a href="https://github.com/angular/angular/labels/hotlist%3A%20community-help" rel="noopener noreferrer"&gt;here&lt;/a&gt;. These issues are generally limited in scope and have better guidance and instructions than a standard issue.&lt;/p&gt;

&lt;p&gt;If you have questions or concerns about one of these issues, please post it as a comment on the issue. Please note that there are no stupid questions here. If you need help or guidance, please post a comment to ask for it. This is what these issues are designed for.&lt;/p&gt;

&lt;p&gt;Note that some questions, that require a significant amount of effort to address, may receive a response that directs you to a specific educational resource. This may be a blog post, Markdown document, Podcast, etc.&lt;/p&gt;

&lt;h4&gt;
  
  
  Code of Conduct
&lt;/h4&gt;

&lt;p&gt;Please note that the &lt;a href="https://github.com/angular/angular/blob/master/CODE_OF_CONDUCT.md" rel="noopener noreferrer"&gt;Angular Code of Conduct&lt;/a&gt; applies to all interactions within the Angular community. This includes public and private communications between Angular community members. The following are some examples of where you should follow the Code of Conduct: GitHub, Gitter, IRC, mailing lists, Twitter, Conferences, Podcasts, instant messaging, face to face communications, conference calls, interviews, press releases, website and blog content, etc. Any questions or violations should be sent to &lt;a href="mailto:conduct@angular.io"&gt;conduct@angular.io&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Developer Guide
&lt;/h4&gt;

&lt;p&gt;The &lt;a href=""&gt;Angular Developer Guide&lt;/a&gt; includes details about prerequisites, getting the source code, installing dependencies, building the Angular framework, and running tests locally.&lt;/p&gt;

&lt;h4&gt;
  
  
  Next steps
&lt;/h4&gt;

&lt;p&gt;I plan to similarly document contributing to the Angular Command Line Interface (CLI), Angular Component Dev Kit (CDK), and the Angular Material Components.&lt;/p&gt;

&lt;p&gt;I also plan to dig into some of the details based upon feedback and what questions are raised by the community. This is especially true for the Developer Guide, but I’m waiting for a few of my PRs, that help smooth some rough edges, to land.&lt;/p&gt;

&lt;p&gt;Subscribe to the &lt;a href="https://medium.com/ngconf" rel="noopener noreferrer"&gt;ng-conf publication&lt;/a&gt; to be notified of those updates.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>angular</category>
      <category>opensource</category>
      <category>contribution</category>
    </item>
    <item>
      <title>Simplified Angular Change Detection</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Fri, 16 Jul 2021 19:10:48 +0000</pubDate>
      <link>https://dev.to/ngconf/simplified-angular-change-detection-242o</link>
      <guid>https://dev.to/ngconf/simplified-angular-change-detection-242o</guid>
      <description>&lt;p&gt;Pankaj Parker | ng-conf | Mar 2019&lt;/p&gt;

&lt;p&gt;A detailed guide to the core part of Angular Framework&lt;/p&gt;

&lt;p&gt;Angular is one of the most extraordinary javascript frameworks available, because it all the features required for the web development out of the box. The change detection system is at heart of framework, it essentially helps to update bindings on a page. In this article, we will learn about change detection in detail, in a simple and easy to understand way.&lt;/p&gt;

&lt;p&gt;Before we begin, let me highlight what principles frameworks or libraries to build applications these days.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rRX-tf-O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2A78Gg8QG_dnMsM4Dg9Ccmxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rRX-tf-O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2A78Gg8QG_dnMsM4Dg9Ccmxw.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  General Application Architecture
&lt;/h6&gt;

&lt;p&gt;Basically what we have is the state of our application, that we are trying to replicate on the UI, this is why we need data bindings on the template. Afterward we wire up “state + template” and replicate data on view. Also in the future, any changes that happen in the state get reflected on view.&lt;/p&gt;

&lt;p&gt;This process of syncing HTML with the state can be termed as “Change detection”, each framework has its own way of doing it. React uses virtual DOM with reconciliation algorithm, Angular uses change detection, etc. This article will cover how change detection works in Angular.&lt;/p&gt;




&lt;h3&gt;
  
  
  What is Change Detection?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;In simple word:- a process to synchronize the model/state changes to the view.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a simple example. Suppose we have a simple component with its own HTML like shown below.&lt;/p&gt;

&lt;h6&gt;
  
  
  a simple binding example
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;span&amp;gt;
  {{title}}
&amp;lt;/span&amp;gt;
&amp;lt;button (click)="title='Changed'"&amp;gt;
  Change Title
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/pankajparkar/2230996326a78f8d87ad9063af543863#file-app-component-html"&gt;app.component.html&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  title  = 'Angular'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/pankajparkar/2230996326a78f8d87ad9063af543863#file-app-component-ts"&gt;app.component.ts&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;&lt;code&gt;app.component.html&lt;/code&gt; has a simple &lt;code&gt;span&lt;/code&gt; which is displaying the &lt;code&gt;title&lt;/code&gt; property of a component and there is a &lt;code&gt;button&lt;/code&gt; on click which will modify the &lt;code&gt;title&lt;/code&gt; property value of &lt;code&gt;changed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GHUETbfm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/554/1%2A2Qbnhoa_sRau_oMXbk6puA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GHUETbfm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/554/1%2A2Qbnhoa_sRau_oMXbk6puA.gif" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  demo
&lt;/h6&gt;

&lt;p&gt;When the page gets happens, it shows "&lt;code&gt;Angular&lt;/code&gt;“ on the page. Later when we click on Change Title &lt;code&gt;button&lt;/code&gt; it changes the binding value to ”&lt;code&gt;Changed&lt;/code&gt;“. This is super awesome, the Angular framework manages this functionality for us. What it essentially does is, track the value changes which are automagically reflected on the UI. Awesome! Check this &lt;a href="https://stackblitz.com/edit/angular-vdqbzm"&gt;stackblitz&lt;/a&gt; of the above example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oaNHIQmx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://giphy.com/gifs/hulu-snl-saturday-night-live-nbc-3o7TKP9ln2Dr6ze6f6" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oaNHIQmx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://giphy.com/gifs/hulu-snl-saturday-night-live-nbc-3o7TKP9ln2Dr6ze6f6" alt='Gif of Shia LaBeouf from an SNL skit. He has long, thick, dark curly hair and a thick moustache. The gif shows him reaching behind his head then pulling out a fake bouquet of flowers while saying "magic".'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  magic
&lt;/h6&gt;

&lt;p&gt;Wondering 🤔 How angular updates the binding? That’s okay! Nothing really happens with magic, a framework must be running some code behind the scenes to do it. This process of updating binding is called as change detection. But the question is when angular running a change detection and how? To find out answers to these question, let’s dig a bit further.&lt;/p&gt;




&lt;h3&gt;
  
  
  When should change detection happen?
&lt;/h3&gt;

&lt;p&gt;The simple answer to this question would be “as soon as an application’s state changes”. But when does the application’s state can change? 🤔&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Event Callback&lt;/li&gt;
&lt;li&gt;Network Call (XHR)&lt;/li&gt;
&lt;li&gt;Timers (setTimeout, setInterval)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do you see any similarity in the examples above? Yes! they are all asynchronous. That means we can simply say any asynchronous call can cause a change in application state and that’s the instance where we should update our state on UI. So far so good!&lt;/p&gt;

&lt;p&gt;Suppose we’re building our own change detection system, we would be firing change detection after the above 3 situations.&lt;/p&gt;




&lt;p&gt;Let’s try to implement our own change detection system.&lt;/p&gt;

&lt;p&gt;We’re just making sure to call &lt;code&gt;detectChanges&lt;/code&gt; method from each method which includes XHR call, Timer, and Event. Just assume that the &lt;code&gt;detectChanges&lt;/code&gt; method is responsible for the actual change detection. The vague implementation of change detection would look like the example below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//network Call
getDataFromServer().then(()=&amp;gt; {
   //state has changed
   detectChanges();
})

//timeout function
setTimeout(()=&amp;gt; {
   //Call change detection
   detectChanges();
}, 5000)

element.addEventListner('click', (event) =&amp;gt;{
   //state could have change
   detectChanges();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/pankajparkar/e394e6f1b4ee0febfdc95cce12aab741#file-change-detection-js"&gt;change-detection.js&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;And the implementation of &lt;code&gt;detectionChanges&lt;/code&gt; method would look like the example below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let detectChanges =&amp;gt; () =&amp;gt; {
  if(currentState != prevState) {
    updateView(currentState);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/pankajparkar/adaf0a5e6935ca590c5e70a675db8831#file-detectchanges-js"&gt;detectChanges.js&lt;/a&gt;hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;Ah! but doing this thing inside our real-world application will mess up everything. Generally in a real-world application you could have this in hundreds of thousands of places. So what can be a better implementation of this? Basically, we can also say that we are supposed to fire change detection when VM turn is over.&lt;/p&gt;

&lt;h3&gt;
  
  
  ZoneJS to the rescue
&lt;/h3&gt;

&lt;p&gt;ZoneJS is an API which has been mostly ported out from the dart language. Behind the scenes, ZoneJS monkey patches the function. Basically, it helps to keep an eye on all async tasks, and provide an ability to call code before or after a task has been completed. The Zone API has different hooks to place your code &lt;code&gt;onBeforeTask&lt;/code&gt;, &lt;code&gt;onAfterTask&lt;/code&gt;, &lt;code&gt;onZoneCreated&lt;/code&gt;, &lt;code&gt;onError&lt;/code&gt;.&lt;/p&gt;

&lt;h6&gt;
  
  
  ZoneJS simple example
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var myZoneSpec = {
  beforeTask: function () {
    console.log('Before task');
  },
  afterTask: function () {
    console.log('After task');
  }
};

var myZone = zone.fork(myZoneSpec);
myZone.run(function() {
   console.log('My task successfully got executed.')
});

// Output:
// Before task
// My task successfully got executed.
// After task
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/pankajparkar/1ab93721db964177191b5702edf04807#file-zonejs-js"&gt;zonejs.js&lt;/a&gt;
&lt;/h6&gt;

&lt;p&gt;So Angular uses the power of Zones to fire change detection. What happens is, if any asynchronous call happens, ZoneJS API emits data to the &lt;code&gt;onMicrotaskEmpty&lt;/code&gt; observable, and angular calls the &lt;code&gt;detectChanges&lt;/code&gt; method based on the same.&lt;/p&gt;




&lt;h3&gt;
  
  
  What happens when Application Bootstrap?
&lt;/h3&gt;

&lt;p&gt;When an angular application bootstraps, it creates a platform for a bootstrapped angular module. It creates an &lt;a href="https://angular.io/api/core/ApplicationRef"&gt;ApplicationRef&lt;/a&gt; for a whole module. Basically, &lt;code&gt;ApplicationRef&lt;/code&gt; has a reference to &lt;code&gt;allcomponents&lt;/code&gt;, &lt;code&gt;componentTypes&lt;/code&gt; and &lt;code&gt;isStable&lt;/code&gt; (zone flag), also it has methods like &lt;code&gt;detatchView&lt;/code&gt;, &lt;code&gt;attachView&lt;/code&gt;, &lt;code&gt;tick&lt;/code&gt; etc. You can look at &lt;a href="https://github.com/angular/angular/blob/7.2.7/packages/core/src/application_ref.ts#L346-L656"&gt;this line&lt;/a&gt; from the source code.&lt;/p&gt;

&lt;p&gt;Let’s have a quick look at &lt;a href="https://github.com/angular/angular/blob/7.2.7/packages/core/src/application_ref.ts"&gt;application_ref.ts&lt;/a&gt; from the angular source code. You will see that after creating an &lt;code&gt;ApplicationRef&lt;/code&gt;, it places a subscription on the &lt;code&gt;onMicrotaskEmpty&lt;/code&gt; observable, so as soon as the VM tick over it emits a value into &lt;code&gt;onMicrotaskEmpty&lt;/code&gt; observable, that will be listened to by a subscription, eventually that will call the &lt;code&gt;tick&lt;/code&gt; method inside the current Zone of application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this._zone.onMicrotaskEmpty.subscribe({
  next: () =&amp;gt; { 
    this._zone.run(() =&amp;gt; { 
      this.tick();
    }); 
  }}
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/pankajparkar/3dbac41c6116671fd67bb836cc4988f5#file-zone_tick-js"&gt;zone_tick.js&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;Let’s look into how the &lt;code&gt;tick&lt;/code&gt; method works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tick(): void {
    try {
      this._views.forEach((view) =&amp;gt; view.detectChanges());
      if (this._enforceNoNewChanges) {
        this._views.forEach((view) =&amp;gt; view.checkNoChanges());
      }
    } catch (e) {
      ...
    } finally {
      ...
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/pankajparkar/2b5c84d5686544ac253c798d980b770f#file-tick_implementation-js"&gt;tick_implementation.js&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;Implementation of the tick method looks pretty simple. It basically loops over each view (components are internally referred to as view) and calls their &lt;code&gt;detectChanges&lt;/code&gt; method which is responsible for updating UI bindings. The interesting thing is on the 4th line, it runs only in dev mode because in the &lt;a href="https://github.com/angular/angular/blob/7.2.7/packages/core/src/application_ref.ts#L475"&gt;application_ref.ts&lt;/a&gt; constructor it sets &lt;code&gt;to_enforceNoNewChanges&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;this._enforceNoNewChanges = isDevMode()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Above is a gist about how change detection works, let's dig deeper how we can use this while crafting Angular application.&lt;/p&gt;




&lt;h3&gt;
  
  
  Change Detection Strategy
&lt;/h3&gt;

&lt;p&gt;In total angular has two flavours of change detection.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Default&lt;/li&gt;
&lt;li&gt;OnPush&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's look at each change detection strategy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Default
&lt;/h3&gt;

&lt;p&gt;When you don’t specify the change detection strategy on the Component decorator, by default angular applies the &lt;code&gt;Default&lt;/code&gt; strategy.&lt;/p&gt;

&lt;p&gt;Any Angular application consists of components, the component where we bootstraped a root component. and we can draw out a diagram of an application with regards to a component. So if change detection fires in any component it will cause the &lt;code&gt;tick&lt;/code&gt; method to be fired in the &lt;code&gt;ApplicationRef&lt;/code&gt;. Ultimately firing &lt;code&gt;detectChanges&lt;/code&gt; method from root component to its descendants as shown in the diagram below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ybQWcEm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/600/1%2A4z3uSUDgJwzx1DGap_Xs1w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ybQWcEm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/600/1%2A4z3uSUDgJwzx1DGap_Xs1w.gif" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  change detection strategy — Default
&lt;/h6&gt;

&lt;p&gt;The problem with the default strategy is, changes that have been detected in on any component lead to firing change detection on all the components (if all component are set to &lt;code&gt;Default&lt;/code&gt; strategy. But most of the time we don’t need such behavior, it would eventually affect the performance of an application by running multiple unnecessary change detection cycle.&lt;/p&gt;

&lt;p&gt;Can we solve this problem efficiently? Luckily there is a solution, you can easily switch the change detection strategy to &lt;code&gt;OnPush&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  OnPush
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;onPush&lt;/code&gt; strategy makes component change detection bit smarter. It runs a change detection for a component only when &lt;code&gt;Input&lt;/code&gt; bindings value of a component is changed. Actually, it compares the reference between oldValue and newValue of a &lt;code&gt;Input&lt;/code&gt; binding. That means if a parent components properties of an object do not change it would not trigger change detection for that component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WUqy4_UA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/600/1%2AeBsnDz7-st7PSflEnWgTBA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WUqy4_UA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/600/1%2AeBsnDz7-st7PSflEnWgTBA.gif" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  change detection strategy — OnPush
&lt;/h6&gt;

&lt;p&gt;As you can see in the above diagram, we’ve set a level 1 component to &lt;code&gt;OnPush&lt;/code&gt; strategy. Both the component have the input of &lt;code&gt;name&lt;/code&gt;. The root component is passing the input &lt;code&gt;name&lt;/code&gt; to both the component with &lt;code&gt;name1&lt;/code&gt; and &lt;code&gt;name2&lt;/code&gt; respectively. On initial page load change detection fires on all the components. And later the right-hand side component emits an event, which tends to change the root component state.&lt;/p&gt;

&lt;p&gt;So, again change detection started firing from the root component. Then change detection runs for the 1st level (&lt;code&gt;OnPush&lt;/code&gt;) component. Before firing change detection on those components, it checks for the input binding &lt;code&gt;name&lt;/code&gt; newValue and oldValue and if there are changes then only fire change detection for that component and it’s descendants. Changes have been detected for the right-hand side component. So change detection gets triggered only for right-hand side branch of components. By setting &lt;code&gt;OnPush&lt;/code&gt; change detection strategy we can significantly improve application performance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Make sure you enforce immutability on the &lt;code&gt;Input&lt;/code&gt; binding value while using component &lt;code&gt;OnPush&lt;/code&gt; strategy.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Before proceeding we can have a look at a real application that is built using both change detection strategies. This application is deployed on &lt;a href="https://pankajparkar.github.io/demystifying-change-detection"&gt;https://pankajparkar.github.io/demystifying-change-detection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a pretty simple application, it has posts displayed on the page and each post can have comments. The way that the application architected, it’s component hierarchy shown below.&lt;/p&gt;

&lt;p&gt;root =&amp;gt; post-list (all posts)=&amp;gt; post (single post)=&amp;gt; comment-list&lt;/p&gt;

&lt;p&gt;The black border around the component indicates the boundary of that particular component.&lt;/p&gt;

&lt;p&gt;Since we want to keep eye on when change detection fires, we highlight the components to yellow as soon change detection fires. We have used &lt;code&gt;ngAfterViewChecked&lt;/code&gt; which tells us that the change detector has visited the current component.&lt;/p&gt;

&lt;h6&gt;
  
  
  highlight component on change detection fired
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngAfterViewChecked(): void {
  this.zone.runOutsideAngular(() =&amp;gt; {
    this.el.nativeElement.classList.add('highlight')
    setTimeout(() =&amp;gt; {
      this.el.nativeElement.classList.remove('highlight')
    }, 1500)
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/pankajparkar/fb93e6eca19032c5f3aa9022486e42be#file-highlight-ts"&gt;highlight.ts&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f_7Cfbum--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/600/1%2AKGNHAx09oL_h9EghTdHFgg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f_7Cfbum--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/600/1%2AKGNHAx09oL_h9EghTdHFgg.gif" alt="gif image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  all component on default strategy
&lt;/h6&gt;

&lt;p&gt;So you can see in the above diagram, on initial page load gets highlighted and they applied with &lt;code&gt;highlight&lt;/code&gt; class. Thereafter while adding a comment in a comment field, you can see that on each &lt;code&gt;keyup&lt;/code&gt; event it fires change detection and all component get highlighted.&lt;/p&gt;




&lt;p&gt;Now, look at the uses of the &lt;code&gt;OnPush&lt;/code&gt; change detection strategy, how it makes a difference in the change detection run cycle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8etQwdNU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/600/1%2ATyKytQEEpQwxvcVuAHpLEg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8etQwdNU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://miro.medium.com/max/600/1%2ATyKytQEEpQwxvcVuAHpLEg.gif" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right now all the components are set to &lt;code&gt;OnPush&lt;/code&gt; strategy. So on page load change detection runs for all components, that’s perfectly fine. Thereafter when I tried to add a text in the comment section, it fires change detection for the comments section of the current component, not others. That’s great! But you can see that the other components post components are getting highlighted.&lt;/p&gt;

&lt;p&gt;Ah! What is going on? PostComponent is already set to &lt;code&gt;OnPush&lt;/code&gt;, there is no &lt;code&gt;Input&lt;/code&gt; binding on that component but it seems to be changed. Is this a bug, is the ngAfterViewChecked lifecycle hook being called without reason? Perhaps.&lt;/p&gt;

&lt;p&gt;Let’s not get confused. We can look into further.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xPBIY-Rh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2ASdyHaw71UOajmOzoAsRDZw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xPBIY-Rh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2ASdyHaw71UOajmOzoAsRDZw.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Taken from &lt;a href="https://blog.angularindepth.com/@maxim.koretskyi"&gt;Max Koretskyi&lt;/a&gt; &lt;a href="https://blog.angularindepth.com/a-gentle-introduction-into-change-detection-in-angular-33f9ffff6f10"&gt;article&lt;/a&gt; from @angularInDepth
&lt;/h6&gt;

&lt;p&gt;Refer to the above diagram — When change detection is running for a parent component, it follows a certain process. Initially, it updates the binding of child components, then calls the &lt;code&gt;ngOnInit&lt;/code&gt;, &lt;code&gt;ngDoCheck&lt;/code&gt;, &lt;code&gt;ngOnChanges&lt;/code&gt; lifecycle hook of the child component. We can also state that this process happens before rendering the parent component. Then it updates the DOM on the current component. Later it runs change detection for a child component(depending on the strategy), followed by calling hooks &lt;code&gt;ngAfterViewChecked&lt;/code&gt;, &lt;code&gt;ngAfterViewInit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That means while running change detection of a parent component, it runs &lt;code&gt;ngDoCheck&lt;/code&gt;, &lt;code&gt;ngContentChecked&lt;/code&gt;, &lt;code&gt;ngAfterViewChecked&lt;/code&gt; lifecycle hooks of child component irrespective of a component change detection strategy.&lt;/p&gt;

&lt;p&gt;Check this &lt;a href="https://github.com/angular/angular/issues/7055"&gt;Github issue link&lt;/a&gt; logged by &lt;a href="https://medium.com/@pascalprecht"&gt;Pascal Precht ʕ•̫͡•ʔ&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might have missed, &lt;strong&gt;There is a catch.&lt;/strong&gt; If you look at the change detection strategy of &lt;a href="https://github.com/pankajparkar/demystifying-change-detection/blob/master/src/app/all-onpush-strategy/post-list/post-list.component.ts"&gt;&lt;code&gt;PostListComponent&lt;/code&gt;&lt;/a&gt;, it has been set to &lt;code&gt;OnPush&lt;/code&gt; strategy, but there is no &lt;code&gt;Input&lt;/code&gt; binding passed to it. So when &lt;a href="https://github.com/pankajparkar/demystifying-change-detection/blob/master/src/app/all-onpush-strategy/post-list/post-list.component.ts"&gt;&lt;code&gt;PostListComponent&lt;/code&gt;&lt;/a&gt; component retrieves a data form the &lt;code&gt;ngOnInit&lt;/code&gt; hook, it doesn’t run change detection from the root component (&lt;a href="https://github.com/pankajparkar/demystifying-change-detection/blob/master/src/app/app.component.ts"&gt;&lt;code&gt;AppComponent&lt;/code&gt;&lt;/a&gt;). But it prevents to running change detection on &lt;a href="https://github.com/pankajparkar/demystifying-change-detection/blob/master/src/app/all-onpush-strategy/post-list/post-list.component.ts"&gt;&lt;code&gt;PostListComponent&lt;/code&gt;&lt;/a&gt; since no &lt;code&gt;Input&lt;/code&gt; have been changed. So we had to call either the &lt;code&gt;detectChanges&lt;/code&gt; method or the &lt;code&gt;markForCheck&lt;/code&gt; method of &lt;code&gt;ChangeDetectorRef&lt;/code&gt; dependency. This will force change detection to run throughout. Such cases can easily happen in a real-world application. You can tackle such situations by calling &lt;code&gt;markForCheck&lt;/code&gt; or &lt;code&gt;detectChanges&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;h3&gt;
  
  
  The difference between calling &lt;code&gt;markForCheck&lt;/code&gt;, &lt;code&gt;detectionChanges&lt;/code&gt; and tick would be
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;markForCheck&lt;/code&gt; — Once you call &lt;code&gt;markForCheck&lt;/code&gt; method on component change detector, it will traverse a component tree till root, and mark those components to run change detection only for the next iteration. It will run change detection on marked component even though they are using the &lt;code&gt;OnPush&lt;/code&gt; strategy.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;detectChanges&lt;/code&gt; — When you call this method on &lt;code&gt;changeDetectorRef&lt;/code&gt; provider, it will run change detection from the current component and all it’s descendants. While running change detection it keeps the change detection strategy in mind.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tick&lt;/code&gt; — The &lt;code&gt;tick&lt;/code&gt; method applicable on &lt;code&gt;ApplicationRef&lt;/code&gt; API. It will run change detection from the root component to all its descendants. It respects the change detection strategy of a component.&lt;/p&gt;

&lt;p&gt;There are two more methods that exist in the &lt;code&gt;ChangeDetectorRef&lt;/code&gt; provider&lt;/p&gt;

&lt;p&gt;&lt;code&gt;detach&lt;/code&gt; — By calling this method you can pluck out a component from the tree of the current component to its descendants. Whenever there is a need for running change detection on the component you could call &lt;code&gt;detectChanges&lt;/code&gt; or &lt;code&gt;markForCheck&lt;/code&gt; method depends on your need.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reattach&lt;/code&gt; — A Plucked a component from the tree can be easily brought back to its original place by calling &lt;code&gt;reattach&lt;/code&gt; method. This can be used for fine tune application performance.&lt;/p&gt;




&lt;p&gt;I hope this article has helped you to understand the mystery of what’s under the hood of change detection. Eventually, this will also make you comfortable with predicting when change detection runs in your application. By applying various flavors you can easily gain performance benefits in your application.&lt;/p&gt;

&lt;p&gt;I gave a talk about this topic recently in #ngIndia&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=XTNL4WJRCrM&amp;lt;br&amp;gt;%0A"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fTP_BKrn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://img.youtube.com/vi/XTNL4WJRCrM/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you like this article press 👏 clap button 50 times or as many times you want. Feel free to ask a question if you have any. Thanks a lot for reading!&lt;/p&gt;

&lt;p&gt;Thanks Tayamba Mwanza for grammatical review 😊&lt;/p&gt;




&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Ready to build the most reliable web applications possible? Join us for the Reliable Web Summit this August 26th-27th, 2021 to learn how! A summit conference on building reliable web applications, including the following three pillars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scalable infrastructure and architecture&lt;/li&gt;
&lt;li&gt;Maintainable Code&lt;/li&gt;
&lt;li&gt;Automated Testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://reliablewebsummit.com/"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>MockStore in NgRx v7.0
</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Mon, 12 Jul 2021 18:30:49 +0000</pubDate>
      <link>https://dev.to/ngconf/mockstore-in-ngrx-v7-0-43a8</link>
      <guid>https://dev.to/ngconf/mockstore-in-ngrx-v7-0-43a8</guid>
      <description>&lt;p&gt;John Crowson | ng-conf | Apr 2019&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ngrx.io/"&gt;NgRx&lt;/a&gt; v7.0 included the released of a new &lt;code&gt;@ngrx/store/testing&lt;/code&gt; module that features a mock Store to be used in testing NgRx applications. The module was introduced in &lt;a href="https://github.com/ngrx/platform/pull/1027"&gt;#1027&lt;/a&gt; with some documentation following in &lt;a href="https://github.com/ngrx/platform/pull/1591"&gt;#1591&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: You can use this API and functionality in NgRx v5 and v6 using the standalone &lt;a href="https://www.npmjs.com/package/ngrx-mockstore"&gt;pngrx-mockstore&lt;/a&gt; package.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Currently, the documentation is light and doesn’t include a complete working code sample. I’ll provide two examples that should help clear things up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Existing: StoreModule
&lt;/h3&gt;

&lt;p&gt;It has been possible to condition the NgRx store in a unit test by providing the &lt;code&gt;StoreModule&lt;/code&gt; in the testing module configuration. The StoreModule creates a store with the initial state defined in the store’s reducer. To condition the desired state for a given test case, you could have to dispatch several actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  New: MockStore
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;MockStore&lt;/code&gt; class provides a simpler way to condition NgRx state in unit tests. You provide an initial default state, then update the state using &lt;code&gt;setState(&amp;lt;nextState&amp;gt;)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see how MockStore can simplify an existing test suite:&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Auth Guard Example
&lt;/h3&gt;

&lt;p&gt;The NgRx &lt;a href="https://github.com/ngrx/platform/tree/master/projects/example-app"&gt;example-app&lt;/a&gt; contains an AuthGuard that provides us a simple example of using the MockStore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// NgRx v7.3.0
@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivate {
  constructor(private store: Store&amp;lt;fromAuth.State&amp;gt;) {}

  canActivate(): Observable&amp;lt;boolean&amp;gt; {
    return this.store.pipe(
      select(fromAuth.getLoggedIn),
      map(authed =&amp;gt; {
        if (!authed) {
          this.store.dispatch(new AuthApiActions.LoginRedirect());
          return false;
        }

        return true;
      }),
      take(1)
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/jtcrowson/5653c6cb9fb64cc52066e81dc818742d#file-auth-guard-service-ts"&gt;auth-guard.service.ts&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;The &lt;code&gt;AuthGuard&lt;/code&gt; selects &lt;code&gt;getLoggedIn&lt;/code&gt; from the store. If the latest &lt;code&gt;getLoggedIn&lt;/code&gt; is true, a &lt;code&gt;LoginRedirect&lt;/code&gt; action is dispatched and the function returns false. If the latest getLoggedIn is false, it returns true.&lt;/p&gt;

&lt;p&gt;The existing AuthGuard test uses the &lt;code&gt;StoreModule&lt;/code&gt;, which requires the test to dispatch a &lt;code&gt;LoginSuccess&lt;/code&gt; action to condition the &lt;code&gt;getLoggedIn&lt;/code&gt; selector to return true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// NgRx v7.3.0
describe('Auth Guard', () =&amp;gt; {
  let guard: AuthGuard;
  let store: Store&amp;lt;any&amp;gt;;

  beforeEach(() =&amp;gt; {
    TestBed.configureTestingModule({
      imports: [
        StoreModule.forRoot({
          ...fromRoot.reducers,
          auth: combineReducers(fromAuth.reducers),
        }),
      ],
    });

    store = TestBed.get(Store);
    spyOn(store, 'dispatch').and.callThrough();
    guard = TestBed.get(AuthGuard);
  });

  it('should return false if the user state is not logged in', () =&amp;gt; {
    const expected = cold('(a|)', { a: false });

    expect(guard.canActivate()).toBeObservable(expected);
  });

  it('should return true if the user state is logged in', () =&amp;gt; {
    const user: any = {};
    const action = new AuthApiActions.LoginSuccess({ user });
    store.dispatch(action);

    const expected = cold('(a|)', { a: true });

    expect(guard.canActivate()).toBeObservable(expected);
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/jtcrowson/fdd258175821b344cd00cc7b2fc3f19f#file-auth-guard-service-spec-ts"&gt;auth-guard.service.spec.ts&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;Let’s refactor the same tests to condition the store’s state without actions using &lt;code&gt;MockStore&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Future version of example-app using MockStore
import { provideMockStore, MockStore } from '@ngrx/store/testing';

describe('Auth Guard', () =&amp;gt; {
  let guard: AuthGuard;
  let store: MockStore&amp;lt;fromAuth.State&amp;gt;;
  const initialState = {
    auth: {
      loginPage: {} as fromLoginPage.State,
      status: {
        user: null,
      },
    },
  } as fromAuth.State;

  beforeEach(() =&amp;gt; {
    TestBed.configureTestingModule({
      providers: [AuthGuard, provideMockStore({ initialState })],
    });

    store = TestBed.get(Store);
    guard = TestBed.get(AuthGuard);
  });

  it('should return false if the user state is not logged in', () =&amp;gt; {
    const expected = cold('(a|)', { a: false });

    expect(guard.canActivate()).toBeObservable(expected);
  });

  it('should return true if the user state is logged in', () =&amp;gt; {
    store.setState({
      ...initialState,
      auth: {
        loginPage: {} as fromLoginPage.State,
        status: {
          user: {
            name: 'John',
          },
        },
      },
    });

    const expected = cold('(a|)', { a: true });

    expect(guard.canActivate()).toBeObservable(expected);
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/jtcrowson/ed4881e111a4d36a81cbc9ba03acf689#file-auth-guard-service-spec-ts"&gt;auth-guard.service.spec.ts&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;Here are the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Line 6: Declare a &lt;code&gt;MockStore&lt;/code&gt; using the same type assertion that is used when declaring the Store in the AuthGuard (&lt;code&gt;fromAuth.State&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Line 7: Create an initial state conforming to the same state interface that was asserted on line 6. &lt;strong&gt;This will be the default state for all tests.&lt;/strong&gt; Since &lt;code&gt;fromAuth.State&lt;/code&gt; &lt;code&gt;extends&lt;/code&gt; &lt;code&gt;fromRoot.State&lt;/code&gt; and our tests only depend on the the &lt;code&gt;user&lt;/code&gt; attribute, we can cast everything else.&lt;/li&gt;
&lt;li&gt;Line 19: Provide the &lt;code&gt;MockStore&lt;/code&gt; using &lt;code&gt;provideMockStore&lt;/code&gt;, passing in the &lt;code&gt;initialState&lt;/code&gt; created in the previous step.&lt;/li&gt;
&lt;li&gt;Line 22: Inject the &lt;code&gt;Store&lt;/code&gt; inside the test.&lt;/li&gt;
&lt;li&gt;Line 31: To condition a different state, use &lt;code&gt;setState&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Testing Effect + withLatestFrom Example
&lt;/h3&gt;

&lt;p&gt;I came across &lt;a href="https://github.com/ngrx/platform/issues/414"&gt;NgRx issue #414&lt;/a&gt; which describes difficulty testing effects that incorporate state using the &lt;code&gt;withLatestFrom&lt;/code&gt; operator and the &lt;code&gt;StoreModule&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Effect()
example$ = this.actions$.pipe(
  ofType(ActionTypes.ExampleAction),
  withLatestFrom(this.store.pipe(
    select(fromExample.getShouldDispatchActionOne)
  )),
  map(([action, shouldDispatchActionOne]) =&amp;gt; {
    if (shouldDispatchActionOne) {
      return new ActionOne();
    } else {
      return new ActionTwo();
    }
  })
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The effect’s injected state couldn’t be changed after &lt;code&gt;TestBed.get(&amp;lt;effect&amp;gt;)&lt;/code&gt; had been called, making it difficult to test different values selected by &lt;code&gt;getShouldDispatchActionOne&lt;/code&gt; in the above snippet. The three common workarounds were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use Jasmine’s &lt;code&gt;SpyOn&lt;/code&gt; to mock the return value of &lt;code&gt;state.select(…)&lt;/code&gt;: &lt;code&gt;spyOn(store, 'select').and.returnValue(of(initialState))&lt;/code&gt;. However, &lt;code&gt;select&lt;/code&gt; is now an RxJs operator. ❌&lt;/li&gt;
&lt;li&gt;Move &lt;code&gt;TestBed.get(&amp;lt;effect&amp;gt;)&lt;/code&gt; from &lt;code&gt;beforeEach&lt;/code&gt; into each individual test after the state is conditioned appropriately. 😐&lt;/li&gt;
&lt;li&gt;Provide a mockStore (hey, don’t we have one of those now?). 😀&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s see how we can test effects that use &lt;code&gt;withLatestFrom&lt;/code&gt; using the MockStore:&lt;/p&gt;

&lt;p&gt;Let’s add a new effect, &lt;code&gt;addBookSuccess$&lt;/code&gt;, to the NgRx example-app’s &lt;code&gt;BookEffects&lt;/code&gt;. When a new book is successfully added, we’ll select the books the user now has in their collection the store, then display an alert with a different message depending on the quantity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Injectable()
export class BookEffects {
  @Effect({ dispatch: false })
  addBookSuccess$ = this.actions$.pipe(
    ofType(CollectionApiActionTypes.AddBookSuccess),
    withLatestFrom(this.store.select(fromBooks.getCollectionBookIds)),
    tap(([action, bookCollection]) =&amp;gt; {
      if (bookCollection.length === 1) {
        window.alert('Congrats on adding your first book!')
      } else {
        window.alert('You have added book number ' + bookCollection.length);
      }
    })
  );

  // search$ effect deleted for simplicity

  constructor(
    private actions$: Actions&amp;lt;FindBookPageActions.FindBookPageActionsUnion&amp;gt;,
    // ...
    private store: Store&amp;lt;fromBooks.State&amp;gt;
  ) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/jtcrowson/191c435185b2dbd46bd3ca6335ae67e7#file-book-effects-ts"&gt;book.effects.ts&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;We can use the &lt;code&gt;MockStore&lt;/code&gt; to condition the state, allowing us to test each of the two cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as fromBooks from '@example-app/books/reducers';
import * as fromSearch from '@example-app/books/reducers/search.reducer';
import * as fromChildBooks from '@example-app/books/reducers/books.reducer';
// Omitting autoimports
describe('BookEffects', () =&amp;gt; {
  let effects: BookEffects;
  let actions$: Observable&amp;lt;any&amp;gt;;
  let store: MockStore&amp;lt;fromBooks.State&amp;gt;;
  const initialState = {
    books: {
      search: {} as fromSearch.State,
      books: {} as fromChildBooks.State,
      collection: {
        loaded: true,
        loading: false,
        ids: ['1']
      }
    }
  } as fromBooks.State;

  beforeEach(() =&amp;gt; {
    TestBed.configureTestingModule({
      providers: [
        BookEffects,
        {
          provide: GoogleBooksService,
          useValue: { searchBooks: jest.fn() },
        },
        provideMockActions(() =&amp;gt; actions$),
        provideMockStore({ initialState }),
      ],
    });

    effects = TestBed.get(BookEffects);
    actions$ = TestBed.get(Actions);
    store = TestBed.get(Store);
    spyOn(window, 'alert');
  });

  describe('addBookSuccess$', () =&amp;gt; {
    it('should print congratulatory message when adding '
       + 'the first book', (done: any) =&amp;gt; {
      const action = new AddBookSuccess(generateMockBook());
      actions$ = of(action);

      effects.addBookSuccess$.subscribe(() =&amp;gt; {
        expect(window.alert)
          .toHaveBeenCalledWith(
            'Congrats on adding your first book!'
          );
        done();
      });
    });

    it('should print number of books after adding '
       + 'the first book', (done: any) =&amp;gt; {
      store.setState({
        ...initialState,
        books: {
          search: {} as fromSearch.State,
          books: {} as fromChildBooks.State,
          collection: {
            loaded: true,
            loading: false,
            ids: ['1', '2']
          }
        }
      });

      const action = new AddBookSuccess(generateMockBook());
      actions$ = of(action);

      effects.addBookSuccess$.subscribe(() =&amp;gt; {
        expect(window.alert)
          .toHaveBeenCalledWith(
            'You have added book number 2'
          );
        done();
      });
    });
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/jtcrowson/34c745d736c02eaa82f9e9e0d32c4fde#file-book-effects-spec-ts"&gt;book.effects.spec.ts&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;Here are the steps, similar to those in the &lt;code&gt;AuthGuard&lt;/code&gt; Example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Line 9: Declare a &lt;code&gt;MockStore&lt;/code&gt; using the same type assertion that is used when declaring the Store in the BookEffects (&lt;code&gt;fromBooks.State&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Line 10: Create an initial state conforming to the same state interface that was asserted on line 9. &lt;strong&gt;This will be the default state for all tests.&lt;/strong&gt; Since &lt;code&gt;fromBooks.State&lt;/code&gt; &lt;code&gt;extends&lt;/code&gt; &lt;code&gt;fromRoot.State&lt;/code&gt; and our tests only depend on the the ids attribute, we can cast everything else.&lt;/li&gt;
&lt;li&gt;Line 32: Provide the &lt;code&gt;MockStore&lt;/code&gt; using &lt;code&gt;provideMockStore&lt;/code&gt;, passing in the &lt;code&gt;initialState&lt;/code&gt; created in the previous step.&lt;/li&gt;
&lt;li&gt;Line 38: Inject the &lt;code&gt;Store&lt;/code&gt; inside the test.&lt;/li&gt;
&lt;li&gt;Line 59: To condition a different state, use &lt;code&gt;setState&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Thanks for reading! You can follow me on Twitter &lt;a href="https://twitter.com/john_crowson"&gt;@john_crowson&lt;/a&gt; :)&lt;/p&gt;

&lt;p&gt;For more Angular goodness, be sure to check out the latest episode of &lt;a href="https://www.spreaker.com/show/angular-show"&gt;The Angular Show podcast&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ngrx</category>
      <category>angular</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Consistent Console Logs in Angular</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Fri, 09 Jul 2021 15:22:08 +0000</pubDate>
      <link>https://dev.to/ngconf/consistent-console-logs-in-angular-3jkj</link>
      <guid>https://dev.to/ngconf/consistent-console-logs-in-angular-3jkj</guid>
      <description>&lt;p&gt;Jared Youtsey | ng-conf | Apr 2019&lt;/p&gt;

&lt;p&gt;When you have to log, do it consistently.&lt;/p&gt;

&lt;p&gt;Logging is necessary. It allows us to debug in both development and production. But &lt;code&gt;console&lt;/code&gt; is disallowed by tslint by default. And for good reason. Console logging is a mess most of the time. If you can just willy-nilly &lt;code&gt;console.log(whatever)&lt;/code&gt; then your logs are pretty much useless.&lt;/p&gt;

&lt;p&gt;We can end up with too much logging in production, which can slow our application down, and not enough in development where we need more details.&lt;/p&gt;

&lt;p&gt;I’ve had to deal with this issue on multiple projects and have written a static logger class in Angular that allows us to control what we log and where.&lt;/p&gt;

&lt;p&gt;Here is the gist &lt;a href="https://gist.github.com/jkyoutsey/e99336d58c2c83bc0ba03cde78fcc64e" rel="noopener noreferrer"&gt;https://gist.github.com/jkyoutsey/e99336d58c2c83bc0ba03cde78fcc64e&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a nutshell you have the following options:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Logger.(debug|info|warn|error|devOnly|techDebt)(module: string, method: string, message?: any)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;debug|info|warn|error&lt;/code&gt; will log in all environments unless you also set the optional &lt;code&gt;devOnly: boolean&lt;/code&gt; argument to &lt;code&gt;true&lt;/code&gt;. Then the &lt;code&gt;module&lt;/code&gt; and &lt;code&gt;method&lt;/code&gt; will still log, but not the &lt;code&gt;message&lt;/code&gt; argument. This allows for tracing without leaking sensitive data in a production environment.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;devOnly|techDebt&lt;/code&gt; do not have the optional &lt;code&gt;devOnly&lt;/code&gt; argument and will only ever log to the console in a non-production environment.&lt;/p&gt;

&lt;p&gt;By environment I mean your &lt;code&gt;src/environments/environment.ts&lt;/code&gt;’s &lt;code&gt;production&lt;/code&gt; property value. If it’s false you’ll get all log statements. If it’s true you’ll only get &lt;code&gt;debug|info|warn|error&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your output will now be consistently formatted, making it easier to read, parse, or even analyze.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyu5it59rne1m9b328sc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyu5it59rne1m9b328sc.png" alt="Image for post" width="696" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Sample Logger Usage
&lt;/h6&gt;

&lt;p&gt;The above commands result in the following output in Chrome DevTools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsh8lakgt455xrwrpr70g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsh8lakgt455xrwrpr70g.png" alt="Image for post" width="474" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Readable Console Output
&lt;/h6&gt;

&lt;p&gt;I’ve even created a VisualStudio Code snippet to make it easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Log All The Things": {
    "prefix": "ll",
    "body": [
        "Logger.${LEVEL}('${CLASS}', '${METHOD}', `${message}`);"
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/jkyoutsey/43c5570815c1c3eba2868e50cf8ae7c5#file-logger-ts-vscode-snippet-txt" rel="noopener noreferrer"&gt;logger.ts.vscode.snippet.txt&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;p&gt;And I’ve got unit tests for it so it won’t impact your coverage (but &lt;a href="https://medium.com/ngconf/angular-unit-testing-code-coverage-lies-603c6c85f801" rel="noopener noreferrer"&gt;you shouldn’t worry too much about coverage&lt;/a&gt;): &lt;a href="https://gist.github.com/jkyoutsey/01e3e2db4ba9a570245bd63d543960e1" rel="noopener noreferrer"&gt;https://gist.github.com/jkyoutsey/01e3e2db4ba9a570245bd63d543960e1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find this useful or interesting, please clap!&lt;/p&gt;




&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/" rel="noopener noreferrer"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>angular</category>
      <category>logging</category>
      <category>console</category>
    </item>
    <item>
      <title>Editing Tabular Data in Angular</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Tue, 06 Jul 2021 18:06:13 +0000</pubDate>
      <link>https://dev.to/ngconf/editing-tabular-data-in-angular-41a4</link>
      <guid>https://dev.to/ngconf/editing-tabular-data-in-angular-41a4</guid>
      <description>&lt;p&gt;Jim Armstrong | ng-conf | May 2019&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A fun dive into everything from custom Directives to advanced &lt;em&gt;ViewChildren&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;This article targets beginning to intermediate-level Angular developers and covers a wide variety of topics that arise in production applications. While centered around the concept of editing tabular data, these techniques may be used in a variety of other Angular applications.&lt;/p&gt;

&lt;p&gt;For anyone who has read at least one of my articles, you should understand that my background is applied mathematics and scientific computing. So, this article continues the trend of exploring the use of Angular in scientific and business (analytics) applications.&lt;/p&gt;

&lt;p&gt;Working with time-series data is a fundamental concept in numerous business and engineering sectors. In this context, front-end development is largely concerned with minor transformations and display of data. Concepts such as data grids, tabular display, and visualization with charts are quite familiar to front-end devs. What is likely to be less familiar is the need to edit one or more values in a time series.&lt;/p&gt;

&lt;p&gt;Data often comes from physical instruments that have some degree of fallibility and/or manual entry that is subject to typical human error. So, at some point during your FE career, it may be necessary to develop components that facilitate both the display &lt;strong&gt;and&lt;/strong&gt; editing of tabular data. Only the latter is discussed in this article.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Project
&lt;/h4&gt;

&lt;p&gt;Before continuing, point your friendly, neighborhood browser to this Github, so that you can follow along with the project deconstruction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/theAlgorithmist/Angular-Table-Editing"&gt;theAlgorithmist/Angular-Table-Editing&lt;/a&gt; on github.com&lt;/p&gt;

&lt;p&gt;Techniques covered in the remainder of the article include&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using Angular Material from a feature module&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Custom Directives (including @HostListener and @HostBinding)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;@ViewChild vs @ViewChildren and subscribing to changes on the latter&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate while typing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Custom Events&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is organized into a few simple folders,&lt;/p&gt;

&lt;p&gt;— &lt;em&gt;src/app&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;— — &lt;em&gt;features&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;— — — &lt;em&gt;table-edit&lt;/em&gt; (table edit component, custom directive, and feature module&lt;/p&gt;

&lt;p&gt;— — libs (because we always need some custom libraries — otherwise, I would be out of business :)&lt;/p&gt;

&lt;p&gt;— — &lt;em&gt;models&lt;/em&gt; (all data models)&lt;/p&gt;

&lt;p&gt;— — &lt;em&gt;services&lt;/em&gt; (because data has to come from somewhere)&lt;/p&gt;

&lt;p&gt;The data used in this sample project comes from an actual, historical dataset on used-car sales from the book, “Machine Learning in R” by Lantz. For tutorial purposes, suppose that all data in the table comes from reliable sources except mileage, which is hand-entered in another application. The code provided with this article simulates a use-case where someone with edit and/or approval authority visually examines a series of data to search for outliers. That data is displayed in a table which contains an &lt;em&gt;Input&lt;/em&gt; field in one column to support editing that particular item. To make the demo more realistic, the original data was hand-edited to insert a number of outliers.&lt;/p&gt;

&lt;p&gt;And, it would not be a project if we did not have some requirements! Every one of the following requirements was taken from an actual client application I’ve worked on in the past.&lt;/p&gt;

&lt;p&gt;1 — Display the data in a table with headers and data returned from a service.&lt;/p&gt;

&lt;p&gt;2 — One and only one column is editable, the car mileage. This is hardcoded into the application and will not change.&lt;/p&gt;

&lt;p&gt;3 — The table should be paged. The number of initial rows and allowable rows for padding will be provided. Allow sorting by date of manufacture as older cars should generally have more mileage.&lt;/p&gt;

&lt;p&gt;4 — A user may tab between rows, but indication of an edited value is via pressing ‘Return’. I’ve also been required to add a small button to the side of the input in actual projects, but that’s not required for this demo.&lt;/p&gt;

&lt;p&gt;5 — User inputs are validated while typing. Only numerical, integer inputs (with no minus sign) are allowed. If the user enters an incorrect character, reset the input field value to its value when the user first focused on the field (or the most recently edited and valid value).&lt;/p&gt;

&lt;p&gt;6 — Inputs fields have a small, grey border by default (color to be provided and not changeable). When the user successfully edits a mileage value, replace the border with a green color (to be provided and not changeable).&lt;/p&gt;

&lt;p&gt;7 — Whenever the user navigates to a new page, the input borders should be reset to the default value.&lt;/p&gt;

&lt;p&gt;8 — Whenever a user clicks on a row, whether they edit a value or not, record that click and store the number of clicks on each car id to be returned to the server. I actually had a client who wanted to do this to capture ‘interest’ in a particular row of data, i.e. they believed the click was indicative of interest in the data whether the user actually edited the data or not. Okay, well, as long as the money’s there … I don’t care :)&lt;/p&gt;

&lt;p&gt;9 — Capture whenever the user moves from one page to another so that we can potentially take action in the future. Yes, folks, that’s a common one … people want to do something, but they won’t know what it is until well into the future.&lt;/p&gt;

&lt;p&gt;10 — Add a ‘Save’ button. Clicking on this button will send a record of all edited data to the server. For tutorial purposes, the button will be implemented, but the handler only logs the edited data to the console.&lt;/p&gt;

&lt;p&gt;In an actual application, a person with &lt;em&gt;edit&lt;/em&gt; authority would perform the data editing and then after saving the data, a person with approval authority would be responsible for viewing all data and approving the modifications. This article is only concerned with the edit portion of the process.&lt;/p&gt;

&lt;h4&gt;
  
  
  Material Table
&lt;/h4&gt;

&lt;p&gt;Enough has been written on the use of &lt;em&gt;Material&lt;/em&gt; and &lt;em&gt;Material Table&lt;/em&gt; in particular, that there is little benefit from adding a lot of explanation in this article. Suffice to say that I personally prefer using &lt;em&gt;ngContainer&lt;/em&gt; to create templates for each column. The most important column in the layout provided below is &lt;em&gt;mileage&lt;/em&gt;, and there is a &lt;em&gt;Material Input&lt;/em&gt; field that allows editing of the mileage values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="mat-elevation-z8"&amp;gt;

  &amp;lt;table mat-table matSort [dataSource]="dataSource"&amp;gt;

    &amp;lt;tr mat-header-row *matHeaderRowDef="displayOrder"&amp;gt;&amp;lt;/tr&amp;gt;

    &amp;lt;tr mat-row *matRowDef="let row; columns: displayOrder" (click)="onTouched(row)"&amp;gt;&amp;lt;/tr&amp;gt;

    &amp;lt;ng-container matColumnDef="year"&amp;gt;
      &amp;lt;th mat-header-cell *matHeaderCellDef mat-sort-header="year"&amp;gt; Year &amp;lt;/th&amp;gt;
      &amp;lt;td mat-cell *matCellDef="let element"&amp;gt; {{element.year}} &amp;lt;/td&amp;gt;
    &amp;lt;/ng-container&amp;gt;

    &amp;lt;ng-container matColumnDef="model"&amp;gt;
      &amp;lt;th mat-header-cell *matHeaderCellDef&amp;gt; Model &amp;lt;/th&amp;gt;
      &amp;lt;td mat-cell *matCellDef="let element"&amp;gt; {{element.model}} &amp;lt;/td&amp;gt;
    &amp;lt;/ng-container&amp;gt;

    &amp;lt;ng-container matColumnDef="price"&amp;gt;
      &amp;lt;th mat-header-cell *matHeaderCellDef&amp;gt; Price &amp;lt;/th&amp;gt;
      &amp;lt;td mat-cell *matCellDef="let element"&amp;gt; {{element.price}} &amp;lt;/td&amp;gt;
    &amp;lt;/ng-container&amp;gt;

    &amp;lt;ng-container matColumnDef="mileage"&amp;gt;
      &amp;lt;th mat-header-cell *matHeaderCellDef&amp;gt; Mileage &amp;lt;/th&amp;gt;
      &amp;lt;td mat-cell *matCellDef="let element"&amp;gt;
        &amp;lt;mat-form-field&amp;gt;
          &amp;lt;input matInput class="bordered editable" type="text" min="0" max="1000000" value="{{element.mileage}}" id="{{element.carid}}"
                 (keyup)="__checkNumber($event)" (inputChanged)="onEdited($event)" &amp;gt;
          &amp;lt;mat-hint&amp;gt;&amp;lt;strong&amp;gt;Mileage&amp;lt;/strong&amp;gt;&amp;lt;/mat-hint&amp;gt;
        &amp;lt;/mat-form-field&amp;gt;
      &amp;lt;/td&amp;gt;
    &amp;lt;/ng-container&amp;gt;

    &amp;lt;ng-container matColumnDef="color"&amp;gt;
      &amp;lt;th mat-header-cell *matHeaderCellDef&amp;gt; Color &amp;lt;/th&amp;gt;
      &amp;lt;td mat-cell *matCellDef="let element"&amp;gt; {{element.color}} &amp;lt;/td&amp;gt;
    &amp;lt;/ng-container&amp;gt;

    &amp;lt;ng-container matColumnDef="transmission"&amp;gt;
      &amp;lt;th mat-header-cell *matHeaderCellDef&amp;gt; Transmission &amp;lt;/th&amp;gt;
      &amp;lt;td mat-cell *matCellDef="let element"&amp;gt; {{element.transmission}} &amp;lt;/td&amp;gt;
    &amp;lt;/ng-container&amp;gt;

  &amp;lt;/table&amp;gt;

  &amp;lt;!-- options should always be Fibonacci :) --&amp;gt;
  &amp;lt;mat-paginator [length]="150" [pageSize]="5" [pageSizeOptions]="[5, 8, 13]" showFirstLastButtons (page)="onPage($event)"&amp;gt;&amp;lt;/mat-paginator&amp;gt;

  &amp;lt;div align="right"&amp;gt;
    &amp;lt;button mat-button color="primary" (click)="onSave()"&amp;gt;Save&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/theAlgorithmist/441519c3e4e018094b48906f4896247d#file-table-edit-component-html"&gt;table-edit.component.html&lt;/a&gt; hosted on GitHub
&lt;/h6&gt;

&lt;p&gt;Note the inclusion of the &lt;em&gt;Material&lt;/em&gt; paginator near the end of the layout.&lt;/p&gt;

&lt;p&gt;The necessary &lt;em&gt;Material&lt;/em&gt; modules are separated into a feature module as shown in the file&lt;/p&gt;

&lt;p&gt;/src/app/features/material.module.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NgModule } from '@angular/core';

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import {
  MatTableModule,
  MatPaginatorModule,
  MatInputModule,
  MatSortModule,
  MatButtonModule
} from '@angular/material';

const PLATFORM_IMPORTS: Array&amp;lt;any&amp;gt; = [BrowserAnimationsModule];

const MATERIAL_IMPORTS: Array&amp;lt;any&amp;gt; = [MatTableModule, MatPaginatorModule, MatInputModule, MatSortModule, MatButtonModule];

@NgModule({
  imports: [PLATFORM_IMPORTS, MATERIAL_IMPORTS],

  exports: MATERIAL_IMPORTS,

  declarations: []
})
export class MaterialModule { }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which is imported into the table edit module&lt;/p&gt;

&lt;p&gt;/src/app/features/table-edit/table-edit.module.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NgModule     } from '@angular/core';
import { CommonModule } from '@angular/common';

import { MaterialModule } from '../material.module';

import { TableEditComponent     } from '../table-edit/table-edit/table-edit.component';
import { InputSelectorDirective } from './directives/input-selector.directive';

export const TABLE_COMPONENTS: Array&amp;lt;any&amp;gt; = [TableEditComponent, InputSelectorDirective];

@NgModule({
  imports: [MaterialModule, CommonModule],

  exports: TABLE_COMPONENTS,

  declarations: TABLE_COMPONENTS
})
export class TableEditModule { }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the table-edit functionality to be easily imported into any project, including ours in &lt;em&gt;/src/app/app.module.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { BrowserModule    } from '@angular/platform-browser';
import { NgModule         } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

// feature module
import { TableEditModule  } from './features/table-edit/table-edit.module';

// app-level components
import { AppComponent } from './app.component';

const APP_DECLARATIONS: Array&amp;lt;any&amp;gt; = [AppComponent];

@NgModule({
  declarations: APP_DECLARATIONS,
  imports: [
    BrowserModule, HttpClientModule, TableEditModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Data Models
&lt;/h4&gt;

&lt;p&gt;All data models (interfaces) for the application are in the &lt;em&gt;/src/app/models/models.ts&lt;/em&gt; file. A single record of car data is modeled as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface ICarData
{
  carid: number;
  year: number,
  model: string,
  price: number
  mileage: number;
  color: string;
  transmission: TransmissionEnum;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the entire model (including headers) is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface ICarDataModel
{
  header: Array&amp;lt;string&amp;gt;;

  data: Array&amp;lt;ICarData&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the user edits car mileage, it is necessary to record the &lt;em&gt;id&lt;/em&gt; of the edited vehicle and the new mileage value, which are stored in an &lt;em&gt;IEditedData&lt;/em&gt; instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface IEditedData
{
  id: number;

  value: number;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Main App Component
&lt;/h4&gt;

&lt;p&gt;The main app component, &lt;em&gt;/src/app/app.component.ts&lt;/em&gt; simply loads a car data model from a JSON file and then separates the header and car data into two bound variables in the __&lt;em&gt;onModelLoaded&lt;/em&gt; method,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected __onModelLoaded(result: ICarDataModel): void
{
  // this handler could be used to check the integrity of returned data
  this.header = result.header.slice();

  // assign a copy of the returned model to the bound data
  this.data = result.data.map( (car: ICarData): ICarData =&amp;gt; {return JSON.parse(JSON.stringify(car))} );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this point, the remainder of the application is handled by the table edit component.&lt;/p&gt;

&lt;h4&gt;
  
  
  Table Edit Component
&lt;/h4&gt;

&lt;p&gt;The table edit component (&lt;em&gt;/src/app/features/table-edit/table-edit/table-edit.component.ts&lt;/em&gt;) employs an &lt;em&gt;InputSelectorDirective&lt;/em&gt; to select individual Input fields. This is accomplished by using a class selector in the &lt;em&gt;Directive&lt;/em&gt;,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Directive({
  selector: '.editable'
})
export class InputSelectorDirective implements OnInit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then applying that class in the &lt;em&gt;Input&lt;/em&gt; field in the template,&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/src/app/features/table-edit/table-edit/table-edit.component.html&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;input matInput class="bordered editable" type="text" min="0" max="1000000" value="{{element.mileage}}" id="{{element.carid}}"
       (keyup)="__checkNumber($event)" (inputChanged)="onEdited($event)" &amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;em&gt;ViewChild&lt;/em&gt; of this &lt;em&gt;Directive&lt;/em&gt; provides a direct reference to a single instance of that &lt;em&gt;Directive&lt;/em&gt;, applied to an &lt;em&gt;Input&lt;/em&gt; field with the class ‘editable.’ This application, however, requires references to &lt;strong&gt;all&lt;/strong&gt; such input fields in the current table page. This is where &lt;em&gt;ViewChildren&lt;/em&gt; and &lt;em&gt;QueryList&lt;/em&gt; are used.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/src/app/features/table-edit/table-edit/table-edit.component.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ViewChildren(InputSelectorDirective)
protected _inputs: QueryList&amp;lt;InputSelectorDirective&amp;gt;;   // reference to QueryList returned by Angular
protected _inputsArr: Array&amp;lt;InputSelectorDirective&amp;gt;;    // Array of Directive references
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;QueryList&lt;/em&gt; provides a reference to the &lt;em&gt;InputSelectorDirective&lt;/em&gt; for all Input fields in the current page.&lt;/p&gt;

&lt;p&gt;Two Typescript &lt;em&gt;Records&lt;/em&gt; are used to store edited data and record ‘row touches’,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected _edited: Record&amp;lt;string, number&amp;gt;;
protected _touches: Record&amp;lt;string, number&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some programmatic support is required to interface with the &lt;em&gt;Material&lt;/em&gt; table, specifically a data source, reference to the &lt;em&gt;MatPaginator&lt;/em&gt; (paginator), and &lt;em&gt;MatSort&lt;/em&gt; (sorting). This is accomplished with two &lt;em&gt;ViewChild&lt;/em&gt; instances and a public variable (for binding)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ViewChild(MatPaginator)
protected _paginator: MatPaginator;

@ViewChild(MatSort)
protected _sort: MatSort;

// (Material) Datasource for the table display
public dataSource: MatTableDataSource&amp;lt;ICarData&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That concludes the basic setup for this component. In terms of logic, a summary of relevant class methods follows to aid in your deconstruction of the application.&lt;/p&gt;

&lt;p&gt;Method: &lt;em&gt;onEdited(evt: IEditedData): void&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This method is called whenever the mileage data is edited. It first checks the argument and event id and then stores the edited data in the class edited-data &lt;em&gt;Record&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Method: &lt;em&gt;onTouched(row: ICarData): void&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This method is called whenever a user clicks on a table row, which is taken as an indication of interest in that data, whether it is edited or not. Yes, I’ve actually had to implement this for a client in a real application. As long as the check clears the bank, it works for me :)&lt;/p&gt;

&lt;p&gt;Method: &lt;em&gt;onSave(): void&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is a placeholder for you to implement a service call to store the edited data should you wish to modify the code for use in a production environment. The edited data is logged to the console to help visualize formatting of the edited-data Record.&lt;/p&gt;

&lt;p&gt;Method: &lt;em&gt;onPage(evt: PageEvent): void&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is another placeholder method in case you want to modify the application to perform some function whenever the user pages to another set of table data.&lt;/p&gt;

&lt;p&gt;Method: __&lt;em&gt;checkNumber(evt: any): boolean&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This method is called to validate a number while typing. It defers the validation to the library method, &lt;em&gt;Validation.checkNumber()&lt;/em&gt;, which is useful for numeric entry of physical properties that must be greater than or equal to zero.&lt;/p&gt;

&lt;p&gt;Method: __&lt;em&gt;onInputsChanged(): void&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This method is executed whenever the &lt;em&gt;QueryList&lt;/em&gt; of &lt;em&gt;Input&lt;/em&gt; fields changes (i.e. on page change). The method’s primary action is to reset the border color on all new fields. Modify for additional functionality as you see fit.&lt;/p&gt;

&lt;p&gt;Since the &lt;em&gt;QueryList&lt;/em&gt; of &lt;em&gt;InputSelectorDirective instances&lt;/em&gt; changes every time the user navigates to a new page of the table, it is necessary to subscribe to changes in that list. The subscription is made in the &lt;em&gt;ngAfterViewInit&lt;/em&gt; lifecycle method,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public ngAfterViewInit(): void
{
  // subscribe to changes in the query list
  this._inputs.changes.subscribe( () =&amp;gt; this.__onInputsChanged() );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and here is the handler,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected __onInputsChanged(): void
{
  // input query list changed (which happens on profile selection)
  this._inputsArr = this._inputs.toArray();

  // set default border color on everything
  if (this._inputsArr &amp;amp;&amp;amp; this._inputsArr.length &amp;gt; 0) {
    this._inputsArr.forEach( (input: InputSelectorDirective): void =&amp;gt; {input.borderColor = '#cccccc'});
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The use of this method and &lt;em&gt;onPage()&lt;/em&gt; provides a natural separation of the primary focus on &lt;em&gt;Input&lt;/em&gt; field changes with any other activities that may be requested on page change. The result is better focus on single responsibility between methods.&lt;/p&gt;

&lt;h4&gt;
  
  
  Input Selector Directive
&lt;/h4&gt;

&lt;p&gt;This &lt;em&gt;Directive&lt;/em&gt; provides a collection of &lt;em&gt;Output&lt;/em&gt; and event handlers to facilitate editing the mileage data in the table.&lt;/p&gt;

&lt;p&gt;The single &lt;em&gt;Output&lt;/em&gt; is ‘inputChanged’ and is emitted whenever a mileage value is changed,&lt;/p&gt;

&lt;p&gt;/src/app/features/table-edit/directives/input-selector.directive.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Output('inputChanged')
protected _changed: EventEmitter&amp;lt;IEditedData&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single &lt;em&gt;HostBinding&lt;/em&gt; to the &lt;em&gt;border-color&lt;/em&gt; style facilitates changing the border color of each &lt;em&gt;Input&lt;/em&gt; field based on whether that element is initially displayed or in an edited state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@HostBinding('style.border-color')
public borderColor: string = '#cccccc';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two host listeners, one for the ‘focus’ event and the other for ‘keyup.’ When an &lt;em&gt;Input&lt;/em&gt; field receives focus, it is necessary to capture the current value and the id associated with that mileage value. The former is used to re-populate the field with the initial value in the event a typing error is detected. The &lt;em&gt;id&lt;/em&gt; must be emitted along with the edited value in order to associate the edited value with a specific record of car data.&lt;/p&gt;

&lt;p&gt;The ‘keyup’ listener performs basic validation on the current numerical input for the mileage value. A valid value on clicking ‘Return’ causes the &lt;em&gt;Input&lt;/em&gt; field to be colored green. Input errors while typing cause the field to be repopulated with the last-known-good value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@HostListener('keyup', ['$event']) onKeyUp(evt: KeyboardEvent): boolean
{
  // test for singleton leading negative sign as first character
  const v: string = this._input.value;
  const n: number = v.length;

  // for now, allow a blank field as it is possible that the entire number could be deleted by backspace before
  // entering a new number
  if (n == 0) {
    return true;
  }

  // physical quantities may not be negative and a decimal is currently not allowed
  if ( (n == 1 &amp;amp;&amp;amp; v == "-") || (evt.key == ".") )
  {
    this.hasError     = true;
    this._input.value = this._currentValue.toString();

    return true;
  }

  // check for most recent keystroke being an enter, which is currently the only way to indicate an edit
  const code: string = evt.code.toLowerCase();
  if (code == 'enter' || code == 'return')
  {
    if (!isNaN(+v) &amp;amp;&amp;amp; isFinite(+v))
    {
      this.hasError      = false;
      this._currentValue = +v;

      // set 'edited' border color and emit the changed event
      this.borderColor = '#66CD00';

      this._changed.emit({id: this._currentID, value: +v});
    }
    else
    {
      this.hasError     = true;
      this._input.value = this._currentValue.toString();
    }

    return true;
  }

  this.hasError = !Validation.checkNumber(evt);

  if (this.hasError)
  {
    console.log( "error: ", this._currentValue );
    // indicate an error by replacing the bad input with the 'current' or last-known good value
    // this may be altered in a future release
    this._input.value = this._currentValue.toString();
  }

  return true;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  &lt;a href="https://gist.github.com/theAlgorithmist/a2ce0b6da2e43cc2f6f63befc5710eae#file-input-selector-directive-ts"&gt;input-selector.directive.ts&lt;/a&gt; hosted by GitHub
&lt;/h6&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;This has been a long and somewhat involved deconstruction. Scientific, engineering, and business-analytic applications often expose a much higher degree of interactivity to FE devs. I hope this article and the supporting code has helped beginning- and intermediate-level Angular developers with their understanding of the platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>dataengineering</category>
    </item>
    <item>
      <title>How To Analyze An Angular Project with Fortify</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Fri, 02 Jul 2021 18:15:25 +0000</pubDate>
      <link>https://dev.to/ngconf/how-to-analyze-an-angular-project-with-fortify-igi</link>
      <guid>https://dev.to/ngconf/how-to-analyze-an-angular-project-with-fortify-igi</guid>
      <description>&lt;p&gt;Rogelio Flores Zubillaga | ng-conf | May 2019&lt;/p&gt;

&lt;h5&gt;
  
  
  Learn to run static code analysis on your Angular Typescript project.
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-jGfnM01VvfgwNTs1VEFOA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-jGfnM01VvfgwNTs1VEFOA.png" alt="image of the Angular and Fortify logos."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Angular + Fortify for the win
&lt;/h6&gt;

&lt;p&gt;Recently, I started a small Angular application that acts as an installer for a distributed API Gateway application. As part of our testing and quality engineering, we always inspect our web applications. However, we hadn’t done much with static code analysis. It was mostly security dynamic analysis over our client and server communication. Fortify is a product that we have used for this since the company that I work for owns it, and recently they added support for Typescript in their static code analysis. So this was a great opportunity to use it on our Angular project.&lt;/p&gt;

&lt;h3&gt;
  
  
  About Fortify
&lt;/h3&gt;

&lt;p&gt;Fortify is a product of Micro Focus that allows security scans of applications. Many people are familiar with “WebInspect”, which some people use as a synonym for Fortify.&lt;/p&gt;

&lt;p&gt;Think of Fortify as big happy family where there are several siblings. Each sibling is a product or program you can run. “Fortify WebInspect” provides dynamic analysis of web applications and services. This is like the first-born son that makes their parents proud. You always want to show others that you run his security scans. Some of your customers might even require that you do this. It helps you prove that your software is secure.&lt;/p&gt;

&lt;p&gt;Fortify Static Code Analyzer (SCA) identifies security vulnerabilities in the source code. Think of it as the sibling everyone dislikes. Like &lt;a href="https://polarexpress.fandom.com/wiki/Know-It-All" rel="noopener noreferrer"&gt;the know-it-all boy in the Polar Express&lt;/a&gt;. Nobody likes him because it will usually tell you things you don’t like to hear. Such as “your code sucks”, or “your code is insecure”. So you try to avoid him.&lt;/p&gt;

&lt;p&gt;Fear no more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F640%2F1%2AN2RNB-mk0zmCFoi352v6yw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F640%2F1%2AN2RNB-mk0zmCFoi352v6yw.jpeg" alt="Image of the annoying blonde boy with glasses from the Polar Express looking over the top of the train seat."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  There is one in every family
&lt;/h6&gt;

&lt;p&gt;In this article, I will focus only on Fortify SCA. Yes, the annoying kid. Fortify SCA is best used during the software development phase. Thus, the target audience of this article are software engineers. Whether involved in the development, or the testing and quality of web applications.&lt;/p&gt;

&lt;p&gt;Most Angular applications use Typescript. And Angular is one of the most used web frameworks nowadays, so let’s explore how to use Fortify with Angular. Our method will apply to any project that uses Typescript and Javascript though.&lt;/p&gt;

&lt;h3&gt;
  
  
  Obtaining and Installing Fortify
&lt;/h3&gt;

&lt;p&gt;We’re going to talk about the on-premise client of Fortify SCA. There is Fortify On Demand, which is the SaaS offering (more on that later). If you don’t have Fortify yet, &lt;a href="https://www.microfocus.com/en-us/products/static-code-analysis-sast/overview" rel="noopener noreferrer"&gt;you can get it here&lt;/a&gt;. There is the option to get a free trial, which comes with some limitations. I suggest you download Fortify SCA &lt;strong&gt;and&lt;/strong&gt; “Applications”, which means you will get the Source Analyzer (the scanner), the Scan Wizard, the Report Generator, Audit Wizard, and others. We will talk at least about these four. Once you have downloaded the software, you go through these steps to install them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;installbuilder&lt;/code&gt;, found in the compressed file you downloaded. Hit &lt;code&gt;Next&lt;/code&gt; (after each of the following steps as well).&lt;/li&gt;
&lt;li&gt;Accept the license agreement&lt;/li&gt;
&lt;li&gt;Accept default installation directory or provide your own&lt;/li&gt;
&lt;li&gt;Specify where your license file &lt;code&gt;fortify.license&lt;/code&gt; is&lt;/li&gt;
&lt;li&gt;(Optionally) provide server settings for security content updates. I left the default Update server URL and didn’t need to provide a proxy host/port.&lt;/li&gt;
&lt;li&gt;Answer if you want to migrate from a previous SCA installation (I didn’t have one, so I said no)&lt;/li&gt;
&lt;li&gt;Select if you want to install sample source code projects&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the end of the installation, you will see a screen like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F608%2F1%2ANrSNxNH_LpIkze4gjKS06Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F608%2F1%2ANrSNxNH_LpIkze4gjKS06Q.png" alt="Screenshot of an Apple Setup popup window. The pop up reads "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Last screen of the Fortify SCA installer
&lt;/h6&gt;

&lt;p&gt;When the installation completes, you will see a checkbox that reads “update security content after installation”. If you leave it selected (default), a quick update will run. When it’s done, a few seconds later, a new dialog appears with the updates, which you can dismiss with an OK button. You are now ready to start using it to scan your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating A Script To Scan (Analyze) Your Code
&lt;/h3&gt;

&lt;p&gt;I know of at least three ways you can run a static code analysis with Fortify. One is to simply run &lt;code&gt;sourceanalyzer&lt;/code&gt; from the command line. A second way is using the Scan Wizard to help you create a script that runs the scan. And the third way is to use the Audit Workbench to run your scan, which is probably the easiest one. The last two methods eventually run &lt;code&gt;sourceanalyzer&lt;/code&gt;. Unfortunately, if we’re talking about an Angular project — but this applies to any project that contains Typescript files, the only way I found to scan Typescript files was to use the command line.&lt;/p&gt;

&lt;p&gt;However, since the command line needs a Build ID, I will teach you how to create a script with the Scan Wizard, which creates one. This will also teach you more about some of the options &lt;code&gt;sourceanalyzer&lt;/code&gt; by looking at how the generated script calls it.&lt;/p&gt;

&lt;p&gt;Fortify provides you with the Scan Wizard (&lt;code&gt;ScanWizard&lt;/code&gt; executable), which generates a script for your platform, based on some inputs and options. Run it, and you will see a wizard with this screen (I have already selected a Project Root):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AFPGZziqi4eERlfcULqG83Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AFPGZziqi4eERlfcULqG83Q.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Screen 1 of the Scan Wizard — Specify Project Root
&lt;/h6&gt;

&lt;p&gt;Select the &lt;code&gt;Add Project Root&lt;/code&gt; button and specify the path to your application. Then hit &lt;code&gt;Next&lt;/code&gt;. The wizard will then scan your project root and find all the source code files that it can potentially scan. It might take a few seconds. You will now see this screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2ADRI0H5A5wVXCMTnz2YxTtg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2ADRI0H5A5wVXCMTnz2YxTtg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Screen 2 of the Scan Wizard — Review Source Files
&lt;/h6&gt;

&lt;p&gt;By default, it will have all directories selected. You can deselect directories such as &lt;code&gt;node_modules&lt;/code&gt; unless you want to scan all your dependencies. By deselecting directories, the wizard will update the file count and automatically detect the languages used in those directories. You can deselect languages as well if you don’t want to scan a particular set of files. Note that Typescript doesn’t appear in the list of languages. Don’t worry, I’ll tell you later how to add Typescript files to the scan.&lt;/p&gt;

&lt;p&gt;Once you have made your selections, hitting &lt;code&gt;Next&lt;/code&gt; will take you to the Translation and Scan screen of the wizard. In this screen you select for which platform you want to generate a script. You can also select whether you want a quick scan. Note that if you select this option, your scan will be faster, but you will be sacrificing accuracy. I recommend that you use this option the first time you run a scan. That way you don’t have to wait as long to make adjustments, if needed. Once you’re satisfied with your settings, you can turn off the “quick scan”.&lt;/p&gt;

&lt;p&gt;The other options are to automatically upload the results to Fortify’s SSC (cloud-based product), or include custom rules. I will not discuss these options in this article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2A_7YH-9vAskVFuDSahKfR-w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2A_7YH-9vAskVFuDSahKfR-w.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Screen 3 of the Scan Wizard — Translation and Scan options
&lt;/h6&gt;

&lt;p&gt;After clicking on the &lt;code&gt;Next&lt;/code&gt; button, you end up with the actual script:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AtnNzqlRPYwmiId_QX0_HHQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AtnNzqlRPYwmiId_QX0_HHQ.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Screen 4 of the Scan Wizard — output script
&lt;/h6&gt;

&lt;p&gt;&lt;code&gt;Finish&lt;/code&gt; the wizard and you will find the output script on your project’s root directory. By default the script didn’t have executable rights after it gets created. To fix that, simply add executable rights like this on a UNIX-like system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x FortifySCA.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before you can execute your script, you might need to add Fortify’s &lt;code&gt;bin&lt;/code&gt; directory to your PATH environment. On Unix-like systems, you do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export PATH=$PATH:/Applications/Fortify/Fortify_SCA_and_Apps_18.20/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to Fortify’s documentation, to be able scan Typescript, we need to change the default configuration. We need to enable “higher order ” analysis and languages, and specify javascript/typescript. These are the properties I added to my properties file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.fortify.sca.hoa.Enable=true
com.fortify.sca.Phase0HigherOrder.Languages=javascript,typescript
com.fortify.sca.EnableDOMModeling=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The third property above is recommended for DOM-related vulnerabilities in the documentation. You can specify these properties in three ways, in order of the priority they will be used:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using the &lt;code&gt;-D&lt;/code&gt; option on the command-line&lt;/li&gt;
&lt;li&gt;Specifying them in the &lt;code&gt;{Fortify Installed Dir}/Core/config/fortify-sca-quickscan.properties&lt;/code&gt; file, but only if you specify the&lt;code&gt;-quick&lt;/code&gt; option to run a “quick” scan.&lt;/li&gt;
&lt;li&gt;Specifying them in the &lt;code&gt;Core/config/fortify-sca.properties&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;There is also a &lt;code&gt;Core/config/fortify.properties&lt;/code&gt; which has more higher-level properties that users seldom need to change. You could also put your properties here.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that if you add your properties to any of these files, they will affect every scan on that system.&lt;/p&gt;

&lt;p&gt;So, the full command on the CLI to run your scan could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./FortifySCA.sh -Dcom.fortify.sca.EnableDOMModeling=true -
Dcom.fortify.hoa.Enable=true -
Dcom.fortify.sca.Phase0HigherOrder.Languages=javascript,typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, running this command didn’t include Typescript files in the scan. To include them, I had to explicitly tell the analyzer to scan those files. I also couldn’t use the script just generated to include Typescript files in the scan. I had to use &lt;code&gt;sourceanalyzer&lt;/code&gt;. But you could simply reference the same Build ID that your script generated (look for &lt;code&gt;BUILDID=&lt;/code&gt; in your script).&lt;/p&gt;

&lt;p&gt;Finally, this is how you can run an analysis on your Angular project which will include your Typescript files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sourceanalyzer -b &amp;lt;build_id&amp;gt; clean 
sourceanalyzer -b &amp;lt;build_id&amp;gt; &amp;lt;path_to_code_root&amp;gt;/**/*.ts
sourceanalyzer -Xmx14745M -Xms400M -Xss24M -b &amp;lt;build_id&amp;gt; -quick -scan -f results.fpr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command simply cleans any previous artifacts of the scan. If this is your first time running it, you don’t need it. But you don’t want to forget to do that especially if you automate this process on a build system. You might also be able to modify the output script from the Scan Wizard to add these options.&lt;/p&gt;

&lt;p&gt;Note that on the third command above I’m specifying a limit on the memory used (the &lt;code&gt;-X**&lt;/code&gt; flags, and also providing the &lt;code&gt;-quick&lt;/code&gt; flag). This is because I ran this on my laptop, which doesn’t have enough memory to run a full scan. Remove these options once you have your final setup on a machine that has more than 16GB of memory. See the documentation links at the end of this article for system requirements.&lt;/p&gt;

&lt;p&gt;You can put these commands in a single script that can be part of your build process. You can include it in a tool like Jenkins. For instance, your scan can run when triggered by a SCM commit and/or be part of your CI pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading the Results
&lt;/h3&gt;

&lt;p&gt;To read the output of the scan, open your “Audit Project” with &lt;em&gt;Audit Workbench&lt;/em&gt;. The Audit Project is what the documentation calls the output file (which ends in &lt;code&gt;.fpr&lt;/code&gt;) of your scan. &lt;em&gt;Audit Workbench&lt;/em&gt; is one of the applications that you can download with Fortify. In it, you see all the vulnerabilities categorized by levels; Critical, High, Medium, and Low.&lt;/p&gt;

&lt;p&gt;Here is a sample screenshot. It’s from a scan of an Angular project. Note that it detected a privacy violation on a Typescript file. This issue is actually triggered from an HTML template. It categorized it as Critical, but since it’s related to a debug-only print out, we’re not too worried.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2A51P_GgKvgXAdpA6FN1BNgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2A51P_GgKvgXAdpA6FN1BNgg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Audit Workbench showing detected issues on Typescript/Angular code.
&lt;/h6&gt;

&lt;p&gt;You see summaries of each vulnerability along with details and recommendations for remediation.&lt;/p&gt;

&lt;p&gt;Scanning your application often during the development cycle will help improve quality. It also gives you trends that you can track. And you track them so that you identify and eliminate the bad ones. Changes during the development phase are cheaper than when the code is complete.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Don’t wait until you’re ready to ship to scan your application.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can also create reports and automate the process. Instead of opening the Audit Project with Audit Workbench, you can generate a report. There are two generators, &lt;code&gt;ReportGenerator&lt;/code&gt; and &lt;code&gt;BIRTReportGenerator&lt;/code&gt;. I had used the open source reporting engine BIRT before (and liked it), and it was recommended by the documentation anyway, so that’s the one we’re using.&lt;/p&gt;

&lt;p&gt;This is the command I ran to create a PDF document with a report based on OWASP Top 10 2017, following by a screenshot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BIRTReportGenerator -template "OWASP Top 10" -source results.fpr -output myreport.pdf -format PDF -showSuppressed -Version "OWASP Top 10 2017"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AIetSygMkWRGO9bZilvjOBw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AIetSygMkWRGO9bZilvjOBw.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Part of the Developer Workbook report. It shows an issue found in a Typescript file. The file is part of an Angular Component
&lt;/h6&gt;

&lt;p&gt;There are several templates to use, depending on what type of report you want. This is the full list included in the installation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developer Workbook&lt;/li&gt;
&lt;li&gt;DISA STIG&lt;/li&gt;
&lt;li&gt;CWE/SANS Top 25&lt;/li&gt;
&lt;li&gt;FISMA Compliance&lt;/li&gt;
&lt;li&gt;OWASP Mobile Top 10&lt;/li&gt;
&lt;li&gt;OWASP Top 10&lt;/li&gt;
&lt;li&gt;PCI DSS Compliance&lt;/li&gt;
&lt;li&gt;DISA CCI 2&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I have ran successfully the first two reports from the list, plus the OWASP Top 10 as shown above. To learn the meaning of the options I used, and other ones available when generating BIRT reports, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BIRTReportGenerator -help
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see that there is a &lt;code&gt;--Version&lt;/code&gt; option for some of the report templates. These target specific versions of specifications that you might be interested in being compliant.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;Fortify also has a SaaS option. It’s called Fortify on Demand (FoD). If you’re using it, upload your source code, and wait for the results.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note that the free trial version of Fortify on Demand does not support Typescript&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is also a plugin for the most popular IDEs. Along with an account with FoD, you can run scans during development without leaving your IDE. I know Eclipse and IntelliJ have plugins available.&lt;/p&gt;

&lt;p&gt;There is another product called Fortify Software Security Center. It will allow you to keep scan results in a central place on the cloud. It is basically a repository of your scan results (the &lt;code&gt;.fpr&lt;/code&gt; files). It makes it easier to see trends, and make comparisons between scans.&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href="https://community.microfocus.com/t5/ratings/ratingdetailpage/message-uid/1672810/rating-system/forum_topic_metoo#userlist" rel="noopener noreferrer"&gt;product announcement&lt;/a&gt; for the latest version as of this writing (18.20). In it you’ll find information about the new features, and links to documentation and samples.&lt;/p&gt;

&lt;p&gt;Finally, I want to point out that there are free resources available to scan your Angular project, including them with &lt;code&gt;tslint&lt;/code&gt; for example. However, if your company is already licensing Fortify for WebInspect (dynamic analysis), then most likely you also have access to the static code analyzer.&lt;/p&gt;




&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/" rel="noopener noreferrer"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>angular</category>
      <category>fortify</category>
    </item>
    <item>
      <title>Upgrading an Existing Angular Application to CLI 7.3 for Conditional Polyfills</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Mon, 28 Jun 2021 19:55:36 +0000</pubDate>
      <link>https://dev.to/ngconf/upgrading-an-existing-angular-application-to-cli-7-3-for-conditional-polyfills-40af</link>
      <guid>https://dev.to/ngconf/upgrading-an-existing-angular-application-to-cli-7-3-for-conditional-polyfills-40af</guid>
      <description>&lt;p&gt;Jared Youtsey |ng-conf | May 2019&lt;/p&gt;

&lt;p&gt;Angular has allowed us to polyfill features back to browsers like IE 9, 10, and 11 for a while using the &lt;code&gt;polyfills.ts&lt;/code&gt; file. With the introduction of Angular CLI 7.3 we get conditional polyfills, where we only ship the older polyfills to pre-ES2105 browsers. This results in a savings of about 56Kb. This won’t take you from average to superhero load times, but this is an easy optimization.&lt;/p&gt;




&lt;p&gt;If you’re starting a new project, just make sure you have at least @angular/&lt;a href="mailto:cli@7.3.0"&gt;cli@7.3.0&lt;/a&gt; installed globally via npm and &lt;code&gt;ng new&lt;/code&gt; away!&lt;/p&gt;




&lt;p&gt;If you have an older project there are a few more steps. Here is the outline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upgrade global CLI to 7.3&lt;/li&gt;
&lt;li&gt;Upgrade project to CLI 7.3&lt;/li&gt;
&lt;li&gt;Delete IE polyfills from &lt;code&gt;polyfills.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add flag to &lt;code&gt;angular.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Validate it’s working&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;First, upgrade your global installation of the CLI. I recommend uninstalling the old one first for good measure.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm uninstall -g @angular/cli&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install -g @angular/cli&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;Next, upgrade your project to the latest Angular version with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng update @angular/cli @angular/core&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will have made a few changes to your &lt;code&gt;package.json&lt;/code&gt;, but you may need to make a few more.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;typescript version should be &amp;gt; 3.2.0 and &amp;lt; 3.3.0.&lt;/li&gt;
&lt;li&gt;@angular-devkit/build-angular version should be at least 0.13.6&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Next, delete the polyfills for IE 9, 10, and 11 from the &lt;code&gt;polyfills.ts&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GRLQv0ty--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2AkrLhPoiuK4lAe2FYdrsglA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GRLQv0ty--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2AkrLhPoiuK4lAe2FYdrsglA.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Now add one flag to &lt;code&gt;angular.json&lt;/code&gt; under your project in &lt;code&gt;architect/build/options&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"es5BrowserSupport": true&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;Now, let’s verify that it works.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng build&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In your project’s &lt;code&gt;dist&lt;/code&gt; folder under your project name you should find a new &lt;code&gt;es2015-polyfills.XXX.js&lt;/code&gt; file. This is the file that will be conditionally loaded if the browser requires those polyfills.&lt;/p&gt;

&lt;p&gt;How do the browsers know whether or not to load the es2015-polyfills? Open the &lt;code&gt;index.html&lt;/code&gt; from your project’s &lt;code&gt;dist&lt;/code&gt; folder and look down at the bottom. The following script tags were added by the builder to your index.html during compilation (I’ve formatted these for the purpose of this article):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CWM94ojo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2AJ9vOTh895xG2rMSgEbISMw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CWM94ojo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2AJ9vOTh895xG2rMSgEbISMw.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the &lt;code&gt;nomodule&lt;/code&gt; attribute on the es2105-polyfills line. The HTML spec for &lt;code&gt;nomodule&lt;/code&gt; says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The &lt;code&gt;nomodule&lt;/code&gt; attribute is a boolean attribute that prevents a script from being executed in user agents that support module scripts.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically, if you put &lt;code&gt;nomodule&lt;/code&gt; on a script tag, any evergreen browser which supports modules is going to ignore that script. So, your older browsers will download this, but the newer ones will not. This will save you about 56Kb on startup!&lt;/p&gt;

&lt;p&gt;If you found this useful, please leave a few claps for me and follow me on Medium!&lt;/p&gt;

&lt;p&gt;If you want to learn more about Angular, be sure and attend &lt;a href="https://www.2021.ng-conf.org/"&gt;ng-conf&lt;/a&gt;, the biggest, best Angular conference around!&lt;/p&gt;




&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>angular</category>
      <category>cli</category>
      <category>optimization</category>
    </item>
    <item>
      <title>Animating Angular’s *ngIf and *ngFor</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Fri, 25 Jun 2021 16:46:55 +0000</pubDate>
      <link>https://dev.to/ngconf/animating-angular-s-ngif-and-ngfor-5e12</link>
      <guid>https://dev.to/ngconf/animating-angular-s-ngif-and-ngfor-5e12</guid>
      <description>&lt;p&gt;Jared Youtsey | ng-conf | May 2019&lt;/p&gt;

&lt;p&gt;&lt;code&gt;*ngIf&lt;/code&gt; and &lt;code&gt;*ngFor&lt;/code&gt; will remove elements from the DOM. There isn’t a CSS solution for animating a non-existing element in the DOM. But Angular provides us with a simple solution.&lt;/p&gt;

&lt;p&gt;For purposes of brevity, wherever I refer to &lt;code&gt;*ngIf&lt;/code&gt; it is equally applicable to &lt;code&gt;*ngFor&lt;/code&gt;. The complete, working code can be downloaded &lt;a href="https://github.com/fivedice/ng-ngif-animations"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s start with the default application generated by the CLI and just modify the nice Angular logo in and out of the view based on a button we add.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng new ngifAnimation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You won’t need routing and can select SCSS for the styling.&lt;/p&gt;

&lt;p&gt;Let’s add the button we want to use to toggle our &lt;code&gt;*ngIf&lt;/code&gt; on the image. Open &lt;code&gt;app.component.html&lt;/code&gt; and add a simple button: (this is the default HTML)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!--The content below is only a placeholder and can be replaced.--
&amp;lt;div style="text-align:center"&amp;gt;
&amp;lt;h1&amp;gt;Welcome to {{ title }}!&amp;lt;/h1&amp;gt;
&amp;lt;button (click)="onClick()"&amp;gt;Toggle Image&amp;lt;/button&amp;gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s add the &lt;code&gt;onClick()&lt;/code&gt; method to the class that toggles a public variable &lt;code&gt;showImage&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class AppComponent {
  title = 'ngifAnimation';  
  showImage = false;
  onClick() {
    this.showImage = !this.showImage;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let’s add the &lt;code&gt;*ngIf&lt;/code&gt; in the template on the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;img
  *ngIf="showImage"
  width="300"
  alt="Angular Logo"
  src="..."
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s add a little bit of CSS to force the button to stay put when the image pops in and out: (&lt;code&gt;app.component.scss&lt;/code&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;button {
  display: block;
  margin: 0 auto;
  clear: both;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run the app now you’ll be able to click the button and the image will jarringly pop in and out of the view. If you check your developer tools, you’ll find that the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag is popping in and out of the DOM. When &lt;code&gt;showImage&lt;/code&gt; is false the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag isn’t even present. This is where our inability to use CSS comes into play. It’s a terrible user experience to have elements, especially large ones, pop in and out without some transition. Let’s make it grow and fade in and out in a pleasing manner!&lt;/p&gt;

&lt;p&gt;To handle animations (for way more reasons than just the one covered in this article) Angular provides the &lt;code&gt;BrowserAnimationsModule&lt;/code&gt;. As of the latest Visual Studio Code, though, it doesn’t want to auto-import this module for you if you add it to your &lt;code&gt;AppModule&lt;/code&gt; imports. It’s hidden in &lt;code&gt;@angular/platform-browser/animations&lt;/code&gt;. Let’s add the import manually and add it to the module’s imports.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, BrowserAnimationsModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’re ready to add our Angular animations! But where? We’ll approach this in the simplest manner. But be aware that we’re just scratching the surface of the power of Angular animation. It’s worth learning much more about. The simple approach is directly in the affected component. In our case, that’s &lt;code&gt;app.component.ts's&lt;/code&gt; &lt;code&gt;@Component&lt;/code&gt; directive. Here is the whole thing, but don’t worry, we’ll break it down and explain it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { trigger, state, style, animate, transition } from '@angular/animations';
@Component({
  ...,
  animations: [
    trigger(
      'inOutAnimation', 
      [
        transition(
          ':enter', 
          [
            style({ height: 0, opacity: 0 }),
            animate('1s ease-out', 
                    style({ height: 300, opacity: 1 }))
          ]
        ),
        transition(
          ':leave', 
          [
            style({ height: 300, opacity: 1 }),
            animate('1s ease-in', 
                    style({ height: 0, opacity: 0 }))
          ]
        )
      ]
    )
  ]
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whew! That’s a lot and it’s not terribly obvious without reading through it carefully. Let’s break it down, bit by bit.&lt;/p&gt;

&lt;p&gt;First, &lt;code&gt;animations: []&lt;/code&gt; is an array of things we want to happen or state definitions. In this case we just want to &lt;code&gt;trigger&lt;/code&gt; an animation called &lt;code&gt;inOutAnimation&lt;/code&gt;. You can name this what you like. It should be descriptive for what it accomplishes or what it should consistently apply to. In our case we are animating an image in and out of the view.&lt;/p&gt;

&lt;p&gt;Then, we give the &lt;code&gt;trigger&lt;/code&gt; a set of states and/or transitions. We only need two specific transitions to occur that are related to &lt;code&gt;*ngIf&lt;/code&gt;: &lt;code&gt;:enter&lt;/code&gt; and &lt;code&gt;:leave&lt;/code&gt;. These are the states that CSS just doesn’t give us. &lt;code&gt;:enter&lt;/code&gt; is when a DOM element is being added, and &lt;code&gt;:leave&lt;/code&gt; is when a DOM element is being removed.&lt;/p&gt;

&lt;p&gt;When we want the image to &lt;code&gt;:enter&lt;/code&gt; we are starting with the style of &lt;code&gt;height: 0, opacity: 0&lt;/code&gt;. It’s basically invisible to start with. When it’s done we would like it to be 300 pixels tall and be completely opaque.&lt;/p&gt;

&lt;p&gt;This is where the &lt;code&gt;animate&lt;/code&gt; instruction comes in. We are going to animate over 1) a period of time 2) with a particular easing mechanism 3) to a new style. 1 and 2 are combined in the first string-based instruction, &lt;code&gt;0.3s ease-out&lt;/code&gt;. This means that we are animating to the new style over 0.3 seconds, and we are easing out, or coming to a gentle stop rather than a sudden one. 3 specifies what the end styling should be. In our case that’s 300 pixels high and completely opaque.&lt;/p&gt;

&lt;p&gt;If you run this now you’ll find that nothing has changed. We now need to apply the animation to the element that is being added/removed from the DOM. In this case, it’s our &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag that has the &lt;code&gt;*ngIf&lt;/code&gt; directive on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;img
  *ngIf="showImage"
  [@inOutAnimation]
  width="300"
  alt="Angular Logo"
  src="..."
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we use the name of the trigger to bind the animation to the template element.&lt;/p&gt;

&lt;p&gt;If you run it now, you can click the button and the image zoom/fades in. Click it again and it’ll shrink/fade out! Voila!&lt;/p&gt;

&lt;p&gt;Personally, I find the syntax of Angular animations somewhat difficult. It’s non-obvious and, if you’re not doing it every day, you’re probably going to have to re-learn this a few times. And the template syntax works with or without the &lt;code&gt;[]&lt;/code&gt;'s, which makes me scratch my head a bit.&lt;/p&gt;

&lt;p&gt;Maybe the Angular team will give us a ReactiveAnimationsModule someday that makes animation a bit easier to work with, like ReactiveFormsModule did for forms? One can hope.&lt;/p&gt;

&lt;p&gt;This is just scratching the surface of what Angular animations are capable of. Very complex transforms/transitions are possible and can be carefully coordinated in ways that CSS just can’t guarantee.&lt;/p&gt;

&lt;p&gt;As a side note, if you’re worried about performance vs pure CSS animations, this is a quote from the &lt;a href="https://angular.io/guide/animations"&gt;Angular docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Angular’s animation system lets you build animations that run with the same kind of native performance found in pure CSS animations. You can also tightly integrate your animation logic with the rest of your application code, for ease of control.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you’ve found this useful, I’d appreciate a few claps for this article.&lt;/p&gt;

&lt;p&gt;If you’d like to learn more about Angular in a fun environment while hanging out with the movers and shakers of the Angular world, snag a ticket to &lt;a href="https://www.2021.ng-conf.org/"&gt;ng-conf&lt;/a&gt; and join us for the best Angular conference in the US.&lt;/p&gt;

&lt;p&gt;Image by &lt;a href="https://pixabay.com/users/piro4d-2707530/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=2137333"&gt;PIRO4D&lt;/a&gt; from &lt;a href="https://pixabay.com/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=2137333"&gt;Pixabay&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more Angular goodness, be sure to check out the latest episode of &lt;a href="https://www.spreaker.com/show/angular-show"&gt;The Angular Show podcast&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>animation</category>
      <category>css</category>
    </item>
    <item>
      <title>Supercharge your Angular application using Web Workers</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Tue, 22 Jun 2021 18:33:00 +0000</pubDate>
      <link>https://dev.to/ngconf/supercharge-your-angular-application-using-web-workers-5h9b</link>
      <guid>https://dev.to/ngconf/supercharge-your-angular-application-using-web-workers-5h9b</guid>
      <description>&lt;p&gt;Zama Khan Mohammed | ng-conf | May 2019&lt;/p&gt;

&lt;p&gt;UI blocking is a thing of the past!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-yEIvAYU2zBX9Uz0lPOPZA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-yEIvAYU2zBX9Uz0lPOPZA.jpeg" alt="Picture of a whirling rollercoaster. The picture is slightly overlaid with the text "&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h6&gt;
  
  
  Original 📷 by @ja5on
&lt;/h6&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AK5sj8pu5XuHL52JwFaIisw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AK5sj8pu5XuHL52JwFaIisw.png" alt="Add for angular. The image reads "&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h6&gt;
  
  
  &lt;a href="https://angularprojects.com" rel="noopener noreferrer"&gt;https://angularprojects.com&lt;/a&gt;
&lt;/h6&gt;

&lt;p&gt;If you are building an application where you do a lot of calculations on UI, such as creating CAD documents, doing heavy geometrical calculations, or heavy data table manipulations, then you might have observed that the UI sometimes becomes laggy or janky.&lt;/p&gt;

&lt;p&gt;This happens because JavaScript is not the only thing that runs on the main thread, but other things like the painting of pixels, style calculations, and many others also run on it. When we run heavy long-running JavaScript on the browser, occasionally we see that frames are missed, which does not provide a great User Experience.&lt;/p&gt;

&lt;p&gt;We have heard that Web Workers is one of the promising solutions to such a problem, but we never knew that it was so easy to introduce it to our Angular Application using Angular CLI.&lt;/p&gt;

&lt;p&gt;Angular CLI v8.0.0-beta.11 added improved bundling support for Web Workers without you needing to add any new configuration. In this article, we will create an application in which we will run heavy calculations of checking if a list of more than 600 numbers are prime numbers or not.&lt;/p&gt;

&lt;p&gt;Let’s create a new Angular CLI application using v8.0.0-beta.11 with npx command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npx -p @angular/cli@next ng new prime-numbers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding Web Workers is as easy as generating components, services, etc. using &lt;a href="https://next.angular.io/cli/generate#webworker" rel="noopener noreferrer"&gt;&lt;code&gt;ng generate&lt;/code&gt;&lt;/a&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; ng generate worker prime-calculations
CREATE src/tsconfig.worker.json (209 bytes)
CREATE src/tsconfig.json (131 bytes)
CREATE src/app/prime-calculations.worker.ts (121 bytes)
UPDATE tsconfig.app.json (232 bytes)
UPDATE angular.json (3558 bytes)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add a file called &lt;code&gt;prime-calculations.worker.ts&lt;/code&gt; in the app folder along with the other changes that are required for web workers setup (only done once).&lt;/p&gt;

&lt;p&gt;Now that we have our worker file, let’s first install a package &lt;a href="https://www.npmjs.com/package/prime-number" rel="noopener noreferrer"&gt;&lt;code&gt;prime-number&lt;/code&gt;&lt;/a&gt; that can check if a number is a prime number, and also has a list of 600+ prime numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; npm install prime-number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The operation that we want to execute in both JavaScript thread and Web Worker is the following, where we loop over the &lt;a href="https://github.com/fibo/prime-number/blob/master/list.js" rel="noopener noreferrer"&gt;&lt;code&gt;primeNumberList&lt;/code&gt;&lt;/a&gt; and check if they're a prime number or not by using the method &lt;a href="https://github.com/fibo/prime-number/blob/master/index.js" rel="noopener noreferrer"&gt;&lt;code&gt;isPrimeNumber&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import isPrimeNumber from 'prime-number';
import primeNumberList from 'prime-number/list';
const arePrimeList = primeNumberList.map((prime) =&amp;gt; {
    return isPrimeNumber(prime);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s add two buttons, one to run the logic in the worker, and another one in the main thread.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button (click)=”runWorker()”&amp;gt;Web Worker&amp;lt;/button&amp;gt;
&amp;lt;button (click)=”runThread()”&amp;gt;JavaScript Thread&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s add both methods to our AppComponent class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import isPrimeNumber from 'prime-number';
import primeNumberList from 'prime-number/list';
...
export class AppComponent {
    title = 'web-worker';
    runWorker() {
       const worker = new Worker('./prime-calculations.worker', { 
           type: 'module' 
       });
       worker.onmessage = ({ data }) =&amp;gt; {
           console.log('From Web Worker:', data);
       };
       worker.postMessage({});
    }
    runThread() {
        const arePrimeList = primeNumberList.map((prime) =&amp;gt; {
            return isPrimeNumber(prime);
        });
        console.log('From Javascript Thread', arePrimeList);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;runThread&lt;/code&gt; method is just doing calculations right in the method, but in &lt;code&gt;runWorker&lt;/code&gt;, we are creating a new worker, and listening to &lt;code&gt;onmessage&lt;/code&gt;, and then posting a message using &lt;code&gt;worker.postMessage()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let’s update our worker &lt;code&gt;prime-calculations.worker.ts&lt;/code&gt; with the same logic,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import isPrimeNumber from 'prime-number';
import primeNumberList from 'prime-number/list';
addEventListener('message', ({ data }) =&amp;gt; {
    const arePrimeList = primeNumberList.map((prime) =&amp;gt; {
        return isPrimeNumber(prime);
    });
    postMessage(arePrimeList);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we listen to the message and then run the same prime calculations that we did in the JavaScript thread.&lt;/p&gt;

&lt;p&gt;Now that both methods are doing the same calculations, let’s see how our app reacts when a user clicks on each button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F612%2F1%2ApQJYuMjnFkEa9ClKaBJCkQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F612%2F1%2ApQJYuMjnFkEa9ClKaBJCkQ.gif" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we clearly see the lag when the JavaScript Thread button was clicked. When we clicked on the Web Worker button we did not see any delay. That happened because the Web Worker runs in a separate thread and does not block the main thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion:
&lt;/h3&gt;

&lt;p&gt;Angular is not just a framework but it’s a platform. Angular’s tooling, especially Angular CLI is exceptional and it is what makes developing Angular Apps much easier.&lt;/p&gt;

&lt;p&gt;👋 Hi! I’m Zama Khan Mohammed. I work at &lt;a href="https://www.tekzenit.com/" rel="noopener noreferrer"&gt;Tekzenit&lt;/a&gt; as a Software Architect — Web Technologies. I’m actively involved in working on Projects using Angular, React and Serverless Technologies along with writing a book “Angular Projects”.&lt;/p&gt;

&lt;p&gt;For more Angular goodness, be sure to check out the latest episode of &lt;a href="https://www.spreaker.com/show/angular-show" rel="noopener noreferrer"&gt;The Angular Show podcast&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/" rel="noopener noreferrer"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webworker</category>
      <category>angular</category>
      <category>angular8</category>
    </item>
    <item>
      <title>Angular on Azure — Part I</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Thu, 17 Jun 2021 17:23:50 +0000</pubDate>
      <link>https://dev.to/ngconf/angular-on-azure-part-i-gng</link>
      <guid>https://dev.to/ngconf/angular-on-azure-part-i-gng</guid>
      <description>&lt;p&gt;Pankaj Parker | ng-conf | May 2019&lt;/p&gt;

&lt;p&gt;Using Azure Pipeline&lt;/p&gt;

&lt;p&gt;Developers test software in a local environment using servers such as LAMP, WAMP, node, IIS, and Apache. Local deployment is good in terms of fast development and debugging, but we can’t ship our physical machines to the client in order to access to the application 😂. We have to deploy an application to a web server/cloud in order to make it accessible to the end user on their preferred platform (mobile, desktop, etc).&lt;/p&gt;




&lt;p&gt;A variety of cloud providers exist in the current market, the most popular being &lt;a href="https://azure.microsoft.com/en-us/" rel="noopener noreferrer"&gt;Microsoft Azure&lt;/a&gt;, &lt;a href="https://cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud Platform&lt;/a&gt;, &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;. These providers offer an unbeatable combination of ease, speed, and automation, so if you have not deployed using such a platform, then this is the article for you! This article focuses on deploying an Angular app to Azure.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Deployment?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  The action of bringing resources into effective action
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;In web development, deployment is concerned with making our static/dynamic resources available over the wire so the end user can access them in a desired device, using a browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is hosting?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Web hosting is a service that allows organizations and individuals to post a website or web page onto the Internet.
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;The deployment process is incomplete without hosting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment Philosophy
&lt;/h3&gt;

&lt;p&gt;Deployment exposes your web application using a philosophy that has been followed for year. The diagram below outlines typical deployment steps that could be applied to any type of software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AMc5IA53FtAGiYqf9_IaIog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AMc5IA53FtAGiYqf9_IaIog.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Deployment Philosophy
&lt;/h6&gt;




&lt;h3&gt;
  
  
  What is Azure?
&lt;/h3&gt;

&lt;p&gt;Azure is a cloud platform service which provides cloud services, including those for compute, analytics, storage, serverless, AI and ML, IoT, containers, DevOps, mobile, and networking. It is widely considered as both a PaaS and IaaS product. This article covers the development, deployment, and DevOps aspects of the platform.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you are new to Azure, a &lt;a href="https://azure.microsoft.com/en-in/free/search/" rel="noopener noreferrer"&gt;free subscription&lt;/a&gt; is available for those wishing to try the platform without any commitment.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Azure App Service
&lt;/h3&gt;

&lt;p&gt;The Azure App Service is part of the PaaS section of the platform. It easily builds and deploys a highly available web app to the cloud. Multiple features are available right out of the box, as illustrated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A4RjvgjzIRDm6nsZEK9zbrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A4RjvgjzIRDm6nsZEK9zbrw.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Azure app service
&lt;/h6&gt;

&lt;p&gt;The important steps are numbered in the above screenshot. If a resource group is not created, then do so in step 3. Also, if you do not have a service plan, create one at this time. Make sure you select ‘ASP .NET 4.7’ in the ‘Runtime Stack’ option in step 5. For more information, follow the guide for the detailed creation of &lt;a href="https://docs.microsoft.com/en-us/azure/app-service/app-service-plan-manage" rel="noopener noreferrer"&gt;Azure Service Plan&lt;/a&gt; and &lt;a href="https://docs.microsoft.com/en-us/azure/app-service/environment/app-service-web-how-to-create-a-web-app-in-an-ase" rel="noopener noreferrer"&gt;Azure App Service&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you’re done with the fill in details, click on “Review and create” button and then on the next screen press “Create” button. To see the newly created resource you can click on “All Resources” option in the sidebar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A6k--VnP66c0sS43a2jJkxA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A6k--VnP66c0sS43a2jJkxA.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Newly created resource group added
&lt;/h6&gt;

&lt;p&gt;The following url can be loaded to check if the recently deployed application is available in the cloud, https://.azurewebsites.net/&lt;/p&gt;

&lt;p&gt;In my case I used app name as “angular-deployment” so URL would become &lt;a href="https://angular-deployment.azurewebsites.net/" rel="noopener noreferrer"&gt;https://angular-deployment.azurewebsites.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A24WH-7vUnIzc4Tyq_f4Exg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A24WH-7vUnIzc4Tyq_f4Exg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  The deployed application running in the cloud
&lt;/h6&gt;

&lt;p&gt;But, before moving forward, we should minimize the final bundle size of the application. No worries; that process is discussed in a later section.&lt;/p&gt;




&lt;h3&gt;
  
  
  Make angular application production ready
&lt;/h3&gt;

&lt;p&gt;Angular CLI tooling is incredible; simply executing &lt;code&gt;ng serve&lt;/code&gt; compiles angular code to Javascript and generates bundle files. For a simple hello-world app, however, the total file size is far short of desirable.&lt;/p&gt;

&lt;p&gt;Angular currently offers two compilation modes&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Just in Time (JIT) Mode&lt;/li&gt;
&lt;li&gt;Ahead of Time (AOT) Mode&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In short, JIT ships the Angular compiler over the wire and component templates are compiled inside the browser. AOT mode precompiles all templates and makes the resulting JS available for further optimization before shipping the bundled application over the wire. Smaller application sizes and quicker response makes for better UX!&lt;/p&gt;

&lt;p&gt;For those new to the Angular CLI, AOT mode is enabled with the command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng build --prod&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command compiles all templates, then applies tree-shaking, optimization, minification, and bundling to create a final, highly-optimized package. All distribution files are automatically placed in the &lt;code&gt;dist&lt;/code&gt; folder of your project, which can be directly hosted to a cloud provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup Deployment
&lt;/h3&gt;

&lt;p&gt;In this article, &lt;a href="https://azure.microsoft.com/en-us/services/devops/?nav=min" rel="noopener noreferrer"&gt;Azure DevOps&lt;/a&gt; (formerly known as VSTS) is used to deploy an application to the cloud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2Ay1T09C1j2toCE5ip114lFQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2Ay1T09C1j2toCE5ip114lFQ.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  DevOps create project
&lt;/h6&gt;

&lt;p&gt;If you have not created an organization, then do so before clicking the ‘Create Project’ button, as shown in the above diagram. This displays the ‘Create New Project’ dialog.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F638%2F1%2A7t2ioKH88sIk3QpMWhfM5Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F638%2F1%2A7t2ioKH88sIk3QpMWhfM5Q.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Create a project inside the Organization
&lt;/h6&gt;

&lt;p&gt;In “Create new project” screen, fill project name, description and select visibility (I selected private). Also, version control was set to ‘Git’, and ‘Work item process’ defaulted to ‘Agile.’ Then, click the ‘Create’ button.&lt;/p&gt;

&lt;p&gt;The dashboard page is displayed after a project is created. Several actions may be performed from the dashboard sidebar.&lt;/p&gt;




&lt;h3&gt;
  
  
  Azure DevOps Gist
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Boards — To track down tasks and progress of a project&lt;/li&gt;
&lt;li&gt;Repos — Code repositories involved in the development.&lt;/li&gt;
&lt;li&gt;Pipelines — CI / CD pipeline&lt;/li&gt;
&lt;li&gt;Test Plans — Provides all tools to successfully test your applications&lt;/li&gt;
&lt;li&gt;Artifacts — Provides a secure, highly performant store and easy feed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most important feature in the above list for purposes of this article is the Azure Pipelines setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create A Brand New Pipeline
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AKId1tf-5Wy0iwSk0ilqU_w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AKId1tf-5Wy0iwSk0ilqU_w.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Pipeline page
&lt;/h6&gt;

&lt;p&gt;Select the ‘Pipelines’ option from the left sidebar, which displays the ‘New Pipeline’ button in the middle of the screen. The following dialog is displayed after clicking the ‘New Pipeline’ button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AhMNFxFASJKGKlUYlMFO-8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AhMNFxFASJKGKlUYlMFO-8w.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Pipeline creation page
&lt;/h6&gt;

&lt;p&gt;Pipelines are created with &lt;code&gt;yaml&lt;/code&gt; files. A new &lt;code&gt;yaml&lt;/code&gt; file may be created with a visual tool or by using the ‘Use the classic editor’ link at the bottom of the dialog.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-T2OdpYwJtzyqKb3zLePdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-T2OdpYwJtzyqKb3zLePdw.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Repository selection
&lt;/h6&gt;

&lt;p&gt;The next step is selecting a repository resource, which can be a new repository (above) or using an existing repo as shown below. I’m using my existing Github repo, so I selected ‘Github’ at this stage. To select a Github repo, click on the ‘…’ Button to browse repositories.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AV_fH_YHyaH5VoRF1o4qb2Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AV_fH_YHyaH5VoRF1o4qb2Q.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Select a repository
&lt;/h6&gt;

&lt;p&gt;Select the desired repository for deployment. In this example, I selected the ‘weather-cast’ repo. Then, click the ‘Select’ button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F677%2F1%2AS_Z7wsW7cwIL3XtdeeXNEw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F677%2F1%2AS_Z7wsW7cwIL3XtdeeXNEw.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Select a source
&lt;/h6&gt;

&lt;p&gt;At this point, you are very close to creating a brand new pipeline! By default, the ‘master’ branch is selected. Click on the ‘Continue’ button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AlC7Gi8Aerr5p1W0R_mZe6A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AlC7Gi8Aerr5p1W0R_mZe6A.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Select job template page
&lt;/h6&gt;

&lt;p&gt;Now, you’ve made it to the final page of pipeline creation! Next, we create a ‘Job’, or the steps involved in the actual deployment. For now, just select ‘Empty Job’ to create a blank Job with no content. Don’t worry, we will add steps for it in the next section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AaAJBm0zeHJyVo5055Qn4Fg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AaAJBm0zeHJyVo5055Qn4Fg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Empty Job page
&lt;/h6&gt;

&lt;p&gt;After the pipeline is created, you will see a screen where an Agent pool is assigned to run a job when any tasks are to be deployed. For this tutorial, we are going to setup deployment tasks under the ‘Agent Job 1.’ Simply click on the ‘+’button in the dialog.&lt;/p&gt;




&lt;h3&gt;
  
  
  Setting Up Pipeline Step
&lt;/h3&gt;

&lt;p&gt;Cool! We’ve finally made it to the stage where we can add tasks for the deployment job! Refer to the following screen shot.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Install node
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AGqt4vq4HVydEA5kAHVVBpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AGqt4vq4HVydEA5kAHVVBpg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Install node on vm
&lt;/h6&gt;

&lt;p&gt;After clicking the ‘+’ icon beside ‘Agent Job 1,’ you can search by ‘node’ in the list (item 1 in the screen shot) then select ‘Node Tool Installer.’ When that dialog displays (item 2), click the ‘Add’ button (item 3 in the above screenshot).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AqsKZB6m3HaLfn1oWd5dzCg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AqsKZB6m3HaLfn1oWd5dzCg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Making node available on machine
&lt;/h6&gt;

&lt;p&gt;This displays the first task in the ‘Agent job 1’ list. Next, fill in the details for this task. Enter display and version spec, as shown above. This configures NodeJS on our VM.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Install Angular CLI
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-JFiJqXcNRsTTR-UtDh5Cg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-JFiJqXcNRsTTR-UtDh5Cg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Install Angular CLI to machine
&lt;/h6&gt;

&lt;p&gt;As before, search for ‘npm’ in the task list and then click the ‘Add’ button. Fill in the details as shown above to install the Angular CLI as the next step in the task list.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. npm install
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-5Zd-TNG559E72FDjdoH7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2A-5Zd-TNG559E72FDjdoH7g.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  npm install on package folder
&lt;/h6&gt;

&lt;p&gt;Continue the same process as above to create a task that installs all npm dependencies.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Create Prod Build
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2Aah8jl4lECBwjeqSYoltK8Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2Aah8jl4lECBwjeqSYoltK8Q.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Create prod build
&lt;/h6&gt;

&lt;p&gt;Again add &lt;code&gt;npm&lt;/code&gt; ask and fill in the details shown above. This time select command as in “custom”, and “command and arguments” would be &lt;code&gt;run build&lt;/code&gt;. Basically, it calls &lt;code&gt;ng build --prod&lt;/code&gt; command written as scripts in . This task helps to create a production ready angular package.&lt;/p&gt;

&lt;p&gt;This is the task that creates the production-ready Angular package. Continue as before using the details shown in the above screenshot. ‘Command’ is ‘custom’ and the ‘Command and arguments’ input is ‘ng build — prod’. This causes the &lt;code&gt;ng build --prod&lt;/code&gt; command to be written in the ‘scripts’ section of the &lt;code&gt;[package.json](https://github.com/pankajparkar/weather-cast/blob/master/package.json#L8)&lt;/code&gt; file.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Host dist folder
&lt;/h4&gt;

&lt;p&gt;Next, search for ‘Azure App Service Deploy’ and add it to the task list. Fill in the details as shown below. This task hosts and deploys code to the server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2Aso-VglqVEBzgwfQm80OigQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2Aso-VglqVEBzgwfQm80OigQ.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Azure app service deploy
&lt;/h6&gt;

&lt;p&gt;After you have finished entering details, click on the ‘Save and queue’ button. This saves and subsequently runs the pipeline. You will see a message with a hyperlink containing a build number. Or, you may navigate to ‘Pipelines &amp;gt; Builds’ to see the following screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AVODLr5mpU-tlllwaLyxBzQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1000%2F1%2AVODLr5mpU-tlllwaLyxBzQ.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  After the build is finished
&lt;/h6&gt;

&lt;p&gt;After the job is finished, we can check it as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AACC1CI7PNdNJVVS4muxwyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AACC1CI7PNdNJVVS4muxwyg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Final Azure Pipeline
&lt;/h6&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F483%2F1%2AKot5V0Amwt1C1mgmVYRTgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F483%2F1%2AKot5V0Amwt1C1mgmVYRTgg.png" alt="Image for post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Final pipeline tasks
&lt;/h6&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This article outlined the steps to deploy an Angular application to Azure directly from Github or another repository. An Azure pipeline is a powerful feature to setup and visualize a deployment job with minimal effort.&lt;/p&gt;




&lt;p&gt;If you like this article press 👏 clap button 50 times or as many times you want. Feel free to ask a question if you have any. Thanks a lot for reading!&lt;/p&gt;




&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/" rel="noopener noreferrer"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Soon, I will release part II of this article which covers CI and CD with Azure&lt;br&gt;
Pipeline. Stay tuned!&lt;/p&gt;

&lt;p&gt;For more Angular goodness, be sure to check out the latest episode of [The Angular Show podcast]&lt;/p&gt;

</description>
      <category>azure</category>
      <category>angular</category>
      <category>devops</category>
      <category>azurepipelines</category>
    </item>
    <item>
      <title>Dynamic Component Generation in Lazy-Loaded Routes</title>
      <dc:creator>ng-conf</dc:creator>
      <pubDate>Tue, 15 Jun 2021 18:30:13 +0000</pubDate>
      <link>https://dev.to/ngconf/dynamic-component-generation-in-lazy-loaded-routes-14eh</link>
      <guid>https://dev.to/ngconf/dynamic-component-generation-in-lazy-loaded-routes-14eh</guid>
      <description>&lt;p&gt;Jim Armstrong | ng-conf | Jun 2019&lt;/p&gt;

&lt;p&gt;&lt;em&gt;— Exploit Data Driven Component Layout, Loaded On-Demand in Angular&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of the fun things about being an applied mathematician in front-end development is the never-ending stream of complex, interactive problems that users wish to solve. These range from gamification of business applications to data-driven user experiences. Two interesting applications of the latter topic include dynamic routing through an application and dynamic component layout. Both are examples of user experiences that vary based on factors such as user role and prior uses of the application. In other words, two different users may be presented with an entirely different experience based on both a &lt;em&gt;priori&lt;/em&gt; knowledge of the user and how the user interacts with the application in real time.&lt;/p&gt;

&lt;p&gt;The general solution I’ve applied to dynamic routing is a data-driven, adaptive decision tree. This is, unfortunately, a client-proprietary solution and can not be shared in public. However, I built the solution on top of two projects that I have released to the public in my Github, a general tree data structure and a lightweight expression engine. Both are written in Typescript. I believe any enterprising developer with some fundamental knowledge of decision trees could duplicate my work. So, here is the best I can do for you at present:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/theAlgorithmist/TSTree"&gt;theAlgorithmist/TSTree&lt;/a&gt; - Typescript Math Toolkit General Tree Data Structure on github.com&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/theAlgorithmist/TSExpressionEngine"&gt;theAlgorithmist/TSExpressionEngine&lt;/a&gt; - Typescript Math Toolkit Expression Engine on github.com&lt;/p&gt;

&lt;h4&gt;
  
  
  Dynamic, Data-Driven Component Layout
&lt;/h4&gt;

&lt;p&gt;This article discusses how to layout Angular components programmatically, based on a simple JSON data structure. A simple example I’ve worked on in the past is where components are vertically stacked in an order that is server-generated. Consider a case where three components, A, B, and C could be presented to a user. They might be displayed in the order A, B, C, or A, C, B, or perhaps C, B, A. In general, there are &lt;em&gt;n&lt;/em&gt;! display permutations of &lt;em&gt;n&lt;/em&gt; components (displayed &lt;em&gt;n&lt;/em&gt; at a time). One might be willing to struggle with a layout that could accommodate all possible scenarios for three components, but what about when the client later indicates there could be anywhere from three to eight components? And, we know how clients think, so that 3–8 range will not stay constant for very long. In short, this is a situation that is much better managed with an imperative instead of declarative approach.&lt;/p&gt;

&lt;p&gt;Thankfully, the Angular team has provided everything we need to dynamically generate components at runtime. But, before we move on, here is the repo for this article so that you can follow along with the deconstruction, and have the code for experimentation and future usage in projects.&lt;/p&gt;

&lt;p&gt;&lt;a href=""&gt;theAlgorithmist/Angular8LazyLoadDynamic&lt;/a&gt; - Angular 8 Dynamic Component Generation in a Lazy-Loaded Route on github.com&lt;/p&gt;

&lt;h4&gt;
  
  
  The Scenario
&lt;/h4&gt;

&lt;p&gt;This demo simulates a scenario where a user logs into an application and then selects a navigational element that routes to another area of the application. The user experience, however, is tailored to each specific user based on information that is known about the user after login. A service call is to be made before activating the route. The service returns some JSON data that describes the order in which child components are to be displayed in the Angular Component associated with the selected route. The JSON data also provides some simple textual and numerical data that is used for binding within each of the child components.&lt;/p&gt;

&lt;p&gt;Since the order of the components is not known in advance and the number of components can also vary, the child components are dynamically created and then rendered into the parent component’s template. For demonstration purposes, the number of components in the code distribution is limited to three. The technique, however, is easily scaled to any number of components in any arbitrary order.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Process
&lt;/h4&gt;

&lt;p&gt;I’ll treat the explanation in a cookbook fashion since additional information on each step in the process is readily available online for subsequent study.&lt;/p&gt;

&lt;p&gt;1 — Each child component that could be rendered into a parent component must be provided as an &lt;em&gt;EntryComponent&lt;/em&gt; into the &lt;em&gt;Module&lt;/em&gt; associated with the route. This is why the route should be lazy-loaded as there is no guarantee that every user will navigate to this route.&lt;/p&gt;

&lt;p&gt;2 — A route &lt;em&gt;Resolver&lt;/em&gt; is used to ensure that the JSON data is loaded before the route activates. This is the mechanism a server would use to dynamically alter the experience for each individual user.&lt;/p&gt;

&lt;p&gt;3 — In order for an Angular component to be dynamically displayed in a template, it must be added to a &lt;em&gt;ViewContainerRef&lt;/em&gt; associated with a DOM container after creating the component. An &lt;em&gt;Attribute Directive&lt;/em&gt; is used for this purpose.&lt;/p&gt;

&lt;p&gt;4 — Each child component is to be generated by two &lt;em&gt;Factories&lt;/em&gt;. One factory (that we write) generates component type and raw data instances based on a symbolic code and a known number of components. So, if the component range is changed from 3–8 to 2–12 at a later point, the four new items must be added to the factory. Another factory (provided by Angular and discussed below) is used to create the actual Angular component at runtime.&lt;/p&gt;

&lt;p&gt;5 — The template for the lazy-loaded component consists of a &lt;em&gt;ng-container&lt;/em&gt; as the primary container with a &lt;em&gt;ngFor&lt;/em&gt; that loops over the number of dynamic components specified in the JSON data.&lt;/p&gt;

&lt;p&gt;6 — Each dynamic component is associated with a &lt;em&gt;ng-template&lt;/em&gt; by using an attribute &lt;em&gt;directive&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;7 — A &lt;em&gt;QueryList&lt;/em&gt; of dynamic item attribute directives is processed by the parent component. Each child component is created by an Angular Component &lt;em&gt;Factory&lt;/em&gt; (provided by a factory resolver) and then added to the &lt;em&gt;ViewContainerRef&lt;/em&gt; of the &lt;em&gt;ng-template&lt;/em&gt;. Data for each component is then added to the newly created component for binding. This requires some handshaking between the parent component code and the attribute directive. The actual separation of concerns can be experimented with and adjusted to suit your specific desires.&lt;/p&gt;

&lt;h4&gt;
  
  
  Application Layout
&lt;/h4&gt;

&lt;p&gt;The application structure for this demo is rather simple. There is a single application module and component. The main app component displays a button whose markup contains a &lt;em&gt;routerLink&lt;/em&gt;. That is used to route the user to the single feature module, appropriately named ‘feature’ :)&lt;/p&gt;

&lt;p&gt;The main app module provides a single route resolver that is used to ensure the JSON data for dynamic layout is loaded before the route is activated.&lt;/p&gt;

&lt;p&gt;All libraries, directives, and components for the single feature are provided in the &lt;em&gt;feature&lt;/em&gt; folder.&lt;/p&gt;

&lt;p&gt;The model for dynamically generated components is provided in &lt;em&gt;src/app/models&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There is no relevant code in the main app component and the only item worth deconstructing is the main app routing module. Relevant code from the routing module is provided below.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/src/app/app-route-module.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const routes: Routes = [
  {
    path: `feature`,
    resolve: { model: AppRouteResolver },
    loadChildren: () =&amp;gt; import(`./feature/feature.module`).then(m =&amp;gt; m.FeatureModule)
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  providers: [AppRouteResolver],
  exports: [RouterModule]
})
export class AppRoutingModule { }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the new Angular 8 dynamic import syntax for lazy-loaded routes. This module also provides the route resolver, &lt;em&gt;AppRouteResolver&lt;/em&gt;. The &lt;em&gt;model&lt;/em&gt; property is used when loading data from the activated route.&lt;/p&gt;

&lt;p&gt;Now, we can deconstruct each of the above-listed steps.&lt;/p&gt;

&lt;h4&gt;
  
  
  (1) Feature Module
&lt;/h4&gt;

&lt;p&gt;Look at &lt;em&gt;/src/app/feature/feature.module.ts&lt;/em&gt;. The important code is shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const DYNAMIC_COMPONENTS: Array&amp;lt;any&amp;gt; = [
  BaseComponent, Component1Component, Component2Component, Component3Component
];

@NgModule({
  declarations: [
    DynamicItemDirective, FeatureComponent, ...DYNAMIC_COMPONENTS
  ],
  imports: [
    CommonModule,
    RouterModule,
    RouterModule.forChild(localRoutes),
  ],
  providers: [],
  entryComponents: DYNAMIC_COMPONENTS
  exports: [
    DynamicItemDirective, ...DYNAMIC_COMPONENTS
  ]
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three dynamic components in this example are &lt;em&gt;Component1Component, Component2Component,&lt;/em&gt; and &lt;em&gt;Component3Component&lt;/em&gt;. Yes, those are stupid names, but slightly better than my original choice of Moe, Larry, and Curly :) Each of these components extends &lt;em&gt;BaseComponent&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In particular, note the declaration of all of dynamic components in the &lt;em&gt;entryComponents&lt;/em&gt; property of &lt;em&gt;NgModule&lt;/em&gt;. Since there is no direct reference to any of these components in a template, Angular needs this information directly for compilation purposes. Without &lt;em&gt;entryComponents&lt;/em&gt; Angular will tree-shake out those components because they are never referenced in a template.&lt;/p&gt;

&lt;p&gt;The attribute directive, &lt;em&gt;DynamicItemDirective&lt;/em&gt;, is used to associate a &lt;em&gt;ViewContainerRef&lt;/em&gt; with a specific DOM element (&lt;em&gt;ng-template&lt;/em&gt; in this example).&lt;/p&gt;

&lt;h4&gt;
  
  
  (2) Route Resolver
&lt;/h4&gt;

&lt;p&gt;The resolver is used by the main app component and is provided in &lt;em&gt;/src/app/app-route.resolver.ts&lt;/em&gt;. This code implements the &lt;em&gt;Resolve&lt;/em&gt; interface by providing a concrete implementation of the &lt;em&gt;resolve()&lt;/em&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Injectable({providedIn: 'root'})
export class AppRouteResolver implements Resolve&amp;lt;LayoutModel&amp;gt;
{
  constructor(@Inject(DataService) protected _service: DataService)
  {
    // empty
  }

  resolve(): Observable&amp;lt;LayoutModel&amp;gt;
  {
    // load layout model
    return &amp;lt; Observable&amp;lt;LayoutModel&amp;gt; &amp;gt; this._service.getData('/assets/layout-model.json');
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ng-conf: Join us for the Reliable Web Summit
&lt;/h2&gt;

&lt;p&gt;Come learn from community members and leaders the best ways to build reliable web applications, write quality code, choose scalable architectures, and create effective automated tests. Powered by ng-conf, join us for the Reliable Web Summit this August 26th &amp;amp; 27th, 2021.&lt;br&gt;
&lt;a href="https://reliablewebsummit.com/"&gt;https://reliablewebsummit.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>dynamiccomponents</category>
    </item>
  </channel>
</rss>
