<?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: Christian Kohler</title>
    <description>The latest articles on DEV Community by Christian Kohler (@christiankohler).</description>
    <link>https://dev.to/christiankohler</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%2F203892%2F20ff7c09-2a2a-47c3-bc7d-1394353a588d.jpeg</url>
      <title>DEV Community: Christian Kohler</title>
      <link>https://dev.to/christiankohler</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/christiankohler"/>
    <language>en</language>
    <item>
      <title>Angular Modules Best Practices 2021</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Mon, 05 Jul 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/playfulprogramming-angular/angular-modules-best-practices-2021-3lo5</link>
      <guid>https://dev.to/playfulprogramming-angular/angular-modules-best-practices-2021-3lo5</guid>
      <description>&lt;p&gt;Angular Modules are used to organize an application and consolidate components, directives, and pipes into blocks of functionality.&lt;/p&gt;

&lt;p&gt;A good strategy can improve code organization, optimize the bundle size and make it easy to extend and refactor an application. A bad strategy can lead to dependency hell and larger bundles than necessary.&lt;/p&gt;

&lt;p&gt;In this blog I will cover different strategies and give you tips on how to choose a strategy for your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TLDR;&lt;/li&gt;
&lt;li&gt;Example Application&lt;/li&gt;
&lt;li&gt;Aspects&lt;/li&gt;
&lt;li&gt;Strategies&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;I use various aspects like bundle size, scalability, simplicity, and boilerplate to compare different module strategies.&lt;/p&gt;

&lt;p&gt;The outcome is that there is not a single strategy for all types of applications but this post should help you in the decision-finding process for which strategy to choose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Application
&lt;/h2&gt;

&lt;p&gt;I will show you how I would organize an application. It is neither a simple counter nor a large enterprise app. So it might not fit your app size but I think it is a good structure to start a new app.&lt;/p&gt;

&lt;p&gt;We take a music player as an example application. This should be a very familiar application to most of you. It has a global player reachable at the bottom and a few views to find and browse songs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fft1mvf8a3vy0fkl0dsdv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fft1mvf8a3vy0fkl0dsdv.png" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Folder Structure
&lt;/h3&gt;

&lt;p&gt;Let’s forget about angular modules for a moment and let’s see how we can structure our application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Folder structure and code organization are subjective and depend on the app you are working on. This is only an inspiration for how you could structure your app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I use three main folders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;core&lt;/li&gt;
&lt;li&gt;shared&lt;/li&gt;
&lt;li&gt;views&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fnlhc4wrd3baxvhz3ur0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fnlhc4wrd3baxvhz3ur0c.png" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Views&lt;/strong&gt; contains the 3 views we can route to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;home-view&lt;/li&gt;
&lt;li&gt;search-view&lt;/li&gt;
&lt;li&gt;album-view&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fru8tkyy26tjt5ii29krb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fru8tkyy26tjt5ii29krb.png" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core&lt;/strong&gt; contains all the components which need to be available when the app starts. This includes the shell and the bottom menu. Also part of the core is the mini-player and the fullscreen player.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F3lxw4ou4zxirad2ige2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3lxw4ou4zxirad2ige2m.png" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shared&lt;/strong&gt; contains all the components which are shared between the views. In our example we have two shared components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;horizontal-albums&lt;/li&gt;
&lt;li&gt;main-title&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F64qucfdcy1mcwwt1qbem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F64qucfdcy1mcwwt1qbem.png" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;View Specific Components&lt;/strong&gt; is one folder (type) I didn’t mention at the beginning. Some components are reused in different views, some are only used in one view. Keeping code as close as possible to where it is used is a good practice. Therefore we place components that are only used in one view into that view folder. In this example that would be the search-bar which is only used in the search view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fq0yjh3ncnpt383870avv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fq0yjh3ncnpt383870avv.png" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Angular Modules
&lt;/h2&gt;

&lt;p&gt;Angular Modules can now be used to combine those components into modules. There are many ways how to slice an app into Angular modules and there is no right or wrong way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aspects
&lt;/h3&gt;

&lt;p&gt;There are a few aspects we should consider when deciding on one or the other approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bundle size&lt;/strong&gt; can be affected by how the modules are sliced. It can be the overall bundle size or also the individual lazy loaded bundles. This impacts the loading time of your app in a browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt; is about how easy it is to navigate and make changes in your code. Depending on how you slice your application, reorganization of code can be more difficult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplicity&lt;/strong&gt; is about how easy it is for someone in the team to understand when and where to create an Angular module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Boilerplate&lt;/strong&gt; How much boilerplate do we need for our Angular modules? The more modules the more boilerplate. This can usually be resolved by generating boilerplate with a CLI or an IDE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testabilty&lt;/strong&gt; How easy is it to test a single component? If the component is part of a large module, we may have to mock many services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strategies
&lt;/h3&gt;

&lt;p&gt;There are 3 strategies I want to have a closer look at today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everything in one module&lt;/li&gt;
&lt;li&gt;One module per feature / view (Lazy Load)&lt;/li&gt;
&lt;li&gt;One module per component (SCAM)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fvfrgt1tje1eaz9n9j5lm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fvfrgt1tje1eaz9n9j5lm.png" width="800" height="688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All strategies have their pros and cons. The radar chart compares the different approaches visually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One module for all components&lt;/strong&gt; is very simple. Whenever we create a component, we add it to the app.module declaration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fm0air1yxi5bc78suuexv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fm0air1yxi5bc78suuexv.png" width="762" height="829"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach is very simple but has a few downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All components are eagerly loaded which results in a longer initial load time&lt;/li&gt;
&lt;li&gt;The app.module file gets bloated and refactoring means touching this file all the time&lt;/li&gt;
&lt;li&gt;Resolving dependencies is a nightmare. For example, it is very hard to figure out what we can remove after deleting a component. Maybe a component was only used in the deleted component and miss to remove that one as well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach might work for very small applications but I wouldn’t recommend it for bigger projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One module per component (SCAM)&lt;/strong&gt; is the exact opposite of the previous approach. In this strategy, we create a single module for every component. SCAM is an abbreviation for “Single Component Angular Module”. Lars Gyrup Brink Nielsen coined the term in &lt;a href="https://dev.to/this-is-angular/angular-revisited-tree-shakable-components-and-optional-ngmodules-36d2"&gt;this blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8jclucr2avcr9kozrt5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8jclucr2avcr9kozrt5e.png" width="762" height="1100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I like about this approach is that it is much easier to understand which dependencies a component has. Each component module only imports the modules it directly uses. That means if we remove a component we also remove all its dependencies automatically. Nice.&lt;/p&gt;

&lt;p&gt;Another benefit of this approach is that Angular can build the optimal bundles for lazy loaded routes thanks to the clear dependency tree.&lt;/p&gt;

&lt;p&gt;And last but not least, the rule is very simple: Every component has its module. That’s it, no discussions about how to slice the modules.&lt;/p&gt;

&lt;p&gt;The only downside I see is that it adds some boilerplate since we have more module definitions and we have to import all dependencies explicitly. But that might change in the future with a new API on the @Component decorator which allows standalone components (without NgModules). For more on that, you can follow that &lt;a href="https://github.com/angular/angular/pull/42831" rel="noopener noreferrer"&gt;spike on Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One module per feature / view (Lazy Load)&lt;/strong&gt; is probably the most common pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1pabvjyq7h38qah2rlzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1pabvjyq7h38qah2rlzz.png" width="762" height="1034"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We get the optimal bundle size when we load all the view lazy. Since the shared module is used in multiple lazy loaded modules, it gets loaded in a separate common module. For more details on that, I wrote a blog post about how Angular bundles modules. &lt;a href="https://christiankohler.net/bundling-angular-modules" rel="noopener noreferrer"&gt;Bundling Angular Modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This pattern is somewhere in the middle of the two other approaches. We get small bundle sizes with little boilerplate and we still have a clear structure.&lt;/p&gt;

&lt;p&gt;If your application is larger you can also split the modules again into smaller feature modules or bundle views together into bigger feature bundles. This can either help you organize your code or lead to confusion on when to create those sub-modules. Angulars official &lt;a href="https://angular.io/guide/module-types" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; is a good read to learn more about this pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to decide what pattern to use?
&lt;/h2&gt;

&lt;p&gt;The easiest decision is to rule out putting everything into one single module. If the application has routes and has more than 10 components, don’t go with that strategy.&lt;/p&gt;

&lt;p&gt;To decide between the view/feature module and the single component module you have to ask yourself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How much boilerplate are you willing to add for a clear dependency tree and a simple rule to follow?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Going with the classic feature/view module approach is still my go-to approach as long as the feature module imports and declarations are manageable.&lt;/p&gt;

&lt;p&gt;If you build a library, the SCAM strategy is perfect since it allows the library consumer to only import the components they use. It is also good if you have difficulties defining a good strategy due to its simple rules.&lt;/p&gt;

&lt;p&gt;Both SCAM and the classic feature/view module approach result in the same bundle structure. So both are very good from a performance perspective. However, this is only the case as long as we do not accidentally import a feature module in the app or core module, which does not happen with SCAM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this blog post, you learned different module strategies and various aspects like bundle size, scalability, simplicity, and boilerplate which helps you to decide on a strategy.&lt;/p&gt;

&lt;p&gt;The three strategies I've shown here are the ones I mainly see and know. If you use another strategy, let me know, maybe I'll have to update the blog post soon with a new strategy 🙃&lt;/p&gt;

&lt;p&gt;If you liked the article 🙌, spread the word and &lt;a href="https://twitter.com/KohlerChristian" rel="noopener noreferrer"&gt;follow me on Twitter&lt;/a&gt; for more posts on web technologies.&lt;/p&gt;

&lt;p&gt;Did you find typos 🤓? Please help improve the blogpost and open an issue &lt;a href="https://github.com/ChristianKohler/homepage" rel="noopener noreferrer"&gt;here&lt;/a&gt; or post your feedback &lt;a href="https://github.com/ChristianKohler/Homepage/discussions/19" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Angular Change Detection Infographic</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Mon, 10 May 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/angular-change-detection-infographic-1821</link>
      <guid>https://dev.to/christiankohler/angular-change-detection-infographic-1821</guid>
      <description>&lt;h1&gt;
  
  
  Angular Change Detection Infographic
&lt;/h1&gt;

&lt;p&gt;The Angular way of change detection is very powerful and makes it easy to start building Angular apps. It is basically magic since it doesn't require the developer to do trigger it manually, it just works. Unless it doesn't where it can be a daunting task to debug the change detection process.&lt;/p&gt;

&lt;p&gt;This cheatsheet is for everyone who wants to know more about how change detection in Angular works.&lt;/p&gt;

&lt;p&gt;👩‍🚀 Protip: 🖨 Print this cheatsheet as a poster and hang it in the toilet. Within a few weeks your work colleagues are Angular experts 😀&lt;/p&gt;

&lt;p&gt;✅ Also feel free to use the cheatsheet for education purposes like workshops or in classes.&lt;/p&gt;

&lt;p&gt;👆 It took me hours to complete this cheatsheet. If you like it follow me on &lt;a href="https://twitter.com/kohlerchristian"&gt;twitter&lt;/a&gt; and spread the word 🙌&lt;/p&gt;

&lt;p&gt;🤓 Did you find a mistake? Please help improve the infographic and open an issue &lt;a href="https://github.com/ChristianKohler/homepage"&gt;here&lt;/a&gt; or give your feedback &lt;a href="https://github.com/ChristianKohler/Homepage/discussions/16"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2021-05-10-infographic-angular-cd/angular-cd-cheatsheet-v1-0.pdf"&gt;Download Angular DI Infographic as PDF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yVGukXia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2021-05-10-infographic-angular-cd/images/angular-cd-cheatsheet-v1-0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yVGukXia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2021-05-10-infographic-angular-cd/images/angular-cd-cheatsheet-v1-0.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Bundling Angular Modules</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Fri, 22 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/bundling-angular-modules-4eco</link>
      <guid>https://dev.to/christiankohler/bundling-angular-modules-4eco</guid>
      <description>&lt;h1&gt;
  
  
  Bundling Angular Modules
&lt;/h1&gt;

&lt;p&gt;NgModules are controversial. They make it harder getting started with Angular. They might become &lt;a href="https://angular.io/guide/roadmap#simplified-angular-mental-model-with-optional-ngmodules" rel="noopener noreferrer"&gt;optional in the future&lt;/a&gt;. But today they are here and it is helpful to understand how they work and how you can use them to write modular and performant applications.&lt;/p&gt;

&lt;p&gt;With the recent updates, especially with Ivy, NgModules became less intrusive and easier to use. In this blogpost I want to give you an overview what you need to know about NgModules in the Ivy world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tldr;&lt;/li&gt;
&lt;li&gt;Why do we need NgModules?&lt;/li&gt;
&lt;li&gt;How to make a component available in a NgModule&lt;/li&gt;
&lt;li&gt;How modules are bundled&lt;/li&gt;
&lt;li&gt;Best practices&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tldr;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Today NgModules are mainly used to register components, directives and pipes&lt;/li&gt;
&lt;li&gt;There are two types of NgModules: Eagerly loaded and lazy loaded modules&lt;/li&gt;
&lt;li&gt;Eagerly loaded modules are always bundled in the main bundle&lt;/li&gt;
&lt;li&gt;Lazy loaded modules have their own bundle file&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Note
&lt;/h2&gt;

&lt;p&gt;Most of the learnings in this blog post apply not only to components but to directives and pipes as well. I use components as a drop in replacement for components/directives/pipes to keep it simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we need NgModules?
&lt;/h2&gt;

&lt;p&gt;With Ivy, one of the main reasons we need NgModules is to register components, directives and pipes.&lt;/p&gt;

&lt;p&gt;When Angular parses a template and sees a custom tag/element (e.g. &lt;code&gt;&amp;lt;component-a&amp;gt;&amp;lt;/component-a&amp;gt;&lt;/code&gt;), the parser looks for a registered angular component which matches the selector.&lt;/p&gt;

&lt;p&gt;Every framework has this challenge. React uses JSX, Vue solves it with a components property on the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ComponentA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ComponentB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;component-a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ComponentA&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Angular solves it with the declaration property on @NgModules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;component-a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ComponentA&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;component-b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;component-a&amp;gt;&amp;lt;/component-a&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ComponentB&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ComponentA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ComponentB&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Angular compiler uses that information and adds all registered components which are used to the component definition. Actually, the directives array in the compiled component looks somehow similar to Vue's approach with the components definition.&lt;/p&gt;

&lt;p&gt;In a simplified example, ComponentB would be compiled to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ComponentB&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nx"&gt;ComponentB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ɵcmp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ɵɵdefineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// template: &amp;lt;component-a&amp;gt;&amp;lt;/component-a&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;ɵɵelement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;component-a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;directives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ComponentA&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- register ComponentA&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, Angular makes sure that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The component is included in the bundle since it is referenced&lt;/li&gt;
&lt;li&gt;The component template can compile its child components&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to go more into detail, here is a working example of an Angular app without NgModules and with the directives array to register components: &lt;a href="https://stackblitz.com/edit/example-ng-without-modules" rel="noopener noreferrer"&gt;https://stackblitz.com/edit/example-ng-without-modules&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Other use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The AppModule is also responsible to define how the application is bootstrapped.&lt;/li&gt;
&lt;li&gt;Even though nowadays most providers/services can be defined without NgModules it is still a solution for more complex scenarios.&lt;/li&gt;
&lt;li&gt;In pre-Ivy applications, entryComponents needed to be defined. Not required anymore in the Ivy-world.&lt;/li&gt;
&lt;li&gt;Additional schemas can be defined. For example to use custom elements with Angular.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to make a component available in a NgModule
&lt;/h2&gt;

&lt;p&gt;As we now learned, by declaring a component in a NgModule, we make it available to use in other components.&lt;/p&gt;

&lt;p&gt;Let's have a closer look how we can make components available in different NgModules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directly declare it
&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F9.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F9.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the easiest way to make a component available within a NgModule.&lt;/p&gt;

&lt;h3&gt;
  
  
  Import it from a different NgModule
&lt;/h3&gt;

&lt;p&gt;Let's say the component is declared in a different NgModule (e.g. "MyComponents") and we want to use it in "MyModule". We need to do two things:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Export the component to make it available for other components (think of it as public components)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponents&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Import the NgModule (e.g. "MyComponents") in "MyModule"
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyComponents&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only import the NgModule without exporting the component, the component is not available in the other module:&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F10.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F10.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is why you have to make sure to also export components you want to make "public".&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F11.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F11.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A common question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I import my component library module in the main NgModule and then use the components in all feature modules?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Answer is no. You have to explicitly import the component library module in every feature module.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F12.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F12.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That brings up the question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Will it have an impact on the bundle size if I import a NgModule in every feature module?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Short answer is no. But let's have a closer look in "How modules are bundled".&lt;/p&gt;

&lt;h2&gt;
  
  
  How modules are bundled
&lt;/h2&gt;

&lt;p&gt;Angular knows two kind of NgModules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eagerly loaded modules&lt;/li&gt;
&lt;li&gt;Lazy loaded modules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AppModule is always loaded eagerly. Lazy modules can be loaded when we navigate to a lazy route. That way the browser doesn't need to load the full application initially.&lt;/p&gt;

&lt;p&gt;The way we define NgModules affects the resulting JavaScript bundle files.&lt;/p&gt;

&lt;p&gt;Let's have a closer look.&lt;/p&gt;

&lt;h3&gt;
  
  
  Component not declared
&lt;/h3&gt;

&lt;p&gt;If you don't declare a component in a NgModule, the component is not bundled. Luckily the compiler throws an error in that case.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F1.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Most simple example
&lt;/h3&gt;

&lt;p&gt;The simplest example is a single module declaring a single component. In that case, as you would expect, the component is bundled in the main JavaScript bundle.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F2.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Separate EagerModule
&lt;/h3&gt;

&lt;p&gt;Every eagerly loaded module is bundled in the main JavaScript bundle. Eagerly loaded modules are always defined in the AppModules import array or in a transitive module (e.g. AppModule &amp;lt;- EagerModule &amp;lt;- OtherModule).&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F3.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy loaded Modules
&lt;/h3&gt;

&lt;p&gt;A lazy loaded module is not directly imported via the imports array but is defined within the router configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lazy-route&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;loadChildren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2021-01-22-ng-modules/lazy.module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LazyModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way the module is only loaded when the user navigates to this page. Angular creates a separate JavaScript bundle for the lazy loaded module.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F4.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F4.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared modules
&lt;/h3&gt;

&lt;p&gt;Shared modules are NgModules which declare and export some components / directives / pipes or services. We could also say it is a small library.&lt;/p&gt;

&lt;p&gt;If a shared module is only imported in a lazy loaded module, it is bundled in the lazy bundle.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F5.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F5.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the shared module is imported in both, an eager loaded module and a lazy loaded module it is only bundled in the main bundle.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F6.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F6.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the shared module is imported in two lazy loaded modules (but not in an eagerly loaded module) a common bundle is generated for the shared code and loaded together with the first lazy loaded module.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F7.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2021-01-22-ng-modules%2Fimages%2F7.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Noteworthy
&lt;/h3&gt;

&lt;p&gt;As you can see, Angular is very clever to split the application in multiple bundles. What you need to know though:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you import a module, all components are bundled, even if not all are used.&lt;/li&gt;
&lt;li&gt;The smaller the modules the better Angular can optimise the bundles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;p&gt;So now we know why and how components are bundled. But we don't now when to create a module. Should you make small or big bundles? What are the best practices?&lt;/p&gt;

&lt;p&gt;There is no simple answer to those questions. This is why I will create a follow up post where I try to answer those questions. Stay tuned ;-)&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;NgModules are required to register components, directives and pipes. All eagerly loaded NgModules are bundled in the main bundle. Lazy loaded modules all have a separate bundle. Shared modules are bundled in an optimal way to not load them too early.&lt;/p&gt;

&lt;p&gt;If you liked the article 🙌, spread the word and &lt;a href="https://twitter.com/KohlerChristian" rel="noopener noreferrer"&gt;follow me on Twitter&lt;/a&gt; for more posts on web technologies.&lt;/p&gt;

&lt;p&gt;Did you find typos 🤓? Please help improve the blogpost and open a pull request &lt;a href="https://github.com/ChristianKohler/homepage" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Papertown - GitHub Actions Submission</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Mon, 31 Aug 2020 13:50:46 +0000</pubDate>
      <link>https://dev.to/christiankohler/papertown-github-actions-submission-1a3c</link>
      <guid>https://dev.to/christiankohler/papertown-github-actions-submission-1a3c</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;The Papertown GitHub Action takes your personal markdown blog and syncs it with platforms like dev.to.&lt;/p&gt;

&lt;p&gt;Setup is simple and straight-forward. It only needs a master-id in the frontmatter and then automatically creates and updates you blog articles. &lt;/p&gt;

&lt;p&gt;I use it on my personal blog: &lt;a href="https://github.com/ChristianKohler/Homepage"&gt;https://github.com/ChristianKohler/Homepage&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more about Papertown read my blogpost linked below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Papertown Sync&lt;/span&gt;
        &lt;span class="s"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ChristianKohler/papertown-github-action@v1.0.5&lt;/span&gt;
        &lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;devto-api-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DEVTO_API_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ChristianKohler"&gt;
        ChristianKohler
      &lt;/a&gt; / &lt;a href="https://github.com/ChristianKohler/papertown-github-action"&gt;
        papertown-github-action
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Github Action for https://github.com/ChristianKohler/papertown
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Papertown Github Action&lt;/h1&gt;
&lt;p&gt;This action runs &lt;a href="https://github.com/ChristianKohler/papertown"&gt;https://github.com/ChristianKohler/papertown&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Papertown syncs you personal markdown blog with blog platforms like dev.to&lt;/p&gt;
&lt;h2&gt;
Inputs&lt;/h2&gt;
&lt;h3&gt;
devto-api-key (required)&lt;/h3&gt;
&lt;p&gt;See: &lt;a href="https://github.com/ChristianKohler/papertown"&gt;https://github.com/ChristianKohler/papertown&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
root-folder&lt;/h3&gt;
&lt;p&gt;See: &lt;a href="https://github.com/ChristianKohler/papertown"&gt;https://github.com/ChristianKohler/papertown&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
image-root-url-github&lt;/h3&gt;
&lt;p&gt;See: &lt;a href="https://github.com/ChristianKohler/papertown"&gt;https://github.com/ChristianKohler/papertown&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
dry-run&lt;/h3&gt;
&lt;p&gt;See: &lt;a href="https://github.com/ChristianKohler/papertown"&gt;https://github.com/ChristianKohler/papertown&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Example usage&lt;/h2&gt;
&lt;div class="highlight highlight-source-yaml"&gt;&lt;pre&gt; - &lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;Papertown Sync&lt;/span&gt;
        &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;ChristianKohler/papertown-github-action@v1.0.5&lt;/span&gt;
        &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
          &lt;span class="pl-ent"&gt;devto-api-key&lt;/span&gt;: &lt;span class="pl-s"&gt;${{ secrets.DEVTO_API_KEY }}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ChristianKohler/papertown-github-action"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;This GitHub actions uses the Papertown API.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/ChristianKohler/papertown"&gt;https://github.com/ChristianKohler/papertown&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blog post: &lt;a href="https://dev.to/christiankohler/introducing-papertown-1lb7"&gt;https://dev.to/christiankohler/introducing-papertown-1lb7&lt;/a&gt;&lt;/p&gt;

</description>
      <category>actionshackathon</category>
    </item>
    <item>
      <title>How to avoid Prop-drilling in Angular</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Sun, 02 Aug 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/how-to-avoid-prop-drilling-in-angular-5hmn</link>
      <guid>https://dev.to/christiankohler/how-to-avoid-prop-drilling-in-angular-5hmn</guid>
      <description>&lt;h1&gt;
  
  
  How to avoid Prop-drilling in Angular
&lt;/h1&gt;

&lt;p&gt;How to avoid Prop-drilling in Angular, or how to apply the idea of React Context to Angular.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Should I be interested?&lt;/li&gt;
&lt;li&gt;The „how“ and the „where“&lt;/li&gt;
&lt;li&gt;What is Prop Drilling?&lt;/li&gt;
&lt;li&gt;The problem of Prop Drilling by example&lt;/li&gt;
&lt;li&gt;How to avoid prop drilling&lt;/li&gt;
&lt;li&gt;Global state vs. Context-like state vs. Prop drilling&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tldr;
&lt;/h2&gt;

&lt;p&gt;If you prefer to use Input/Outputs in Angular you might find yourself writing a lot of boilerplate code to propagate events up the component hierarchy. As a solution you could add that state into a global service.&lt;/p&gt;

&lt;p&gt;A better approach is to put the state into a service provided by a component on the highest level necessary. This can be achieved by using the hierarchical dependency injection system of Angular.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I be interested?
&lt;/h2&gt;

&lt;p&gt;If you have all your state in a global store, this article is not for you. But..&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if you try to keep your state and logic as close as possible to where it is used&lt;/li&gt;
&lt;li&gt;and you often end up propagating state and actions through multiple components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;..then read on 👇&lt;/p&gt;

&lt;h2&gt;
  
  
  The „how“ and the „where“
&lt;/h2&gt;

&lt;p&gt;State management is a broad topic. To make it easier the topic can be divided into two parts. The "how" and the "where".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "how"&lt;/strong&gt; defines how to handle state. Are you using redux, mobx, ngrx or just a simple class with getter and setter? Is your data immutable or not?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "where"&lt;/strong&gt; defines whether you have multiple stores / states. For example a common pattern with redux is to have one global store. But it's possible to have local stores or feature stores. State can be within a single component or within a subtree of components.&lt;/p&gt;

&lt;p&gt;In this blogpost I don't cover the "how" but look into the "where". I try to keep the examples as simple as possible. That's why I don't use any "fancy" state management library, only pure typescript and a mutable data structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Prop Drilling?
&lt;/h2&gt;

&lt;p&gt;Kent C. Dodds wrote a good blog post about &lt;a href="https://kentcdodds.com/blog/prop-drilling"&gt;Prop Drilling&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Prop drilling is propagating or threading data through multiple levels of components. Since we don't use props in Angular we could also call it input/output drilling.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem of Prop Drilling by example
&lt;/h2&gt;

&lt;p&gt;Let's look at the problem by writing a small todo app.&lt;/p&gt;

&lt;p&gt;Disclaimer: The example is not complete. Some parts might be oversimplified or overengineered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple List
&lt;/h3&gt;

&lt;p&gt;We start with a simple "one-component" application with a list of todos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div *ngFor="let todo of todos"&amp;gt;
      {{ todo }}
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TodoList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Buy milk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pay bills&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bWj8URS9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/SimpleList.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bWj8URS9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/SimpleList.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a Filter
&lt;/h3&gt;

&lt;p&gt;Now we want to add a filter. Since we want to share our state we create a component called "Todos" which contains the state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BVcFHFEO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/WithFilter.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BVcFHFEO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/WithFilter.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;todo-filter [(filter)]="filter"&amp;gt;&amp;lt;/todo-filter&amp;gt;
    &amp;lt;todo-list [todos]="filteredTodos"&amp;gt;&amp;lt;/todo-list&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Todos&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Buy milk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;due&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;today&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pay bills&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;due&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tomorrow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;today&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;filteredTodos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// return filtered todos&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Add a TodoItem Component
&lt;/h3&gt;

&lt;p&gt;Now we want to replace the todo string in the TodoList component with a component. We create a "TodoItem" component for that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vXZ-nDMd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/WithTodoItem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vXZ-nDMd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/WithTodoItem.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;todo-item
      *ngFor="let todo of todos"
      [todo]="todo"
    &amp;gt;&amp;lt;/todo-item&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TodoList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;{{ todo.title }}&amp;lt;/div&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TodoItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Add a ToggleTodo Component
&lt;/h3&gt;

&lt;p&gt;Now we want to add another component within "TodoItem" called "ToggleTodo". This component should display a checkbox and call a method named "toggleTodo()" on the state.&lt;/p&gt;

&lt;p&gt;Note: For such a simple application this ToggleTodo component definitely is too much component splitting. I do it here to make the problem of prop drilling more visible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kAAWpLlP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/WithToggleItem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kAAWpLlP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/WithToggleItem.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * The toggle event is handled here
 */&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;todo-filter [(filter)]="filter"&amp;gt;&amp;lt;/todo-filter&amp;gt;
    &amp;lt;todo-list
      [todos]="filteredTodos"
      (toggle)="toggleTodo($event)"
    &amp;gt;
    &amp;lt;/todo-list&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Todos&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Buy milk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;due&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;today&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pay bills&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;due&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tomorrow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;today&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;filteredTodos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// return filtered todos&lt;/span&gt;

  &lt;span class="nx"&gt;toggleTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// handle toggle&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * TodoList has to pass the event on
 */&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;todo-item
      *ngFor="let todo of todos"
      [todo]="todo"
      (toggle)="toggle.emit($event)"
    &amp;gt;&amp;lt;/todo-item&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TodoList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * TodoItem has to pass the event on
 */&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;toggle-todo
      [todo]="todo"
      (toggle)="toggle.emit($event)"
    &amp;gt;&amp;lt;/toggle-todo&amp;gt;

    &amp;lt;span&amp;gt;
      {{ todo.title }}
    &amp;lt;/span&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TodoItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * The event starts here
 */&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toggle-todo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;input
      type="checkbox"
      [checked]="todo.done"
      (change)="toggle.emit(todo.id)"
    /&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ToggleTodo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, this leads to a lot of boilerplate since we have to emit the toggle event from component to component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YAv_4KO1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/PropDrilling.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YAv_4KO1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/PropDrilling.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the problem of prop drilling. To set the state from the ToggleTodo we have to go through TodoItem and TodoList.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to avoid prop drilling
&lt;/h2&gt;

&lt;p&gt;React has a nice solution for that problem. It's called context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reactjs.org/docs/context.html"&gt;https://reactjs.org/docs/context.html&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Context provides a way to pass data through the component tree without having to pass props down manually at every level.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Angular doesn't have a functionality like context but we can use its powerful dependency injection system to achieve the same goal.&lt;/p&gt;

&lt;p&gt;Note that React's context and Angular's DI are fundamentally different in how the work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular's hierarchical dependency injection system
&lt;/h3&gt;

&lt;p&gt;Angular comes with a hierarchical dependency injection system. I've &lt;a href="https://christiankohler.net/angular-dependency-injection-infographic"&gt;created a infographic poster&lt;/a&gt; to visualise that system.&lt;/p&gt;

&lt;p&gt;What you need to know for know is that every component has its own injector and that child components can access the services from further up in the hierachy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Todo App with context-like state
&lt;/h3&gt;

&lt;p&gt;So let's use the power of Angular's DI system to create a context for our state.&lt;/p&gt;

&lt;p&gt;We are going to provide the state in the Todos component and inject it in the ToggleTodo component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jdf1AM0a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/ProvideInject.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jdf1AM0a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-08-02-propdrilling/images/ProvideInject.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Create the state service
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TodoState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Buy milk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pay bills&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;filteredTodos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// return filtered todos&lt;/span&gt;

  &lt;span class="nx"&gt;toggleTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// handle toggle&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Provide the TodoState in the Todos component
 */&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;todo-filter
      [(filter)]="todoState.filter"
    &amp;gt;&amp;lt;/todo-filter&amp;gt;
    &amp;lt;todo-list
      [todos]="todoState.filteredTodos"
    &amp;gt;&amp;lt;/todo-list&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TodoState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;--- provide it here&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Todos&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;todoState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TodoState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Use the TodoState in the ToggleTodo component
 */&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toggle-todo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;input
      type="checkbox"
      [checked]="todo.done"
      (change)="todoState.toggleTodo(todo.id)"
    /&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ToggleTodo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Inject the TodoState here
   */&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;todoState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TodoState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Introducing the TodoState service in this example reduced the boilerplate of propagating the toggle event from component to component. It's a nice way to reduce boilerplate without the need to throw the state into the "global bucket".&lt;/p&gt;

&lt;h2&gt;
  
  
  Global state vs. Context-like state vs. Prop drilling
&lt;/h2&gt;

&lt;p&gt;I think there is a place for all concepts, even in the same application.&lt;/p&gt;

&lt;p&gt;Personally I try to start with Inputs/Outputs. It is easier to follow and refactor (like a pure function) and change detection is also easier to understand.&lt;/p&gt;

&lt;p&gt;When I feel that the added boilerplates negates the benefits of Inputs/Outputs I switch to context-like state services. This reduces boilerplate but still keeps the state as close as possible to where it is used.&lt;/p&gt;

&lt;p&gt;Some state is global. One common example is the selected theme. In this case I'd use a global service like this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ThemeProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;selectedTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;selectLightTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;selectDarkTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You might ask yourself why not make everything global. In small applications like the todo example from this post, putting the state into a global service is fine. But the more complex you application is, the more important it is to keep your logic and state as close as possible to where you use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this blog post you learned that there is not just global or local state in Angular. With the power of the hierarchical DI system we can provide a state service in the the exact (highest) place in the component tree where we need it to be. This is often a nice compromise between having a local state and making it globally available.&lt;/p&gt;

&lt;p&gt;If you liked the article 🙌, spread the word and &lt;a href="https://twitter.com/KohlerChristian"&gt;follow me on Twitter&lt;/a&gt; for more posts on web technologies.&lt;/p&gt;

&lt;p&gt;Did you find typos 🤓? Please help improve the blogpost and open an issue &lt;a href="https://github.com/ChristianKohler/homepage"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>react</category>
      <category>state</category>
    </item>
    <item>
      <title>It’s a trap - The biggest pitfall of String.prototype.replace()</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Tue, 30 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/it-s-a-trap-the-biggest-pitfall-of-string-prototype-replace-57kp</link>
      <guid>https://dev.to/christiankohler/it-s-a-trap-the-biggest-pitfall-of-string-prototype-replace-57kp</guid>
      <description>&lt;p&gt;Replacing a substring is a very common task. It should also be a very simple one but actually it isn’t.&lt;/p&gt;

&lt;p&gt;In this short post I will show you the biggest pitfall, how to avoid it and how a new JavaScript feature is going to improve the situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;String.prototype.replace&lt;/code&gt; only replaces the first occurrence when used with a string as pattern argument. A global regex can be used to replace all occurrences instead.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;String.prototype.replaceAll&lt;/code&gt; will fix that and also replace all occurrences with a string pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we want to achieve
&lt;/h2&gt;

&lt;p&gt;We want to replace 🌧 with 🌈 in this weather forecast which is basically a string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Input:  "Mon: 🌧, Tue: 🌧, Wed 🌧"&lt;/span&gt;
&lt;span class="c1"&gt;// Result: "Mon: 🌈, Tue: 🌈, Wed 🌈"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Naive approach (the pitfall 🚨)
&lt;/h2&gt;

&lt;p&gt;The first approach most (newbie) developers would use is &lt;code&gt;String.prototype.replace&lt;/code&gt; with a substring argument.&lt;/p&gt;

&lt;p&gt;replace takes two arguments. The first argument can be either a substring or a regex pattern, the second argument is the replacement substring.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mon: 🌧, Tue: 🌧, Wed 🌧&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌧&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌈&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The result would look like this. Only the first occurrence would be replaced.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Result: "Mon: 🌈, Tue: 🌧, Wed 🌧"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;String.prototype.replace&lt;/code&gt; only replaces the first occurrence when used with a substring argument.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The pitfall is that you might test your code for a single replacement but it then fails when the string has more then one occurrence.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I said that would be the approach taken by newbies but honestly I still find myself walking in this trap from time to time.&lt;/p&gt;

&lt;p&gt;Now let’s have a look how you can replace all occurrences in a string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working approach (with regex)
&lt;/h2&gt;

&lt;p&gt;When using a global regex pattern instead of a simple substring for the first argument the &lt;code&gt;String.prototype.replace&lt;/code&gt; function replaces all occurrences.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Input:  "Mon: 🌧, Tue: 🌧, Wed 🌧"&lt;/span&gt;
&lt;span class="c1"&gt;// Result: "Mon: 🌈, Tue: 🌈, Wed 🌈"&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mon: 🌧, Tue: 🌧, Wed 🌧&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/🌧/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌈&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This approach works, is supported by all browsers and is fast. But it’s harder to read and you have to remember to use the regex pattern if you want to replace all occurrences.&lt;/p&gt;

&lt;h2&gt;
  
  
  New approach (with replaceAll)
&lt;/h2&gt;

&lt;p&gt;For many use cases a regex is not required and just makes the code a little bit harder to read. That’s were the new &lt;code&gt;String.prototype.replaceAll&lt;/code&gt; comes in. ReplaceAll is a stage 4 proposal but is already supported by most modern browsers.&lt;/p&gt;

&lt;p&gt;It allows you to replace all occurrences with the substring argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Input:  "Mon: 🌧, Tue: 🌧, Wed 🌧"&lt;/span&gt;
&lt;span class="c1"&gt;// Result: "Mon: 🌈, Tue: 🌈, Wed 🌈"&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mon: 🌧, Tue: 🌧, Wed 🌧&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌧&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌈&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  When to use which approach?
&lt;/h2&gt;

&lt;p&gt;There are a few things to consider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compatibility&lt;/strong&gt;. Check if your targets support &lt;code&gt;String.prototype.replaceAll&lt;/code&gt; directly or if your toolchain (e.g. babel) polyfills it. You can check the status here: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;. Both functions are very fast for short strings. If you don’t plan to parse a full book the difference is neglectable.&lt;/p&gt;

&lt;p&gt;Here are the results of the benchmark in Safari. Those results differ depending on your browser and machine. They might also change with future browser versions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/🌧/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌈&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 130,000,000 ops/s&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌧&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌈&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//   6,300,000 ops/s&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/🌧/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🌈&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//   1,600,000 ops/s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I came up with two simple rules which makes it easier to decide what to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule I
&lt;/h3&gt;

&lt;p&gt;Always use replaceAll if your environment supports it. You can use it with the string pattern or the regex pattern and you avoid the pitfall of replacing only the first occurrence. This is imho how replace should work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule II
&lt;/h3&gt;

&lt;p&gt;If you have to use replace, avoid the string pattern and always use the regex patten. You could even add a linting rule to avoid the pitfall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;If you reached the end of the blogpost, congratulations on reading a full blogpost about a single JavaScript function 😉&lt;/p&gt;

&lt;p&gt;I hope I could show you the problem with replace and how to avoid it.&lt;/p&gt;

&lt;p&gt;If you liked the article 🙌, spread the word and &lt;a href="https://twitter.com/KohlerChristian"&gt;follow me on Twitter&lt;/a&gt; for more posts on web technologies.&lt;/p&gt;

&lt;p&gt;Did you find typos 🤓? Please help improve the blogpost and open an issue &lt;a href="https://github.com/ChristianKohler/homepage"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tc39/proposal-string-replaceall"&gt;GitHub - tc39/proposal-string-replaceall: ECMAScript proposal: String.prototype.replaceAll&lt;/a&gt;&lt;br&gt;
&lt;a href="https://v8.dev/features/string-replaceall"&gt;String.prototype.replaceAll · V8&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.string.replace-all.js"&gt;core-js/esnext.string.replace-all.js at master · zloirock/core-js · GitHub&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Lessons learned from building a Grid List in React Native</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Fri, 05 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/lessons-learned-from-building-a-grid-list-in-react-native-ckn</link>
      <guid>https://dev.to/christiankohler/lessons-learned-from-building-a-grid-list-in-react-native-ckn</guid>
      <description>&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;Use the power of flexbox and aspectRatio to build a dynamic grid which works for all screens and orientations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fgoal.jpg" 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fgoal.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We want to build a photo grid which is easy to use, supports both portrait and landscape orientation and has configurable columns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flatlist
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://reactnative.dev/docs/flatlist" rel="noopener noreferrer"&gt;https://reactnative.dev/docs/flatlist&lt;/a&gt; makes it really easy to implement a photo grid. It handles all the hard work of big lists and comes with build in support for columns. We use Flatlist to build our grid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Flatlist Example
&lt;/h2&gt;

&lt;p&gt;This is a full app example how to use a Flatlist. &lt;a href="https://snack.expo.io/@christiankohler/flatlist_blog_simple_example" rel="noopener noreferrer"&gt;Try it out on expo.io&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FlatList&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;picsumImages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://placeimg.com/640/360/any&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setImages&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;picsumImages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FlatList&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;renderItem&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;renderItem&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We only need to provide those attributes to make it work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data -&amp;gt; array of items we want to iterate over&lt;/li&gt;
&lt;li&gt;renderItem -&amp;gt; the component we want to render per item&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a list of images with a height of 100 and stretched to full width.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fsimple_example.jpg" 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fsimple_example.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Flatlist with columns
&lt;/h2&gt;

&lt;p&gt;To create a grid from the previous example is straight forward. We only have to define the number of columns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FlatList&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;renderItem&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;renderItem&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;numColumns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 If you coded along you might have noticed that the screen is now white and no images are displayed. The is because we didn't define a width for the individual items.&lt;/p&gt;

&lt;p&gt;Let's just add a fixed width for now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a grid. But since the width is fixed to 100 the last image is clipped. &lt;a href="https://snack.expo.io/@christiankohler/flatlist_blog_clipped" rel="noopener noreferrer"&gt;Open in snack.expo.io&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fclipped.jpg" 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fclipped.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set tile size with dimension api
&lt;/h2&gt;

&lt;p&gt;One approach to fix the clipping problem is to read the width of the screen and then calculate the the tile width:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dimensions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;screenWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;window&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tileSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screenWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;numColumns&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tileSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tileSize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a nice photo grid that works. &lt;a href="https://snack.expo.io/@christiankohler/flatlist_blog_dimension_api" rel="noopener noreferrer"&gt;Here is a working example&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fdimension_api.jpg" 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fdimension_api.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I don't like about the solution is that I have to calculate the tile size manually. With my web background I always prefer a fluid solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set tile size with flexbox
&lt;/h2&gt;

&lt;p&gt;React Native comes with a great support for flexbox. So let's get rid of the dimension api and replace it with flexbox.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So my first approach gives me this result. &lt;a href="https://snack.expo.io/@christiankohler/flatlist_blog_flex_1" rel="noopener noreferrer"&gt;Live example&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fflex1.jpg" 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fflex1.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two problems here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The height is fixed which breaks the aspect ratio of 1&lt;/li&gt;
&lt;li&gt;If the number of items can not be divided by the number of columns the bottom items are stretched&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Introducing the aspect ratio
&lt;/h3&gt;

&lt;p&gt;The aspect ratio problem is easy to fix. Just remove the height property and define the aspectRatio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Faspect_ratio.jpg" 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Faspect_ratio.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://snack.expo.io/@christiankohler/flatlist_blog_aspect_ratio" rel="noopener noreferrer"&gt;Live example&lt;/a&gt; (Make sure you run it in the simulator since the web view doesn't support the aspectRatio property)&lt;/p&gt;

&lt;h3&gt;
  
  
  Using flex with 1/numColumns
&lt;/h3&gt;

&lt;p&gt;There are at least two ways how to fix the stretched bottom items issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add fake empty items to fill it up&lt;/li&gt;
&lt;li&gt;Use flex 1/numColumns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I want to focus on the flex/numColumns solution.&lt;/p&gt;

&lt;p&gt;It's actually pretty simple. Just set the flex to 1/numColumns&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;numColumns&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fnum_columns.jpg" 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-06-05-react-native-grid%2Fimages%2Fnum_columns.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://snack.expo.io/@christiankohler/flatlist_blog_num_columns" rel="noopener noreferrer"&gt;Here is a live example&lt;/a&gt; (Make sure you run it in the simulator since the web view doesn't support the aspectRatio property)&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Flatlist makes it very easy to build a photo grid with React Native. flexbox helps to create fluid layouts without the need to know the exact dimensions of the screen.&lt;/p&gt;

&lt;p&gt;Creating a grid is a very common problem and I hope I could show you an easy and robust way how to do that.&lt;/p&gt;

&lt;p&gt;If you liked the article 🙌, spread the word and &lt;a href="https://twitter.com/KohlerChristian" rel="noopener noreferrer"&gt;follow me on Twitter&lt;/a&gt; for more posts on React Native, Angular and web technologies.&lt;/p&gt;

&lt;p&gt;Did you find typos 🤓? Please help improve the blogpost and open an issue &lt;a href="https://github.com/ChristianKohler/homepage" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FlatList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dimensions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;picsumImages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://placeimg.com/640/360/any&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderItem&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt;
      &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;numColumns&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setImages&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;picsumImages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FlatList&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;renderItem&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;renderItem&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;numColumns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;numColumns&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>react</category>
      <category>reactnative</category>
      <category>flatlist</category>
    </item>
    <item>
      <title>Reactive Angular with ngrx/component</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Sun, 22 Mar 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/reactive-angular-with-ngrx-component-2oig</link>
      <guid>https://dev.to/christiankohler/reactive-angular-with-ngrx-component-2oig</guid>
      <description>&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;Angular change detection relies on Zone.js which works well in most situations but is hard to debug and might lead to performance problems.&lt;/p&gt;

&lt;p&gt;With the rise of reactive programming in Angular we might not need Zone.js at all and instead trigger change detection whenever the view state changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/Michael_Hladky"&gt;Michael Hladky&lt;/a&gt; and the ngrx team are working on a library named ngrx/component to make it easier to trigger change detection with observables.&lt;/p&gt;

&lt;p&gt;In this article we look at how this new library helps us write maintainable code without Zone.js&lt;/p&gt;

&lt;h2&gt;
  
  
  TOC
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;🤔 What's wrong with Zone.js?&lt;/li&gt;
&lt;li&gt;🔦 When should we run change detection?&lt;/li&gt;
&lt;li&gt;🚲 Zone less approach in Angular&lt;/li&gt;
&lt;li&gt;💡 Change detection in a reactive application&lt;/li&gt;
&lt;li&gt;🚧 Async Pipe&lt;/li&gt;
&lt;li&gt;🚀 ngrx PushPipe and let directive&lt;/li&gt;
&lt;li&gt;❓ Should I now rewrite my code?&lt;/li&gt;
&lt;li&gt;👩‍🚀 Be ready for a reactive (zone-less) future&lt;/li&gt;
&lt;li&gt;📚 Resources&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's wrong with Zone.js? 🤔
&lt;/h2&gt;

&lt;p&gt;Most Angular developers learn about Zone.js when they run into change detection issues. Zone.js doesn't do change detection but triggers it after async operations were completed. One good example is a &lt;code&gt;setTimeout()&lt;/code&gt; callback after which Zone.js triggers change detection.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In general Zone.js just works and helps Angular developers write less code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But every design decision has its pros and cons.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problems withs Zone.js are
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;it's hard to debug&lt;/li&gt;
&lt;li&gt;it might lead to performance issues&lt;/li&gt;
&lt;li&gt;no native async await support (Typescript target: ES2017 or higher)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Zones.js allows for a mix of imperative and reactive code
&lt;/h3&gt;

&lt;p&gt;I often see how part of an Angular application is written in a imperative way and part of it reactive. It's not always a bad thing but I feel that the mix often makes it harder to read code.&lt;/p&gt;

&lt;p&gt;In 2019 Rob Wormald talked about Zone.js in his keynote. He said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Zones are great until they are not.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Watch the full keynote here: &lt;a href="https://www.youtube.com/watch?v=-32nh-pGXaU&amp;amp;feature=youtu.be&amp;amp;t=19m10s"&gt;Rob Wormald - Keynote - What's New and Coming in Angular | AngularUP 2019&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When should we run change detection? 🔦
&lt;/h2&gt;

&lt;p&gt;With Zone.js Angular change detection magically works for almost any scenario. To make it work, it assumes that whenever you have an event like a click event, the state changed and the view has to be rerendered.&lt;/p&gt;

&lt;p&gt;Let's take that simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;Count is {{ count }}&amp;lt;/div&amp;gt;
    &amp;lt;button (click)="increment()"&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;button (click)="noEffect()"&amp;gt;Dummy Button&amp;lt;/button&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// triggers change detection&lt;/span&gt;
  &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// also triggers change detection&lt;/span&gt;
  &lt;span class="nx"&gt;noEffect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this example Angular needs to trigger change detection after the &lt;code&gt;increment&lt;/code&gt; method because we want to update our view. But we don't need to trigger change detection after we call the &lt;code&gt;noEffect&lt;/code&gt; method&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ideally we only trigger change detection when the view state changes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The React way
&lt;/h3&gt;

&lt;p&gt;In React you change the state explicitly which then triggers a rerender. In the following example the setCount sets part of the state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;You clicked &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; times&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This approach is easy to understand and to debug.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zone less approach in Angular 🚲
&lt;/h2&gt;

&lt;p&gt;So let's get rid of Zone.js and let's try to make change detection more predictable and easier to debug.&lt;/p&gt;

&lt;p&gt;We can easily disable Zone.js in Angular by setting ngZone to "noop":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;platformBrowserDynamic&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;bootstrapModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ngZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since change detection is not triggered anymore by Zone.js we need to trigger it manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;cdRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChangeDetectorRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cdRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detectChanges&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;noEffect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This approach works but involves a lot of manual work and pollutes our code with change detection logic. Also due to the imperative nature of that code it can become very difficult to understand what triggered change detection the more complex the code gets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Change detection in a reactive application 💡
&lt;/h2&gt;

&lt;p&gt;In a reactive application we know exactly when a change happens. Every time a new value is emitted in a observable. And whenever a change happens we can trigger change detection. This means we don't need to rely on Zone.js to trigger change detection.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When every view state is an observable, we know exactly when to trigger change detection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice how this is a very similar to Reacts approach?&lt;/p&gt;

&lt;h2&gt;
  
  
  Async Pipe 🚧
&lt;/h2&gt;

&lt;p&gt;With Zone.js deactivated the first idea for a reactive approach would be to use Angulars async pipe to trigger change detection when a new value is emitted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;Count is {{ count$ | async }}&amp;lt;/div&amp;gt;
    &amp;lt;button (click)="increment()"&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;button (click)="noEffect()"&amp;gt;Dummy Button&amp;lt;/button&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;increment$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;count$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;increment$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;startWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;increment$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Unfortunately that &lt;strong&gt;doesn't trigger change detection&lt;/strong&gt; since the async pipe only runs markForChecked on the components ChangeDetectorRef.&lt;/p&gt;

&lt;p&gt;So we need an async pipe which can trigger change detection. Luckily there is a library &lt;a href="https://github.com/ngrx/platform/pull/2046"&gt;coming up&lt;/a&gt; for exactly that.&lt;/p&gt;

&lt;h2&gt;
  
  
  ngrx PushPipe and let directive 🚀
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/Michael_Hladky"&gt;Michael Hladky&lt;/a&gt; and the ngrx team are working on a new library named ngrx/component. It's not released yet but we can already try it out. It's a collection of tools to make it easier to write reactive angular components.&lt;/p&gt;

&lt;p&gt;Or as &lt;a href="https://twitter.com/Michael_Hladky"&gt;Michael Hladky&lt;/a&gt; says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The idea of ngrx/component is building applications where the word subscribe is not present."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote class="twitter-tweet"&gt;
&lt;p&gt;In &lt;a href="https://twitter.com/hashtag/rxjs?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#rxjs&lt;/a&gt; .subscribe() is where reactive programming ends&lt;/p&gt;— Michael Rx Hladky (&lt;a class="comment-mentioned-user" href="https://dev.to/michael_hladky"&gt;@michael_hladky&lt;/a&gt;
) &lt;a href="https://twitter.com/Michael_Hladky/status/1180316203937681410?ref_src=twsrc%5Etfw"&gt;October 5, 2019&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;Currently it consists of two features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PushPipe, a drop in replacement for the async pipe&lt;/li&gt;
&lt;li&gt;Let directive, an enhancement/alternative to ngIf for binding observable values&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  PushPipe
&lt;/h3&gt;

&lt;p&gt;The PushPipe is a drop in replacement for the async pipe. &lt;strong&gt;It triggers change detection&lt;/strong&gt; in a zone-less context or triggers &lt;code&gt;markForCheck&lt;/code&gt; like the async pipe in a zone context.&lt;/p&gt;

&lt;h4&gt;
  
  
  Usage
&lt;/h4&gt;

&lt;p&gt;Replace the async pipe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;{{ count$ | async }}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;with the ngrx PushPipe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;{{ count$ | ngrxPush }}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://stackblitz.com/edit/blog-pushpipe-example?file=src/app/app.module.ts"&gt;Here is a Stackblitz example&lt;/a&gt; with the counter and the PushPipe. Try it out and replace the ngrxPush with async to see how it affects change detection. Also check the &lt;a href="https://github.com/ngrx/platform/blob/680f77fbe38c8086f9684f9033d7722b14a78025/projects/ngrx.io/content/guide/component/push.md"&gt;PushPipe documentation&lt;/a&gt; for more examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let Directive
&lt;/h3&gt;

&lt;p&gt;Another great addition to make it easier to build reactive Angular components is the let-directive.&lt;/p&gt;

&lt;p&gt;The let directive is similar to *ngIf but handles 0 values and supports zone-less the same way the PushPipe does. That means it also triggers change detection when a new value is emitted.&lt;/p&gt;

&lt;p&gt;The let-directive does not provide the show/hide funtionality which is imho a good design decision. The let-directive binds to observable values and the ngIf can then be used for the show/hide logic. It's a nice seperation of concerns.&lt;/p&gt;

&lt;h4&gt;
  
  
  Usage
&lt;/h4&gt;

&lt;p&gt;Replace the *ngIf:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"count$ | async as count"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Count is {{ count }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;width *ngrxLet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;*ngrxLet=&lt;/span&gt;&lt;span class="s"&gt;"count$ as count"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Count is {{ count }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://stackblitz.com/edit/blog-pushpipe-example?file=src/app/app.module.ts"&gt;Here is a Stackblitz example&lt;/a&gt; with the counter and the let directive. Try it out and replace the ngrxLet with ngIf to see how it affects change detection. Also check the &lt;a href="https://github.com/ngrx/platform/blob/680f77fbe38c8086f9684f9033d7722b14a78025/projects/ngrx.io/content/guide/component/let.md"&gt;Let directive documentation&lt;/a&gt; for more examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  How PushPipe and the let-directive improve performance?
&lt;/h3&gt;

&lt;p&gt;PushPipe and the let-directive improve performance in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only trigger change detection when a new observable value is emitted&lt;/li&gt;
&lt;li&gt;Trigger change detection only for the component and its children&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Should I now rewrite my code? ❓
&lt;/h2&gt;

&lt;p&gt;Short answer: &lt;strong&gt;Keep Zone.js for now but start using PushPipe and let-directive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What I showed you in the examples is a zone-less full reactive Angular example. You don't have to go zone-less to make your application more reactive. Let's look at the different motivations behind using ngrx/component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Motivation "Reactive Angular"
&lt;/h3&gt;

&lt;p&gt;If you don't have any problems with Zone.js or performance I would keep Zone.js turned on. Focus on writing reactive code. Ngrx/component makes it easier with features like the let-directive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Motivation "Zone-less Angular"
&lt;/h3&gt;

&lt;p&gt;You want to get rid of Zone.js and improve performance by only rerendering the current component and its children. A good use case would be Angular Elements. It would simplify the usage of Angular Elements and reduce the bundle size. Ngrx/component is the easiest way to go Zone-less. Only replace the async pipe with the new PushPipe.&lt;/p&gt;

&lt;p&gt;🧨 If you turn off Zone.js, some 3rd party libraries might not work anymore. For example, Angular Material select doesn't work out of the box without Zone.js. Try it out and disable Zone.js &lt;a href="https://stackblitz.com/angular/lymrvyjbndk?file=src%2Fmain.ts"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✨ Start using PushPipe and the let-directive
&lt;/h3&gt;

&lt;p&gt;👉 PushPipe and the let directive are not released yet (as of 23 March 2020). I will update this post after the release.&lt;/p&gt;

&lt;p&gt;Since both, PushPipe and let-directive, work with Zone.js enabled you can &lt;strong&gt;use them as a drop in replacement today&lt;/strong&gt;. When you ever decide to turn off Zone.js it just works (which is not the case with the async pipe).&lt;/p&gt;

&lt;p&gt;The let-directive is also more than just a zone-less ngIf. It seperates the show/hide functionality from binding to observable values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be ready for a reactive (zone-less) future 👩‍🚀
&lt;/h2&gt;

&lt;p&gt;Angular makes it easy to write reactive code. Default libraries like the router and the http client provide observables. Ngrx builds on observables. With ngrx/component it gets even easier to write full reactive code. Full reactive code makes it also much easier to know when to trigger change detection and to write zone-less code.&lt;/p&gt;

&lt;p&gt;If you are a developer, embrace RxJS and write your code in a reactive way. It will make it easier for you to use new features like the PushPipe.&lt;/p&gt;

&lt;p&gt;If you are a 3rd party library maintainer make sure your library works in a zone-less environment.&lt;/p&gt;

&lt;p&gt;If you liked the article 🙌, spread the word and &lt;a href="https://twitter.com/KohlerChristian"&gt;follow me on Twitter&lt;/a&gt; for more posts on Angular and web technologies.&lt;/p&gt;

&lt;p&gt;Huge thanks to &lt;a href="https://twitter.com/Michael_Hladky"&gt;Michael Hladky&lt;/a&gt; for his inputs and reviews, and the work he put into ngrx/component.&lt;/p&gt;

&lt;p&gt;Did you find typos 🤓? Please help improve the blogpost and open an issue &lt;a href="https://github.com/ChristianKohler/homepage"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources 📚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ngrx/platform/issues/2441"&gt;@ngrx/component roadmap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackmd.io/42oAMrzYReizA65AwQ7ZlQ"&gt;Design Doc - Coalescing of Change Detection - HackMD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackmd.io/Uus0vFu3RmWRVGgmtzuUWQ?view"&gt;Design Doc - Push Pipe - HackMD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackmd.io/8_3rp0A7RweSYJiulsifbQ?view"&gt;Design Doc - Let Directive - HackMD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ngrx/platform/pull/2046"&gt;Ngrx component setup by BioPhoton&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ngrx/component-builds"&gt;GitHub - ngrx/component-builds: @ngrx/component nightly builds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ngrx/platform/blob/680f77fbe38c8086f9684f9033d7722b14a78025/projects/ngrx.io/content/guide/component/let.md"&gt;platform/let.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ngrx/platform/blob/680f77fbe38c8086f9684f9033d7722b14a78025/projects/ngrx.io/content/guide/component/push.md"&gt;platform/push.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>rxjs</category>
      <category>ngrx</category>
    </item>
    <item>
      <title>How to use ResizeObserver with Angular</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Mon, 24 Feb 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/how-to-use-resizeobserver-with-angular-9l5</link>
      <guid>https://dev.to/christiankohler/how-to-use-resizeobserver-with-angular-9l5</guid>
      <description>&lt;h1&gt;
  
  
  tl;dr
&lt;/h1&gt;

&lt;p&gt;Sometimes we need to execute JavaScript when an element is resized.&lt;/p&gt;

&lt;p&gt;Current solutions are &lt;strong&gt;based on the viewport dimension&lt;/strong&gt;, &lt;strong&gt;not&lt;/strong&gt; on &lt;strong&gt;element dimensions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;ResizeObserver is a new API which allows us to react to element resizing. &lt;/p&gt;

&lt;p&gt;There are a few steps required to use it properly with Angular. You have to make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;to unobserve on destroy&lt;/li&gt;
&lt;li&gt;that change detection is triggered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found it to cumbersome to do it on every component. That's why I've created a library to simplify the usage with Angular. 🚀&lt;/p&gt;

&lt;h1&gt;
  
  
  ✨React to element dimension changes
&lt;/h1&gt;

&lt;p&gt;Many changes in screen size or element size can be handled with pure CSS. But sometimes we &lt;strong&gt;need to know when an element is resized&lt;/strong&gt; and execute some logic in JavaScript.&lt;/p&gt;

&lt;p&gt;This is usually implemented with either &lt;code&gt;window.onchange&lt;/code&gt; or &lt;code&gt;matchMedia&lt;/code&gt;. Both solutions are based on the viewport dimension, not the element dimension.&lt;/p&gt;

&lt;p&gt;ResizeObserver &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver" rel="noopener noreferrer"&gt;ResizeObserver - Web APIs | MDN&lt;/a&gt; is a new API to solve exactly this problem. In this article we will have a look at how it works and how we can use this new API together with Angular.&lt;/p&gt;

&lt;p&gt;Let's start with why we need a new API.&lt;/p&gt;

&lt;h1&gt;
  
  
  💣 What's the problem with window.onchange?
&lt;/h1&gt;

&lt;p&gt;We are only interested in events where our component changes its width. Unfortunately window.onchange sometimes fires &lt;strong&gt;too often&lt;/strong&gt; or &lt;strong&gt;not at all&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  onchange fires too often
&lt;/h2&gt;

&lt;p&gt;This happens when the viewport changes but our component doesn't. Do you see the first window.onresize (colored in red)? We are not interested in this event. Running to much code on every onresize could lead to performance problems.&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/images%2Fonresize-fires-too-much.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/images%2Fonresize-fires-too-much.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  onchange doesn't fire (but should)
&lt;/h2&gt;

&lt;p&gt;This happens when the viewport doesn't change but the elements within change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New elements are added dynamically&lt;/li&gt;
&lt;li&gt;Elements are collapsed or expanded (e.g. Sidebar)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the graphic below the viewport doesn't change and the sidebar gets expanded. The ResizeObserver triggers but the window.onresize doesn't.&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/images%2Fonresize-doesnt-fire.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/images%2Fonresize-doesnt-fire.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know why we need the new ResizeObserver Api we will take a closer look at it.&lt;/p&gt;

&lt;h1&gt;
  
  
  🚀 ResizeObserver in a nutshell
&lt;/h1&gt;

&lt;p&gt;Here is an example on how to use ResizeObserver to subscribe to a resize event of an element.&lt;/p&gt;

&lt;p&gt;You can observe multiple elements with one ResizeObserver. That's why we have an array of entries.&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResizeObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.my-element&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This is how an entry looks like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;_div_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"contentRect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"top"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bottom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"left"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;Since we subscribed to an observer, we need to unsubscribe as well:&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.my-element&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create observer&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResizeObserver&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

&lt;span class="c1"&gt;// Add element (observe)&lt;/span&gt;
&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Remove element (unobserve)&lt;/span&gt;
&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unobserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myEl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;That's ResizeObserver in a nutshell. For a full overview of what you can do with ResizeObserver, check out &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver" rel="noopener noreferrer"&gt;ResizeObserver - Web APIs | MDN&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  🏁 Status ResizeObserver
&lt;/h1&gt;

&lt;p&gt;At the time of writing (Feb 2020), ResizeObserver is a EditorsDraft &lt;a href="https://drafts.csswg.org/resize-observer-1/" rel="noopener noreferrer"&gt;Resize Observer&lt;/a&gt;. This means it is still in a very early phase &lt;a href="https://www.w3.org/2015/Process-20150901/#maturity-levels" rel="noopener noreferrer"&gt;World Wide Web Consortium Process Document&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chrome and Firefox support ResizeObserver, Edge and Safari don't. A ponyfill is available.&lt;/p&gt;

&lt;h1&gt;
  
  
  🛠 How to use it with Angular
&lt;/h1&gt;

&lt;p&gt;Let's create a component which displays its width.&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/images%2Fcode_example.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/images%2Fcode_example.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1: Create the component
&lt;/h2&gt;

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

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ width }}px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  2: Add Observer
&lt;/h2&gt;

&lt;p&gt;Now let's observe the nativeElement of our component and log the current width. Works like a charm (in Chrome and Firefox 😉)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResizeObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;contentRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  3: Trigger change detection
&lt;/h2&gt;

&lt;p&gt;If you are following this example you may have tried to bind the width directly to the class property. Unfortunately the template is not rerendered and keeps the initial value.&lt;/p&gt;

&lt;p&gt;The reason is that Angular has monkey-patched most of the events but not (yet) ResizeObserver. This means that this callback runs outside of the zone.&lt;/p&gt;

&lt;p&gt;We can easily fix that by manually running it in the zone.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NgZone&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResizeObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;contentRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  4: Unobserve on destroy
&lt;/h2&gt;

&lt;p&gt;To prevent memory leaks and to avoid unexpected behaviour we should unobserve on destroy:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NgZone&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResizeObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;contentRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnDestroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unobserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Want to try it out? &lt;a href="https://stackblitz.com/edit/angular-resize-observer-example?file=src%2Fapp%2Fapp.module.ts" rel="noopener noreferrer"&gt;Here is a live example&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5: Protip: Create a stream with RxJS
&lt;/h2&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;width$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NgZone&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResizeObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;contentRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnDestroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unobserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Follow me on 🐦 &lt;a href="https://twitter.com/KohlerChristian" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; for more blogposts about Angular and web technologies&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  ☀️ Use ng-resize-observer to simplify the usage of ResizeObserver
&lt;/h1&gt;

&lt;p&gt;💻 &lt;a href="https://github.com/ChristianKohler/ng-resize-observer" rel="noopener noreferrer"&gt;https://github.com/ChristianKohler/ng-resize-observer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📦 &lt;a href="https://www.npmjs.com/package/ng-resize-observer" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/ng-resize-observer&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;ng-resize-observer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Import and use the providers&lt;/li&gt;
&lt;li&gt;Inject the NgResizeObserver stream&lt;/li&gt;
&lt;/ol&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ngResizeObserverProviders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;NgResizeObserver&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ng-resize-observer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ width$ | async }} px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;ngResizeObserverProviders&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;width$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resize$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;resize$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NgResizeObserver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NgResizeObserver&lt;/strong&gt; is created per component and will automatically unsubscribe when the component is destroyed. It's a RxJS observable and you can use all operators with it.&lt;/p&gt;

&lt;p&gt;Want to try it out? &lt;a href="https://stackblitz.com/edit/ng-resize-observer-simple-example" rel="noopener noreferrer"&gt;Here is a live example on Stackblitz&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Make the web resizable 🙌
&lt;/h1&gt;

&lt;p&gt;ResizeObservers allow us to run code exactly when we need it. I hope I could give you an overview over this new API. &lt;/p&gt;

&lt;p&gt;If you want to use it in your Angular application, give &lt;strong&gt;ng-resize-observer&lt;/strong&gt; a try and let me know what you think.&lt;/p&gt;

&lt;p&gt;If you liked the article 🙌, spread the word and &lt;a href="https://twitter.com/KohlerChristian" rel="noopener noreferrer"&gt;follow me on twitter&lt;/a&gt; for more posts on Angular and web technologies.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>resizeobserver</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>Angular Dependency Injection Infographic</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Mon, 03 Feb 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/angular-dependency-injection-infographic-1bjm</link>
      <guid>https://dev.to/christiankohler/angular-dependency-injection-infographic-1bjm</guid>
      <description>&lt;p&gt;Angular has its own dependency injection framework. It's very powerful and helps increase the efficiency and modularity of your application. It can also be quite complex when compared to traditional DI frameworks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular.io/guide/dependency-injection" rel="noopener noreferrer"&gt;The official documentation&lt;/a&gt; is very well written and a must read for every Angular developer. The only thing missing for me was a good graphical overview. This is why I created this infographic poster.&lt;/p&gt;

&lt;p&gt;👩‍🚀 Protip: 🖨 Print your DI poster and hang it in the toilet. Within a few weeks your work colleagues are DI experts 😀&lt;/p&gt;

&lt;p&gt;✅ Also feel free to use the poster for education purposes like workshops or in classes.&lt;/p&gt;

&lt;p&gt;👆 It took me hours to complete this cheatsheet. If you like it follow me on &lt;a href="https://twitter.com/kohlerchristian" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; and spread the word 🙌&lt;/p&gt;

&lt;p&gt;🤓 Did you find a mistake? Please help improve the infographic and open an issue &lt;a href="https://github.com/ChristianKohler/homepage" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-02-03-infographic-angular-di/angular-di-infographic.pdf" rel="noopener noreferrer"&gt;Download Angular DI Infographic as PDF&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-02-03-infographic-angular-di%2Fimages%2Fposter-thumbnail.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2020-02-03-infographic-angular-di%2Fimages%2Fposter-thumbnail.png" alt="thumbnail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2020-02-03-infographic-angular-di/angular-di-infographic.pdf" rel="noopener noreferrer"&gt;Download Angular DI Infographic as PDF&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Update 20.02.2020
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Added providedIn: Module example&lt;/li&gt;
&lt;li&gt;Simplified Provider Syntax (removed string tokens)&lt;/li&gt;
&lt;li&gt;Minor design improvements&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>dependencyinjection</category>
      <category>infographic</category>
    </item>
    <item>
      <title>Improved Dependency Injection with the new providedIn scopes 'any' and 'platform'</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Sun, 15 Dec 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/improved-dependeny-injection-with-the-new-providedin-scopes-any-and-platform-30bb</link>
      <guid>https://dev.to/christiankohler/improved-dependeny-injection-with-the-new-providedin-scopes-any-and-platform-30bb</guid>
      <description>&lt;p&gt;Have you looked at the changelog of Angular 9 and found the new functionality of providedIn and want to know what &lt;strong&gt;'any'&lt;/strong&gt; and &lt;strong&gt;'platform'&lt;/strong&gt; are for? In this article we look at the two new scopes of providedIn.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2Fchangelog.jpg" 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2Fchangelog.jpg" alt="changelog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  tl;dr
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;'platform'&lt;/strong&gt; and &lt;strong&gt;'any'&lt;/strong&gt; are two new ways to define where a service should be resolved.&lt;/p&gt;

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

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;any&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;platform&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;'platform'&lt;/strong&gt; makes a service available between multiple apps or Angular Elements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;'any'&lt;/strong&gt; creates isolated (not singleton) services for every child injector.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Official Angular 9 documentation
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://next.angular.io/api/core/Injectable" rel="noopener noreferrer"&gt;offical documentation&lt;/a&gt; describes the new scopes as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;'root'&lt;/strong&gt; injector, which will be the application-level injector in most apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;'platform'&lt;/strong&gt; injector, which would be the special singleton platform injector shared by all applications on the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;'any'&lt;/strong&gt; injector, which would be the injector which receives the resolution. (Note this only works on NgModule Injectors and not on Element Injector)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The documentation already gives us a good overview of the new scopes. In the next chapters I'll go into the individual scopes in more detail.&lt;/p&gt;

&lt;h1&gt;
  
  
  Quick Angular DI recap
&lt;/h1&gt;

&lt;p&gt;** Module Injectors **&lt;/p&gt;

&lt;p&gt;There are two injector hierarchies in Angular:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ModuleInjector&lt;/li&gt;
&lt;li&gt;ElementInjector (NodeInjector in Ivy)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See &lt;a href="https://angular.io/guide/hierarchical-dependency-injection" rel="noopener noreferrer"&gt;Hierarchical injectors&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article we only look at the ModuleInjectors.&lt;/p&gt;

&lt;p&gt;A simplified visualization of the module injector hierachy would 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2Fdi-diagram.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2Fdi-diagram.png" alt="di-diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your services are in one of those injectors (Most likely in the root injector).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Platform Injector (special things like DomSanitizer)&lt;/li&gt;
&lt;li&gt;root Injector (main injector and place for all eagery loaded module providers)&lt;/li&gt;
&lt;li&gt;LazyModules Injectors (all lazy loaded modules create a child injector)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** Pre Angular 6 **&lt;/p&gt;

&lt;p&gt;The only way to define providers was with the providers array. Services were singletons in eagerly loaded modules but could be instatiated multiple times with lazy loaded modules.&lt;/p&gt;

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

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;** Angular 6+ **&lt;/p&gt;

&lt;p&gt;Angular 6 introduced tree-shakable providers with providedIn: &lt;strong&gt;'root'&lt;/strong&gt;.&lt;/p&gt;

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

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This has 3 big advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Services are tree-shakable&lt;/li&gt;
&lt;li&gt;Services are singleton for the whole application, also for lazy loaded modules&lt;/li&gt;
&lt;li&gt;No need to explicitly register the service with a NgModule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to know more about this, read the excellent &lt;a href="https://medium.com/@tomastrajan/total-guide-to-angular-6-dependency-injection-providedin-vs-providers-85b7a347b59f" rel="noopener noreferrer"&gt;article&lt;/a&gt; by Tomas.&lt;/p&gt;

&lt;p&gt;** Angular 9 ✨ **&lt;/p&gt;

&lt;p&gt;Now with Angular 9 we have two new ways to define providedIn scopes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;any&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;platform&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's have a look at them.&lt;/p&gt;

&lt;h1&gt;
  
  
  ProvidedIn: root
&lt;/h1&gt;

&lt;p&gt;Every service defined with &lt;strong&gt;'root'&lt;/strong&gt; will be provided in the root injector and is a singleton for the whole application. Lazy modules will use the instance from 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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2FprovidedInroot2.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2FprovidedInroot2.png" alt="providedinroot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;providedIn: 'root' will still be the default choice for most services.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  ProvidedIn: platform
&lt;/h1&gt;

&lt;p&gt;Every service defined with &lt;strong&gt;'platform'&lt;/strong&gt; will be provided in the platform injector and is a singleton for all applications. Lazy modules will use the instance from platform.&lt;/p&gt;

&lt;p&gt;The difference between &lt;strong&gt;'root'&lt;/strong&gt; and &lt;strong&gt;'platform'&lt;/strong&gt; is only noticeable when running multiple Angular application in the same window. Both make sure that only one singleton exists even for lazy loaded modules. But when running two applications in the same window, each application has it's own root injector but both share the platform injector.&lt;/p&gt;

&lt;p&gt;This means that the best use case for &lt;strong&gt;providedIn: 'platform'&lt;/strong&gt; is for sharing services over application boundaries. E.g. with Angular Elements.&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2FprovidedInplatform.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2FprovidedInplatform.png" alt="providedinplatform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use providedIn: 'platform' for sharing services over application boundaries. E.g. with Angular Elements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  ProvidedIn: any
&lt;/h1&gt;

&lt;p&gt;Every service defined with &lt;strong&gt;'any'&lt;/strong&gt; will be provided in every module it is used. That means there might be multiple instances of the same service. That means that every lazy loaded module has it's own instance of the service. All eagerly loaded modules share one instance provided by the root module injector.&lt;/p&gt;

&lt;p&gt;In the following example is the service used twice. Once within an eagerly loaded module (provided by root) and once in Lazy Module B (provided by its child injector).&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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2FprovidedInany.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%2Fraw.githubusercontent.com%2FChristianKohler%2FHomepage%2Fmaster%2Fcontent%2Fposts%2F2019-12-15-ng9-providedin-any%2Fimages%2FprovidedInany.png" alt="providedinany"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's really cool with that approach is, that you can make sure that a child injector always has it's own instance without the need to register the service in the providers list. 💪&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;'Root'&lt;/strong&gt; will still be the default for most services. It makes it very convenient to create tree-shakable services which are singleton within an application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;'Platform'&lt;/strong&gt; is most likely used for creating shared services for Angular Elements. If you know another use case, please let me know an create a &lt;a href="https://github.com/ChristianKohler/Homepage/blob/master/content/posts/2019-12-15-ng9-providedin-any/index.md" rel="noopener noreferrer"&gt;PR on this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;'Any'&lt;/strong&gt; is very helpful to make sure a service is a singleton within module boundaries. It's a robust alternative to &lt;strong&gt;'root'&lt;/strong&gt; to make sure the individual modules don't have a side effect on each other.&lt;/p&gt;

&lt;p&gt;All in all a very welcome feature 🥳&lt;/p&gt;

&lt;p&gt;👆 If you like the article follow me on &lt;a href="https://twitter.com/kohlerchristian" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; 🙌&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>One bite at a time - How to introduce new lint rules in a large codebase</title>
      <dc:creator>Christian Kohler</dc:creator>
      <pubDate>Tue, 26 Nov 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/christiankohler/one-bite-at-a-time-how-to-introduce-new-lint-rules-in-a-large-codebase-37ph</link>
      <guid>https://dev.to/christiankohler/one-bite-at-a-time-how-to-introduce-new-lint-rules-in-a-large-codebase-37ph</guid>
      <description>&lt;p&gt;Linters such as ESLint or TSLint can help make your code more readable and maintainable, and help you detect errors earlier. It's good to use linters from the beginning, but it's also a good idea to introduce linters into an existing code base.&lt;/p&gt;

&lt;p&gt;This article focuses on the introduction of linters into existing code bases.&lt;/p&gt;

&lt;h1&gt;
  
  
  tl;dr;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Use autofix if possible&lt;/li&gt;
&lt;li&gt;Extend lint config with a second config&lt;/li&gt;
&lt;li&gt;Add new rules to the second config&lt;/li&gt;
&lt;li&gt;Run linter with the second config with a precommit hook&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;Let's say the codebase is 1000 files large. You create a linter config, run the linter and you get like &lt;strong&gt;1000000 errors&lt;/strong&gt;. 🤯😱&lt;/p&gt;

&lt;p&gt;Now what can you do?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Autofix&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A lot of linting rule can be autofixed. For example the tslint rule&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"no-var-keyword": true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;can be autofixed. The autofixer replaces the &lt;em&gt;var&lt;/em&gt; keyword with a &lt;em&gt;let&lt;/em&gt; keyword.&lt;/p&gt;

&lt;p&gt;Tip: All autofixable keywords in the &lt;a href="https://palantir.github.io/tslint/rules/"&gt;list&lt;/a&gt; have the "Has Fixer" tag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manually fix&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you can't fix it automatically, you have to fix it manually. This can be a "Herculean task". So what often happens is that a rule is simply not used because it's too much work to fix all existing bugs.&lt;/p&gt;

&lt;h1&gt;
  
  
  The solution: The Boy Scout Rule
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Leave your code better than you found it. ...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The boy scout approach to apply new rules is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fix existing errors when you touch existing code&lt;/li&gt;
&lt;li&gt;Don't add new errors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Different Rules for CI/CD and changed files
&lt;/h2&gt;

&lt;p&gt;We need two sets of rules. The main one and one which extends it and adds new rules.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;th&gt;Rules&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tslint.json&lt;/td&gt;
&lt;td&gt;CI/CD&lt;/td&gt;
&lt;td&gt;Rules which apply for all files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tslint.newrules.json&lt;/td&gt;
&lt;td&gt;precommit hook&lt;/td&gt;
&lt;td&gt;New rules which only apply for changed files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example tslint.json&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Used by the CI/CD pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"defaultSeverity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"no-empty"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example tslint.newrules.json&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Used during the precommit hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"defaultSeverity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2019-11-25-lint-one-bite-at-a-time/tslint.json"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"no-any"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Important: The tslint.newrules.json extends the main ruleset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://raw.githubusercontent.com/ChristianKohler/Homepage/master/content/posts/2019-11-25-lint-one-bite-at-a-time/tslint.json"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Enforce tslint.newrules.json with a precommit hook
&lt;/h2&gt;

&lt;p&gt;This part is very easy nowadays thanks to the amazing libraries &lt;a href="https://github.com/okonet/lint-staged"&gt;lint-staged&lt;/a&gt; and &lt;a href="https://github.com/typicode/husky"&gt;husky&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So just install lint-staged and then configure the precommit hook to run tslint or eslint with the the correct configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev lint-staged@beta
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lint-staged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"**/*.{ts}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"tslint --project tsconfig.json -c tslint.newrules.json"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"husky"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pre-commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lint-staged"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;It is easy and very little work to set up a "newrule" configuration and enforce the configuration with a pre-commit hook. Now your codebase should get better every day as people work on it. Without the upfront costs, you would have to fix all the bugs in a commit. That's how you eat an elephant. One bite at a time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do you eat an elephant? One bite at a time.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;* I am strongly against eating elephants. It's a saying. Google it 😉&lt;/p&gt;

&lt;p&gt;Hero photo by @keilahoetzel&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>lint</category>
    </item>
  </channel>
</rss>
