<?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: Thomas King</title>
    <description>The latest articles on DEV Community by Thomas King (@kinginit).</description>
    <link>https://dev.to/kinginit</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%2F1205185%2F23e30316-2795-430a-aba8-1ccddfcf9972.png</url>
      <title>DEV Community: Thomas King</title>
      <link>https://dev.to/kinginit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kinginit"/>
    <language>en</language>
    <item>
      <title>Easily create mock data for unit tests 🧪</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Thu, 15 Feb 2024 12:37:36 +0000</pubDate>
      <link>https://dev.to/kinginit/easily-create-mock-data-for-unit-tests-3fji</link>
      <guid>https://dev.to/kinginit/easily-create-mock-data-for-unit-tests-3fji</guid>
      <description>&lt;p&gt;Whenever you write unit tests, the time comes that you have to mock data. Mocking this data can become tedious in many ways. Either the data gets copied over and over again for each unit test, or there is a file (or multiple files) that will contain all the mock data. If that data's interface (or class) suddenly changes, you will have to update each occurrence. You can use the IDE for most heavy lifting if you're lucky. &lt;/p&gt;

&lt;p&gt;With this guide, I will show you a way to easily create mock data for each interface or class you have. It is based on the &lt;a href="https://refactoring.guru/design-patterns/builder/typescript/example#lang-features" rel="noopener noreferrer"&gt;builder&lt;/a&gt; design pattern, which will allow easily created instances that can still be overridden with custom data. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;u&gt;Note&lt;/u&gt;: I will be using &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; as testing framework throughout the examples.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As an example, let's start with two interfaces, &lt;code&gt;Pet&lt;/code&gt; and &lt;code&gt;Person&lt;/code&gt;.&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pet&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;Creating mock data for these interfaces could look like this:&lt;/p&gt;

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

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Person should have pets&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="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="na"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bella&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="na"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&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="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Seems ok and not too much code, it could even be optimized more e.g., by using a for-loop. But, this is only for 1 unit test. If the &lt;code&gt;Person&lt;/code&gt; interface will be used in another unit test (in another file), that same code will have to be recreated. The downsides of manually creating this data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It is time-consuming&lt;/li&gt;
&lt;li&gt;Prone to human errors (e.g., copy-pasting and forgetting to change something)&lt;/li&gt;
&lt;li&gt;A large volume of mock data might become unscalable and hard to manage&lt;/li&gt;
&lt;li&gt;It might add a lot of bloat to your unit testing code making it less readable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fql2gqzsfl04ceadtnlm2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fql2gqzsfl04ceadtnlm2.gif" alt="copy-paste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Time to build a &lt;code&gt;PersonBuilder&lt;/code&gt; and &lt;code&gt;PetBuilder&lt;/code&gt; that will do the heavy lifting for us by providing default mock data. Let's start by creating an abstract Builder class that other builders can extend. &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;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;private&lt;/span&gt; &lt;span class="na"&gt;intermediate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&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="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="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&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;intermediate&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setDefaults&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="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nf"&gt;setDefaults&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;with&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt; &lt;span class="nx"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;intermediate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&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;intermediate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&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;intermediate&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&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;The abstract &lt;code&gt;Builder&lt;/code&gt; class contains four methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;reset&lt;/strong&gt;: to reset the internal object inside the builder back to the defaults. This is marked as private but can be marked as public as well if you prefer to use it outside your builder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;setDefaults&lt;/strong&gt;: the abstract method that will be implemented in the child Builders and that will provide the defaults for the object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;with&lt;/strong&gt;: the method that can provide overrides for your object. Returning &lt;code&gt;this&lt;/code&gt; will make these methods chainable. Intellisense will be provided thanks to the &lt;code&gt;K extends keyof T&lt;/code&gt;.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7183g4457axb04malbt.png" alt="with intellisense"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;build&lt;/strong&gt;: the method that will provide the final instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this base &lt;code&gt;Builder&lt;/code&gt; class, creating child Builder classes becomes easy. All you have to do is extend from &lt;code&gt;Builder&lt;/code&gt; with the appropriate generic type and implement the abstract method &lt;code&gt;setDefaults&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Creating a &lt;code&gt;PetBuilder&lt;/code&gt; will look like this:&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;PetBuilder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setDefaults&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Pet&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bella&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;The &lt;code&gt;Person&lt;/code&gt; interface contains a reference to &lt;code&gt;Pet&lt;/code&gt;, so we can use the newly created &lt;code&gt;PetBuilder&lt;/code&gt; to create a default pet for us inside the &lt;code&gt;PersonBuilder&lt;/code&gt;.&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;PersonBuilder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setDefaults&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Person&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PetBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;build&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="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Updating our previous unit test with these builders will look like this:&lt;/p&gt;

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

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Person should have pets&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="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="na"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PetBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&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;PersonBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&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="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We could even make it shorter by just removing the pets variable since the &lt;code&gt;PersonBuilder&lt;/code&gt; already provides us with a default &lt;code&gt;pets&lt;/code&gt; array containing 1 pet. But since this unit test tests for the presence of pets, we should include it as well.&lt;/p&gt;

&lt;p&gt;Using the builder pattern, making overrides becomes easy:&lt;/p&gt;

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

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Given a person&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PersonBuilder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;beforeEach&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="nx"&gt;builder&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;PersonBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;with the first name Tim should have that name&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="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="na"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstName&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="s1"&gt;Tim&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Tim&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;with the first name Thomas should have that name&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="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="na"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstName&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="s1"&gt;Thomas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Thomas&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;with the last name Doe should have no pets&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="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="na"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastName&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="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pets&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="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&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="p"&gt;});&lt;/span&gt;



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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;u&gt;Note&lt;/u&gt;: I know these unit tests make no sense from a testing perspective, but it is purely an example of the builders.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Bonus: adding Faker
&lt;/h2&gt;

&lt;p&gt;Instead of manually having to think of defaults for your interface properties, you could use &lt;a href="https://fakerjs.dev/" rel="noopener noreferrer"&gt;Faker&lt;/a&gt;.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;faker&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="s1"&gt;@faker-js/faker&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;PetBuilder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setDefaults&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Pet&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firstName&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="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;PersonBuilder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setDefaults&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Person&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PetBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;build&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="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Using Faker in your unit tests will create randomly generated data, which is nice but during testing, you'll want reproducible results. Luckily Faker provides something precisely for that: &lt;code&gt;faker.seed(123);&lt;/code&gt;. Using a seed will provide reproducible results when running your unit tests. &lt;/p&gt;

&lt;p&gt;You can add this seed in your global setup or use a &lt;code&gt;beforeAll&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I hope this guide will make your life of mocking data a bit easier. If you have any questions, feel free to reach out!&lt;/p&gt;

</description>
      <category>unittest</category>
      <category>jest</category>
      <category>typescript</category>
      <category>testing</category>
    </item>
    <item>
      <title>Which Angular components should you create? 🤔</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Wed, 13 Dec 2023 23:00:00 +0000</pubDate>
      <link>https://dev.to/kinginit/which-angular-components-should-i-create-5d1e</link>
      <guid>https://dev.to/kinginit/which-angular-components-should-i-create-5d1e</guid>
      <description>&lt;p&gt;When creating an Angular application, you probably already chose a UI library to handle the most rudimentary components, such as dropdowns, date pickers, etc. Also, have a look at my other blog post in which I compared several Angular UI libraries &lt;a href="https://dev.to/kinginit/the-big-angular-ui-library-comparison-4ifp"&gt;here&lt;/a&gt;.&lt;br&gt;
Now, apart from all these components that are offered by a library, what are some components you can create in your web application? Let's go over a (non-exhaustive) list of possible components.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: It is highly recommended to keep your component template small. That's why it's better to split it up into several (tiny) components.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  List
&lt;/h2&gt;

&lt;p&gt;Often, you'll end up having to display a list of something. Then it's obvious you create a &lt;code&gt;list&lt;/code&gt; component for it. Next to the &lt;code&gt;list&lt;/code&gt; component, you can further split this up into smaller components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;list item&lt;/strong&gt;: create a list item component that you can reuse in your &lt;a class="mentioned-user" href="https://dev.to/for"&gt;@for&lt;/a&gt; (or ngFor) of the parent list component. It will make the template of your list component a lot smaller and more readable. You can also create different types of list item components, depending on the needs, e.g., a list item for multimedia content and one for more textual content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;empty list&lt;/strong&gt;: create a component that acts as a placeholder when the list component has no items.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: With a &lt;code&gt;list&lt;/code&gt; component, I don't necessarily mean a generic one. E.g., for a list of products, you can create a &lt;code&gt;product-list&lt;/code&gt; component.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;You can do the same with cards as you do with lists. Create a &lt;code&gt;cards&lt;/code&gt; component, further split up with the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;card item&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;empty cards&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The UI library often provides a &lt;code&gt;card&lt;/code&gt; component that you can use in your cards component (or, a level below, in the card item).&lt;/p&gt;
&lt;h2&gt;
  
  
  Table
&lt;/h2&gt;

&lt;p&gt;A table is often more complex than regular lists or cards. Depending on the library you use, it might already provide a full-blown table component. Nonetheless, it is recommended to create a separate table component, even if it uses the table component of the UI library inside of it.&lt;/p&gt;

&lt;p&gt;If the library does not provide any table components, these are the components you can create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;table header&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;table row item&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;table footer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;editable table row item&lt;/strong&gt; in case of inline editing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;table summary row item&lt;/strong&gt; for totals at the end of the table&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;empty table&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymcg5m093rz7fgoc88o2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymcg5m093rz7fgoc88o2.png" alt="Table component"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Form-related
&lt;/h2&gt;

&lt;p&gt;Forms are almost always part of a web application. To increase reusability, you can create the following components:.&lt;/p&gt;
&lt;h3&gt;
  
  
  Form field
&lt;/h3&gt;

&lt;p&gt;Some libraries offer a full form field component containing a label and a text field. If that's not the case, you could create one yourself.&lt;/p&gt;

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

&lt;p&gt;To be included as options inside the form field component are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;label text&lt;/li&gt;
&lt;li&gt;id (for accessibility)&lt;/li&gt;
&lt;li&gt;is required (to show the "*")&lt;/li&gt;
&lt;li&gt;helper text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The actual text field can be supplied by using content projection (&lt;code&gt;ng-content&lt;/code&gt;). That way, you have the flexibility to add different kinds of content, e.g., text field, textarea, dropdown, etc.&lt;/p&gt;

&lt;p&gt;The main benefit of having a dedicated form field component is that all form markup is in one single place. Possible changes could be floating labels instead of regular ones, instead of "*" you have to show "(required)", etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  Form actions
&lt;/h3&gt;

&lt;p&gt;If you have the same buttons for every form, you could create a &lt;code&gt;form actions&lt;/code&gt; component for them. That clears up some space in your forms, and every form action is now part of a single component. Any changes to form actions now only have to be done in that component.&lt;/p&gt;

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

&lt;p&gt;You could even supply short keys to the form actions. They can then be handled in that component, instead of implementing them everywhere a form is used.&lt;/p&gt;
&lt;h3&gt;
  
  
  Validation summary
&lt;/h3&gt;

&lt;p&gt;Depending on the types of validation your web application needs, you might need to implement validation summaries. You can create a &lt;code&gt;validation summary&lt;/code&gt; component that will handle this for you. You can even add functionality that, when made visible, scrolls to the validation summary.&lt;/p&gt;

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

&lt;p&gt;The navigation menu of your web application can be created by a &lt;code&gt;menu&lt;/code&gt; component of the UI library you're using. But it's worth creating a dedicated menu component yourself. Even if it only incorporates the &lt;code&gt;menu&lt;/code&gt; component of the UI library. Sometimes changes have to be made that are perhaps not available in the UI library (e.g., an avatar). By creating your own menu component, you can easily add it yourself. It also makes the template of the component where your menu resides a bit smaller.&lt;/p&gt;
&lt;h2&gt;
  
  
  Skeleton
&lt;/h2&gt;

&lt;p&gt;A skeleton component is often already provided by the UI library. But since a skeleton component has the same structural layout as the one it is loading for, you will have several. You can create template skeletons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skeleton for a &lt;strong&gt;table layout&lt;/strong&gt;. Optionally with a configurable number of rows and columns.&lt;/li&gt;
&lt;li&gt;Skeleton for a &lt;strong&gt;list layout&lt;/strong&gt;. Configurable with the number of items, and how many rows per item.&lt;/li&gt;
&lt;li&gt;Skeleton for a &lt;strong&gt;form layout&lt;/strong&gt;. Configurable with the number of form fields. You can further split this skeleton into a regular form field skeleton component and a textarea field skeleton component that can be used in the general skeleton for the form layout.&lt;/li&gt;
&lt;li&gt;Skeleton for &lt;strong&gt;card layout&lt;/strong&gt;. Configurable with the number of cards and possible card template options.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Pickers
&lt;/h2&gt;

&lt;p&gt;Other than the common date or time picker, your application often requires other types of pickers. Here are some ideas.&lt;/p&gt;
&lt;h3&gt;
  
  
  Language picker
&lt;/h3&gt;

&lt;p&gt;When your web application needs to support multiple languages, the user needs to change the selected language. You could create two types of language pickers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dropdown: pick a language from a dropdown list.&lt;/li&gt;
&lt;li&gt;inline: all the languages are shown next to each other as links, with either the current language not being shown or the current language being highlighted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you need to support another language, you don't need to update any occurrences, but only the language picker.&lt;/p&gt;
&lt;h3&gt;
  
  
  Municipality picker
&lt;/h3&gt;

&lt;p&gt;Often used in address forms, you might need the user to choose a municipality. Either by searching by postal code or by municipality. You can create a municipality picker component for this.&lt;/p&gt;

&lt;p&gt;Most UI libraries provide an autocomplete (some call it typeahead) with which you can easily create the municipality picker. Your backend has to provide the search endpoint of course.&lt;/p&gt;
&lt;h3&gt;
  
  
  Country picker
&lt;/h3&gt;

&lt;p&gt;Just like municipalities, a country can be chosen as well. Same idea as the municipality picker, but for countries. You can add extras like the country flag or abbreviations.&lt;/p&gt;
&lt;h3&gt;
  
  
  Gender picker
&lt;/h3&gt;

&lt;p&gt;Usually, this is just a simple dropdown, but it could be that something more visual is needed, e.g., a dialog to ask questions like "Do you want to be addressed with they/them?". You can create a &lt;code&gt;gender picker&lt;/code&gt; component to let the user select a gender.&lt;/p&gt;
&lt;h2&gt;
  
  
  Confirm dialog
&lt;/h2&gt;

&lt;p&gt;Almost all UI libraries provide a dialog out-of-the-box, but often there is no built-in confirm dialog. You can create a custom confirm dialog component with options such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;message&lt;/li&gt;
&lt;li&gt;confirm button label&lt;/li&gt;
&lt;li&gt;cancel button label&lt;/li&gt;
&lt;li&gt;confirm callback&lt;/li&gt;
&lt;li&gt;cancel callback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can even go next level by providing a template instead of a regular text message.&lt;/p&gt;
&lt;h2&gt;
  
  
  Unauthenticated
&lt;/h2&gt;

&lt;p&gt;It could be that your application uses some form of authentication but still allows unauthenticated users to see pages that need authentication. Instead of seeing the authenticated content, they will see content that encourages them to log in or sign up.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"You can only see chat messages when you're logged in. Please log in or sign up by using one of the buttons below." &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In that case, you can create an &lt;code&gt;unauthenticated&lt;/code&gt; component with configurable text to show to the user based on the page they are on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6ye7muhjwoz5ef2omc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6ye7muhjwoz5ef2omc3.png" alt="Unauthenticated component"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Back button
&lt;/h2&gt;

&lt;p&gt;When navigating through your pages, users need to have a way back to the previous page. It's worth creating a "back button" component. This is because it is often prefixed with an icon to indicate the "this goes back" functionality, e.g., by using a left arrow.&lt;/p&gt;

&lt;p&gt;The functionality to go back to the previous page can all be incorporated into the back button component. So if a page needs a back button, you only need to include this component, and it is done.&lt;/p&gt;

&lt;p&gt;An extra reason why it's worth creating a component for this is maintainability. If someone decides that the back button should be prefixed with a chevron instead of an arrow, then you only have to update that icon in the back button component.&lt;/p&gt;
&lt;h2&gt;
  
  
  Login
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;login&lt;/code&gt; component containing only the fields required for logging (username or email, password, social logins, etc.). Not only will this make your login page template smaller, but you can also reuse it when you want the login functionality somewhere else, e.g., a dialog on some other page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0bwnhsukxg56p12v22v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0bwnhsukxg56p12v22v.png" alt="Login component"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  User menu
&lt;/h2&gt;

&lt;p&gt;When a user is logged in, they can view some settings by clicking their avatar on the top right. This often pops up a list of options, such as account settings or logging out. You can create a &lt;code&gt;user menu&lt;/code&gt; component to incorporate all these things.&lt;/p&gt;

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

&lt;p&gt;Some layouts keep coming back in your application. E.g., a page with a title and back button, a page with a sidebar and right content, etc. Instead of copy-pasting the code for each of those pages, create layout components instead. Example layout components could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title with side navigation and content to the right&lt;/li&gt;
&lt;li&gt;title with content but no navigation&lt;/li&gt;
&lt;li&gt;full-screen layout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use the layout component directly inside another component or use Angular Routing. The latter comes with a bit more setup, as you have to add some configuration to your routes. Long story short, it's more or less this: place your existing routes as children underneath an empty route path in your route definition:&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="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&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;redirectTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pathMatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NavLayoutComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// your layout component&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;DashboardComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;detail/:id&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;HeroDetailComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;heroes&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;HeroesComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&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;Then the template of the layout component will contain everything similar across the child components (e.g., titles, navigation, etc.). The &lt;code&gt;router-outlet&lt;/code&gt; will load the component based on the route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!--nav-layout.component.html--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;routerLink=&lt;/span&gt;&lt;span class="s"&gt;"/dashboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Dashboard&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;routerLink=&lt;/span&gt;&lt;span class="s"&gt;"/heroes"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Heroes&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;router-outlet&amp;gt;&amp;lt;/router-outlet&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Success
&lt;/h2&gt;

&lt;p&gt;When dealing with many wizards in your web application, you might want the final step (after everything is completed) to be a success step with a call-to-action. You can create a &lt;code&gt;success&lt;/code&gt; component with options such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;optional image&lt;/li&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;message&lt;/li&gt;
&lt;li&gt;call-to-action button text&lt;/li&gt;
&lt;li&gt;callback for the call-to-action button&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Counter
&lt;/h2&gt;

&lt;p&gt;This could be for animated purposes or an actual countdown.&lt;br&gt;
You see this on many websites when they're showing numbers; they are often animated to quickly animate from 0 to the number they want to show.&lt;br&gt;
Or an actual countdown, where something happens when the countdown reaches zero.&lt;/p&gt;

&lt;p&gt;In the first case, you can create an &lt;code&gt;animated count&lt;/code&gt; component. You can create the range inside your component and calculate the total duration to display from start to end. Or by using CSS only. See an explanation &lt;a href="https://css-tricks.com/animating-number-counters/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the actual countdown, you can create a &lt;code&gt;countdown&lt;/code&gt; component in which you do the actual countdown and provide a callback when the countdown reaches zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The types of components you need all depend on your web application, of course. The main takeaway here is to keep your component templates small, and the best way to do that is to create different components.&lt;/p&gt;

&lt;p&gt;Do you have any more examples of possible components? Let me know in the comments.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>design</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The big Angular UI library comparison 📚</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Mon, 11 Dec 2023 10:43:20 +0000</pubDate>
      <link>https://dev.to/kinginit/the-big-angular-ui-library-comparison-4ifp</link>
      <guid>https://dev.to/kinginit/the-big-angular-ui-library-comparison-4ifp</guid>
      <description>&lt;p&gt;There are many UI libraries for Angular out there. Some provide the basics; others provide a whole arsenal of components. I went through the most-used Angular UI libraries and compared the components they provide. The libraries I took up in my comparison are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ng-bootstrap.github.io/#/home" rel="noopener noreferrer"&gt;Ng-bootstrap&lt;/a&gt; (MIT license)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://primeng.org/" rel="noopener noreferrer"&gt;PrimeNG&lt;/a&gt; (MIT license)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.telerik.com/kendo-angular-ui" rel="noopener noreferrer"&gt;Kendo UI for Angular&lt;/a&gt; (subscription)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://valor-software.com/ngx-bootstrap/#/" rel="noopener noreferrer"&gt;Ngx-bootstrap&lt;/a&gt; (MIT license)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://material.angular.io/" rel="noopener noreferrer"&gt;Angular Material&lt;/a&gt; (MIT license)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.syncfusion.com/angular-components" rel="noopener noreferrer"&gt;Syncfusion Angular UI&lt;/a&gt; (subscription)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://js.devexpress.com/Angular/" rel="noopener noreferrer"&gt;Devextreme Angular&lt;/a&gt; (subscription)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ng.ant.design/docs/introduce/en" rel="noopener noreferrer"&gt;Ng-zorro&lt;/a&gt; (MIT license)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://akveo.github.io/nebular/" rel="noopener noreferrer"&gt;Nebular&lt;/a&gt; (MIT license)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://clarity.design/pages/introduction" rel="noopener noreferrer"&gt;Clarity&lt;/a&gt; (MIT license)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.infragistics.com/products/ignite-ui-angular" rel="noopener noreferrer"&gt;Ignite UI for Angular&lt;/a&gt; (subcription)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, four of these are subscription-based; the rest have an MIT license. A handy website to know what you can do with a license is &lt;a href="https://www.tldrlegal.com/" rel="noopener noreferrer"&gt;tl;drLegal&lt;/a&gt;. The MIT license summarized:&lt;/p&gt;

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

&lt;p&gt;Now off to the comparison! To make the comparison a bit easier for you, I've created a StackBlitz in which you can easily toggle between different UI libraries. You can even search the components. If the StackBlitz below does not work, I've added the entire sheet at the end of the blog as well.&lt;/p&gt;

&lt;p&gt;There's more information about the individual components and what is meant by them below the StackBlitz.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/stackblitz-starters-dxgq1j?embed=1&amp;amp;file=src%2Fconstants%2Fui-libraries.const.ts&amp;amp;hideExplorer=1&amp;amp;hideNavigation=1&amp;amp;theme=light&amp;amp;view=preview" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  List of components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Accordion
&lt;/h3&gt;

&lt;p&gt;The accordion component allows the user to show and hide sections of related content on a page. Most commonly, when you expand a section, the previous section will collapse.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Alert
&lt;/h3&gt;

&lt;p&gt;The alert component provides contextual feedback to the user. Often, you can choose between the types &lt;code&gt;info&lt;/code&gt;, &lt;code&gt;warning&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;success&lt;/code&gt;, or a color theme (e.g., &lt;code&gt;primary&lt;/code&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyulfrmuk0j56plfzp9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyulfrmuk0j56plfzp9d.png" alt="Alert" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Autocomplete (Typeahead)
&lt;/h3&gt;

&lt;p&gt;An autocomplete (or typeahead) is a special kind of input in which the user can start typing, and while he is typing, some results are shown as a suggestion to autocomplete his current input. This can be either local data or data coming from a server.&lt;/p&gt;

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

&lt;p&gt;Some libraries allow the results of the autocomplete to be grouped.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avatar
&lt;/h3&gt;

&lt;p&gt;The avatar component is used to display the profile image of a user. Depending on the UI library, it can be round, square, or rounded square.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Badge
&lt;/h3&gt;

&lt;p&gt;The badge component visually shows the status of something or depicts the count on some element. E.g., the number of notifications. A badge is purely visual and not to be confused with a tag. You can interact with a tag, not with a badge.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Barcodes
&lt;/h3&gt;

&lt;p&gt;A component not only to show or generate barcodes but sometimes QR codes (e.g., Ng-zorro uses QR codes).&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Block UI
&lt;/h3&gt;

&lt;p&gt;A component that will add an overlay to your page so you can no longer interact with it. It is often used when something is loading or submitting to prevent any user interaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Breadcrumb
&lt;/h3&gt;

&lt;p&gt;The breadcrumb component shows the user where he is in the web application hierarchy. It allows him to navigate up the hierarchy.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Button
&lt;/h3&gt;

&lt;p&gt;There is no need to explain what a button component does, as it speaks for itself. A component is used instead of the regular HTML button because it allows for more control and extensibility. The button component often comes in different color themes.&lt;/p&gt;

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

&lt;p&gt;Some libraries provide additional options for their button component, such as loading behavior, ripples, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Button group
&lt;/h3&gt;

&lt;p&gt;Sometimes you wish to group buttons that are related. This can be to toggle between different states or even be purely visual to show the user these buttons are in fact related.&lt;/p&gt;

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

&lt;p&gt;Some libraries allow the button group to behave as a radio button group (single selection) or as a multi-selection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calendar
&lt;/h3&gt;

&lt;p&gt;The calendar component displays an entire calendar to the user. The library often provides the calendar as an inline variant of what is shown in the popup of the date picker.&lt;/p&gt;

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

&lt;p&gt;Depending on the library, you can choose options such as the start day of the week, a button to select "today", changing globalization, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Card
&lt;/h3&gt;

&lt;p&gt;The card component displays some data as a card. Content is always required for the card. You can additionally (depending on the library's capabilities) add a title, image, avatar, call-to-action, etc.&lt;/p&gt;

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

&lt;p&gt;The card component often distinguishes itself by showing a shadow around the card to display some form of depth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Carousel
&lt;/h3&gt;

&lt;p&gt;A carousel component, or slideshow component, is used to cycle through several elements. These can be images or even content. Some options depending on the library are autoplay, styling of the left and right arrows, adding pagination bullets, etc.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Chart
&lt;/h3&gt;

&lt;p&gt;Some Angular UI libraries offer different types of charts; others are more limited. A chart component is used to display data in a visual way.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Chat
&lt;/h3&gt;

&lt;p&gt;A chat component is used to visualize an entire chat.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Checkbox
&lt;/h3&gt;

&lt;p&gt;A checkbox component is used to display true or false values. Some libraries even provide tri-state support (i.e., true, false, or null). A checkbox component is used in preference to the regular HTML input (type &lt;code&gt;checkbox&lt;/code&gt;) to provide custom styling or additional options.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Chips
&lt;/h3&gt;

&lt;p&gt;Chips are a special kind of input in which each input of the user is represented as a "chip" in the list. It allows the user to enter multiple things and clearly see each separate input. A library often allows each chip to be removed by adding a remove icon (a bin or an "x"). They can also be accompanied by another icon to depict the usage. &lt;/p&gt;

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

&lt;p&gt;Sometimes the library allows direct interaction with the chips, even without any input field.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Collapse
&lt;/h3&gt;

&lt;p&gt;A collapse component allows some content to be expanded or collapsed that is triggered by something else. An accordion is a special kind of collapse since each header collapses or expands the content beneath it. A collapse component can be any content and can often be triggered by any element (although good accessibility suggests a button).&lt;/p&gt;

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

&lt;p&gt;With some additional styling, you could use an accordion component as a collapse. The accordion component would then only hold a single panel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Color picker
&lt;/h3&gt;

&lt;p&gt;A color picker component allows the user to select a color. Some libraries prefer to create their own color picker instead of the regular HTML input (type &lt;code&gt;color&lt;/code&gt;) to provide additional styling or extra options, e.g., an inline variant. It also allows them to return a different format (rgba, hex, rgb, etc.).&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Context menu
&lt;/h3&gt;

&lt;p&gt;A context menu component is used when the user right-clicks a part of your page and you want to provide a different menu with different actions.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Data view
&lt;/h3&gt;

&lt;p&gt;A data view is a component in which you can provide tabular data and, by means of a template, show it to the user in a specific way.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Date picker
&lt;/h3&gt;

&lt;p&gt;With a date picker component, you can fill in an input field with a date selected from a calendar that pops up next to the input field. A library can provide its own date picker instead of the HTML input (type &lt;code&gt;date&lt;/code&gt;), so it can have custom styling and more options, e.g., different views (year, month, day, time) or date formatting.&lt;/p&gt;

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

&lt;p&gt;Some libraries allow for date range selection as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagram
&lt;/h3&gt;

&lt;p&gt;A diagram component can show a diagram, such as an activity diagram or sequence diagram.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Divider
&lt;/h3&gt;

&lt;p&gt;A divider component is used to clearly divide a list of items or sections. Most often, it is a single line to show the divider, but it can be accompanied by text.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Dock
&lt;/h3&gt;

&lt;p&gt;A dock component is a special menu for navigation that is docked to one of the four sides of the pages: top, bottom, left, or right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsz71hjflcxefl2l2rgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsz71hjflcxefl2l2rgc.png" alt="Dock on the left" width="651" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Drag &amp;amp; drop
&lt;/h3&gt;

&lt;p&gt;A drag &amp;amp; drop component allows for drag &amp;amp; drop functionality. This can be used for sorting, allowing the user to set preferences in order, etc.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Dropdown (Select)
&lt;/h3&gt;

&lt;p&gt;A dropdown component, or a select component, is used to make a selection from a list. When a selection is made, the selected item appears in the box. Some libraries allow for multiple selections by using checkboxes.&lt;/p&gt;

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

&lt;p&gt;The library prefers to provide its own dropdown component in favor of the regular HTML select to have custom styling and/or extra options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dropdown button
&lt;/h3&gt;

&lt;p&gt;A dropdown button allows the user to show multiple actions on a button. Much like a regular dropdown, but instead of showing the selection afterwards, an action is performed.&lt;/p&gt;

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

&lt;p&gt;Some libraries have a "split button", in which not only can you have multiple actions on the dropdown, but the main button also has an action. So with the split button, you can have a main action or a side action.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Editor
&lt;/h3&gt;

&lt;p&gt;Some libraries offer a basic editor component; others offer an entire WYSIWYG (What You See Is What You Get). The user can edit content and apply basic or advanced styling to it. Often, the component also allows for export or preview.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  File upload
&lt;/h3&gt;

&lt;p&gt;With a file upload component, users can upload one or multiple files. Some libraries allow for only one file per upload; others allow multiple uploads. You could use the regular HTML input (type &lt;code&gt;file&lt;/code&gt;), but a file upload component provides much more options.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Filter
&lt;/h3&gt;

&lt;p&gt;A filter component is used to create advanced filters. Often used for creating complex queries.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Floating button
&lt;/h3&gt;

&lt;p&gt;A floating button component (also called FAB, or Floating Action Button) is a button that floats in a specific position on the page. When you scroll down, the floating button always stays in that position. It is most commonly used to execute a primary action for that page.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Floating label
&lt;/h3&gt;

&lt;p&gt;A floating label component is used together with a text field. When the user focuses on that text field, the label (that looks like the placeholder) will simply float above the text field, making the user still aware of what that text field is about.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furyojhcbecolpuean8hb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furyojhcbecolpuean8hb.gif" alt="Floating label" width="229" height="67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Gauge
&lt;/h3&gt;

&lt;p&gt;A gauge component shows data in a gauge. Some libraries allow for high customization and nice animations.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Icon
&lt;/h3&gt;

&lt;p&gt;Some libraries come with their own icon library. You can use the icon component to display an icon. Often, you have options like color and size.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Image editor
&lt;/h3&gt;

&lt;p&gt;An image editor component allows for editing an image and saving or exporting it.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Image preview
&lt;/h3&gt;

&lt;p&gt;An image preview component shows an image on which the user can interact so that the image is shown in a larger view (preview).&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Input
&lt;/h3&gt;

&lt;p&gt;The input component allows for user input. You can often choose between different colors, sizes, and other options, like a clear button. Some libraries include the label in the input component.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Input group
&lt;/h3&gt;

&lt;p&gt;An input group component shows related things inside a single input. This could be a button next to the input or a prefix icon.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Input mask
&lt;/h3&gt;

&lt;p&gt;The input mask component provides a mask to the user to which they must adhere. Good examples are phone numbers or credit card numbers.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Label
&lt;/h3&gt;

&lt;p&gt;A label component is often a wrapper component for the regular label but provides additional styling and options, such as an icon or required markers.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  List view
&lt;/h3&gt;

&lt;p&gt;The list view component shows data in a list. The data is provided to the list view component, and by using a certain item template, it is shown as desired.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Listbox
&lt;/h3&gt;

&lt;p&gt;A listbox component is used for showing several options and allowing the user to select multiple of them. The listbox options are all shown in a panel to the user immediately, which is different than a dropdown.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Map
&lt;/h3&gt;

&lt;p&gt;A map component is used for showing a map to the user.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Menu
&lt;/h3&gt;

&lt;p&gt;The menu component is a form of navigation. It is often displayed as a menu bar.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Modal (Dialog)
&lt;/h3&gt;

&lt;p&gt;A modal (or dialog) component is used for displaying content above something else. Libraries often provide closing options such as click backdrop, a close button, or the escape key.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Multiselect
&lt;/h3&gt;

&lt;p&gt;A multiselect component is like a dropdown (select) component but allows for multiple selections, and this is often done by using checkboxes.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Paginator
&lt;/h3&gt;

&lt;p&gt;The paginator component is used for showing the pagination of something, e.g., a list or a table. It often contains options like go to the first or last page, go to the previous or next page, or separators when there are a lot of pages.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Pdf viewer
&lt;/h3&gt;

&lt;p&gt;A pdf viewer component is used for showing pdf documents inside a page.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Pivot table
&lt;/h3&gt;

&lt;p&gt;A pivot table component is used for analyzing a set of data. With it, you can create powerful summaries or calculations. E.g., based on a set of data in which people wear a hat or hoodie, extract how many people wear a hat, how many wear a hoodie, etc.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Popover
&lt;/h3&gt;

&lt;p&gt;A popover component is used to display related, additional content. It is not to be confused with a tooltip. A tooltip is used for explaining the content, and a popover shows related, additional content. Often, a popover is shown by clicking the source. It also supports multiple forms of content, such as images or links.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Progress bar
&lt;/h3&gt;

&lt;p&gt;The progress bar component is used to show progress to the user. You can often choose from several colors. Some also allow for indefinite progress bars.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Radio button
&lt;/h3&gt;

&lt;p&gt;A radio button component is used together with other radio buttons to provide the user with a choice. A radio button component is used in preference to the regular HTML input (type &lt;code&gt;radio&lt;/code&gt;) to provide custom styling or additional options.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Rating
&lt;/h3&gt;

&lt;p&gt;A rating component is a special kind of slider component. The range is often small (e.g., 0 to 5, 0 to 10), starting from a certain number, and is represented by a set of icons (often a star icon). When you hover over the rating component, the icons will be filled to the point where your mouse is hovering. As soon as you click, that rating persists (until you choose a new rating).&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Scheduler
&lt;/h3&gt;

&lt;p&gt;The scheduler component represents scheduled data and allows a user to manage it by creating, updating, or deleting events from the schedule. A scheduler can display data on different views, e.g., months, days, etc.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Sidebar
&lt;/h3&gt;

&lt;p&gt;A sidebar component is used for displaying navigation items on the side of a page.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Signature
&lt;/h3&gt;

&lt;p&gt;A signature component allows the user to sign content by adding their signature.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Skeleton
&lt;/h3&gt;

&lt;p&gt;A skeleton component is a special kind of loading component. It shows the rough structure of the content that is loading, e.g., 4 horizontal rectangles for a list component that is loading. It gives the user an idea of what kind of content will appear after the loading has finished.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Slider
&lt;/h3&gt;

&lt;p&gt;A slider component is used for displaying a range between two numbers. You can also change the number of steps the slider increases. A good example for the slider component is a price range for a filter.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Sparkline
&lt;/h3&gt;

&lt;p&gt;Sparkline charts are a special kind of chart. They are used for displaying data in a small space (e.g., inline usage).&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Spinner
&lt;/h3&gt;

&lt;p&gt;A spinner component is used as a placeholder or as an overlay for the content that is loading. It is often an icon that is animated by spinning it. Some libraries have spinner components that can be used inline.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Splitter
&lt;/h3&gt;

&lt;p&gt;The splitter component creates layouts that split into panes that may be resized, expanded, and collapsed. A good example of a splitter component is on StackBlitz, where you can resize the editor and preview panel.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Spreadsheet
&lt;/h3&gt;

&lt;p&gt;A spreadsheet component is used for displaying Excel-like spreadsheets. They often come with export functionality.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Steps
&lt;/h3&gt;

&lt;p&gt;The steps component, or wizard component, is used for showing steps. It guides the user through a certain process.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Table
&lt;/h3&gt;

&lt;p&gt;A table component is used for displaying tabular data. Some libraries offer a basic table component to show the tabular data. Others have advanced table components with options like sorting, filtering, or even exporting.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Tabs
&lt;/h3&gt;

&lt;p&gt;Tabs is a container component that the user can navigate by means of tabs. Some libraries have extra options, like scrollable tabs.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Tag
&lt;/h3&gt;

&lt;p&gt;A tag component is used to categorize content. They contain simple text and can be interactive. Common examples of tags are status, category, etc.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Terminal
&lt;/h3&gt;

&lt;p&gt;A terminal component provides an entire terminal to the user.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Textarea
&lt;/h3&gt;

&lt;p&gt;A textarea component is used to have multiline text input. A textarea component is sometimes preferred over the regular HTML textarea because it allows for extra options such as helper text or floating labels.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Timeline
&lt;/h3&gt;

&lt;p&gt;The timeline component is used for showing a list of events over a period of time.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Time picker
&lt;/h3&gt;

&lt;p&gt;What a date picker is for entire dates, the time picker is for time specifically. It allows you to pick a time.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Toast
&lt;/h3&gt;

&lt;p&gt;A toast is a dismissible message. Some libraries allow toasts to be automatically dismissed after a period of time. They are most often set at the bottom right, but they have configurable positioning.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Toggle
&lt;/h3&gt;

&lt;p&gt;A toggle or switch is used to show true or false values in the form of a visual switch.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Toggle button
&lt;/h3&gt;

&lt;p&gt;Just like a regular toggle, the toggle button is used to show true or false values. But instead of a switch, it is a button that is either in the pressed state or not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zlckzpqrt68x4gzjj2i.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zlckzpqrt68x4gzjj2i.gif" alt="Toggle button" width="74" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Toolbar
&lt;/h3&gt;

&lt;p&gt;A toolbar is a set of buttons and/or actions all grouped in a bar that is fixed at a certain position (either top, bottom, left, or right) of a content panel. The buttons and actions on the toolbar often have an influence on the content of the content panel. E.g., a toolbar for a rich text editor.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Tooltip
&lt;/h3&gt;

&lt;p&gt;A tooltip displays text to explain the content you're hovering over. You can often change the position it is displayed in (top, right, bottom, or left). Some libraries also allow you to trigger the tooltip with a click.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Tree
&lt;/h3&gt;

&lt;p&gt;A tree component is used for showing nested data. Some libraries allow for nested tabular data; others are more basic and are nested lists.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Word (Document viewer)
&lt;/h3&gt;

&lt;p&gt;A viewer component for showing a Word file or another document. Just like the pdf viewer, but for Word or other documents.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you can see, there are many Angular UI libraries, but you should pick one that fits your needs. Also, think about the budget, because not every library here is free. You can always go for a free one and use other open-source libraries for the more detailed stuff, like charts. Just keep in mind to keep the number of libraries limited, because the more libraries you use, the more you will need to maintain when updating your Angular version.&lt;/p&gt;

&lt;p&gt;To end this blog post, here's the entire comparison in a regular table (in case the StackBlitz fails to load). I hope you enjoyed this read! And as always, if you have any questions, feel free to contact me!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Ng-bootstrap&lt;/th&gt;
&lt;th&gt;PrimeNg&lt;/th&gt;
&lt;th&gt;Kendo UI&lt;/th&gt;
&lt;th&gt;Ngx-bootstrap&lt;/th&gt;
&lt;th&gt;Angular Material&lt;/th&gt;
&lt;th&gt;Syncfusion&lt;/th&gt;
&lt;th&gt;DevExtreme Angular&lt;/th&gt;
&lt;th&gt;Ng-zorro&lt;/th&gt;
&lt;th&gt;Nebular&lt;/th&gt;
&lt;th&gt;Clarity&lt;/th&gt;
&lt;th&gt;Ignite UI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Accordion                &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alert                    &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autocomplete (Typeahead)&lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avatar                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Badge                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Barcodes                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block UI                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Breadcrumb              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Button                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Button group            &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Calendar                &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Card                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Carousel                &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chart                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Checkbox                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chips                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collapse                &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Color picker            &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context menu            &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data view                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Date picker              &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diagram                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Divider                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dock                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Drag &amp;amp; drop              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dropdown (Select)        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dropdown button          &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Editor                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File upload              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filter                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Floating button          &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Floating label          &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gauge                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Icon                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image editor            &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image preview            &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input group              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input mask              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Label                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;List view                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listbox                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Map                      &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Menu                    &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modal (Dialog)          &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiselect              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paginator                &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pdf viewer              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pivot table              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Popover                  &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preview image            &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Progressbar              &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Radiobutton              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rating                  &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduler                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sidebar                  &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signature                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skeleton                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slider                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sparkline                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spinner                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Splitter                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spreadsheet              &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Steps                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Table                    &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tabs                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tag                      &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminal                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;           &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Textarea                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timeline                &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timepicker              &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toast                    &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toggle                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toggle button            &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toolbar                  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tooltip                  &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x            &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tree                    &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;x                &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;x                  &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x      &lt;/td&gt;
&lt;td&gt;x        &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Word (Document viewer)  &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;             &lt;/td&gt;
&lt;td&gt;                 &lt;/td&gt;
&lt;td&gt;x          &lt;/td&gt;
&lt;td&gt;                   &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;       &lt;/td&gt;
&lt;td&gt;         &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>angular</category>
      <category>ui</category>
      <category>library</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Why you should never use form.invalid 🙅‍♂️</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Tue, 05 Dec 2023 07:00:00 +0000</pubDate>
      <link>https://dev.to/kinginit/why-you-should-never-use-forminvalid-4hkl</link>
      <guid>https://dev.to/kinginit/why-you-should-never-use-forminvalid-4hkl</guid>
      <description>&lt;p&gt;When doing form validation in Angular, it's best practice to check the form's validity before posting it to the server or processing it. The form itself has a &lt;code&gt;valid&lt;/code&gt; property but also an &lt;code&gt;invalid&lt;/code&gt; property to check for validity. This might lead to this kind of code:&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invalid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// show errors&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// process form and continue&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will actually work in most cases, but it is deceiving as it might give false positives. And that's the case when using any &lt;a href="https://angular.io/guide/form-validation#creating-asynchronous-validators"&gt;async validation&lt;/a&gt; on the form.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding async validation to a form
&lt;/h2&gt;

&lt;p&gt;So you have that same form, but now there's a change incoming that requires you to add some async validation to a form control: check whether the username is already taken.&lt;/p&gt;

&lt;p&gt;The user starts typing, fills in an existing username, and immediately hits enter to submit the form. Hopefully the back-end gives you an error message to tell the user this username already exists because the front-end won't do it.&lt;/p&gt;

&lt;p&gt;Why is that? Because next to &lt;code&gt;valid&lt;/code&gt; and &lt;code&gt;invalid&lt;/code&gt;, there is a third state called &lt;code&gt;pending&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As soon as the async validation is triggered on that form control, the form properties &lt;code&gt;valid&lt;/code&gt; and &lt;code&gt;invalid&lt;/code&gt; will be false, but the &lt;code&gt;pending&lt;/code&gt; property will be true. When the async validation has ended, the &lt;code&gt;pending&lt;/code&gt; property will be false, and depending on the result of the async validation, the correct states are set on &lt;code&gt;valid&lt;/code&gt; and &lt;code&gt;invalid&lt;/code&gt;. But by using the existing logic, it will go to the &lt;code&gt;else&lt;/code&gt; condition, process the form, and continue.&lt;/p&gt;

&lt;p&gt;To be on the safe side, never use the &lt;code&gt;invalid&lt;/code&gt; property but negate the &lt;code&gt;valid&lt;/code&gt; property:&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// show errors&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// process form and continue&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even when using async validation, this will correctly interpret the form validation, i.e., the form is invalid as long as the async validation is not done.&lt;/p&gt;

&lt;p&gt;I've created a form status emulator (embedded StackBlitz below) to check for the different statuses a form goes through when editing a form control. Use this playground to check the status of the form according to the update mode and attached validators. In this playground, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;change the update mode to change, blur, or submit.&lt;/li&gt;
&lt;li&gt;add a required validator.&lt;/li&gt;
&lt;li&gt;add a maxlength validator (the maximum length is fixed at 10 characters).&lt;/li&gt;
&lt;li&gt;add an async validator (does an async validation for 4 seconds and checks whether the input starts with "server").&lt;/li&gt;
&lt;li&gt;reset the form&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/angular-ivy-wgmj8p?embed=1&amp;amp;file=src%2Fapp%2Fapp.component.ts&amp;amp;hideNavigation=1&amp;amp;view=preview" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

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

&lt;p&gt;When the form is going through async validation, both &lt;code&gt;valid&lt;/code&gt; and &lt;code&gt;invalid&lt;/code&gt; will be false, whereas the &lt;code&gt;pending&lt;/code&gt; property will be true. This gives false positives because the async validation is not over and could potentially return validation error(s). Use the &lt;code&gt;valid&lt;/code&gt; property to check for correct form validity.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to contact me!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>forms</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>RxJS mergeMap vs switchMap vs concatMap vs exhaustMap</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Fri, 01 Dec 2023 07:00:00 +0000</pubDate>
      <link>https://dev.to/kinginit/rxjs-mergemap-vs-switchmap-vs-concatmap-vs-exhaustmap-5gpg</link>
      <guid>https://dev.to/kinginit/rxjs-mergemap-vs-switchmap-vs-concatmap-vs-exhaustmap-5gpg</guid>
      <description>&lt;p&gt;First of all, I would like to start off by saying that this isn't the first blog post about this subject. But what I miss the most in other posts is visualizing these operators. This is the reason I created this blog post. So off we go!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mergeMap&lt;/code&gt;, &lt;code&gt;switchMap&lt;/code&gt;, &lt;code&gt;concatMap&lt;/code&gt;, and &lt;code&gt;exhaustMap&lt;/code&gt; are all called higher-order mapping operators. Instead of mapping values to other values, they map them to Observables, on which you can pipe further.&lt;/p&gt;

&lt;p&gt;One of the most used ones is probably the &lt;code&gt;switchMap&lt;/code&gt; operator. Most commonly, it is used together with HTTP GET calls, something like this:&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;idParam$&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="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;switchMap&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;  &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;productsService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProduct&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="err"&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;People know this operator because of its cancellation effect. But there's also the &lt;code&gt;mergeMap&lt;/code&gt;, &lt;code&gt;concatMap&lt;/code&gt; and even &lt;code&gt;exhaustMap&lt;/code&gt; operators, of which many people are not aware of or don't know when to use them. Let's go through them one by one.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: In each example image down below, you can see "SOURCE" and "INNER". "SOURCE" means the source Observable (e.g., a click event, ActivatedRoute query params, etc.), and "INNER" is the inner Observable that is returned by one of the higher-order mapping operators.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  MergeMap
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;mergeMap&lt;/code&gt; operator is the easiest of them all. It will map each source value to an Observable, which is merged into the output Observable. Simply explained: whatever comes in, comes out, regardless of order.&lt;/p&gt;

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

&lt;p&gt;In this example, you see that when the source (&lt;code&gt;A&lt;/code&gt;) gets called, the inner source starts emitting its values. When the source gets called again while the inner source is still emitting its values, the new values will be emitted as well. So if the source is called multiple times, all inner sources will emit their values in parallel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use case
&lt;/h3&gt;

&lt;p&gt;A good use case of the &lt;code&gt;mergeMap&lt;/code&gt; is a list of items in a shopping cart. You have an overview of all items, and next to each item is a button to delete it from the cart. If you're in a hurry, you can delete several items at once by clicking each "delete" button quickly. As a customer, you expect that each item that you click to delete will effectively be deleted. And that is what the mergeMap will do; it will continue to delete each one, even if you already clicked one for deletion.&lt;/p&gt;

&lt;p&gt;Now imagine you use &lt;code&gt;switchMap&lt;/code&gt; instead: you hastily click each "delete" button. Since the first delete is still ongoing on the server while you click the second delete, the first delete will be cancelled, but while the second delete is ongoing, the third is clicked for deletion, canceling the second one, etc. This makes deleting items in your shopping cart quite unpredictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  SwitchMap
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;switchMap&lt;/code&gt; will map each source value to an Observable, which is merged into the output Observable, but also cancel any previous inner Observable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xcccqp1v6cmk0kilgpa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xcccqp1v6cmk0kilgpa.gif" alt="switchMap example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the example, each time the source &lt;code&gt;A&lt;/code&gt; gets called, the emitting of the previous inner source will get cancelled. The new values will be emitted instead, unless source &lt;code&gt;A&lt;/code&gt; gets called again.&lt;/p&gt;

&lt;p&gt;The cancellation effect is more visible when you call the source &lt;code&gt;A&lt;/code&gt; multiple times after each other:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frz2r0n7asbk46lf8t9gf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frz2r0n7asbk46lf8t9gf.gif" alt="switchMap cancellation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Use case
&lt;/h3&gt;

&lt;p&gt;As stated before, the &lt;code&gt;switchMap&lt;/code&gt; is most often used together with HTTP GET calls in order to cancel a previous call when a new one is requested soon after. For example, a "refresh" button that will refresh the data in a list. You could spam the button to refresh, but with &lt;code&gt;switchMap&lt;/code&gt; that would keep canceling all previous clicks.&lt;/p&gt;

&lt;p&gt;Another good use case is autocomplete. While typing, the results are being fetched for you. But when the first results come in, it might be that you have already typed some more, which might return a more narrow result. So in that case, it would be handy that the previous call was cancelled to go for the newest one. The best practice is to combine your &lt;code&gt;switchMap&lt;/code&gt; with a &lt;code&gt;debounceTime&lt;/code&gt; operator to further improve your autocomplete.&lt;/p&gt;

&lt;h2&gt;
  
  
  ConcatMap
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;concatMap&lt;/code&gt; will map each source value to an Observable, which is merged into the output Observable in a serialized fashion, waiting for each one to complete before merging the next. So, simply put, they emit values while maintaining order.&lt;/p&gt;

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

&lt;p&gt;In the example, when the button is clicked for the first time, the inner source starts emitting its values. While it's still emitting, we call the source a second time. We can see that instead of emitting new values for the inner source, it waits until the values of the first time are all emitted. Hence, the order is maintained.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use case
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;concatMap&lt;/code&gt; is used where order is of importance. A use case could be a character builder in a game where you can choose several options, but some options are dependent on each other. For example, you choose a red hair color and, at the same time, want to add a moustache. The order is important here because you want a red moustache to be added. So the first API call will be with the "red hair" filter, followed by a second API call with the "moustache" filter. Due to the first API call, the second one already knows the hair color is red and can send over a red moustache.&lt;/p&gt;

&lt;p&gt;  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3i247clyv49nkzpn97qz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3i247clyv49nkzpn97qz.png"&gt;&lt;/a&gt;Source: &lt;a href="https://www.icy-veins.com/forums/" rel="noopener noreferrer"&gt;https://www.icy-veins.com/forums/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compare &lt;code&gt;concatMap&lt;/code&gt; with customers at a pharmacy. They all get served in the order when they arrived. Even if some arrive at the same time, they are handled in a sequential manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  ExhaustMap
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;exhaustMap&lt;/code&gt; will map each source value to an Observable, which is merged into the output observable only if the previous projected Observable has completed. In simpler terms, the new values are only emitted when the previous ones have all been emitted.&lt;br&gt;
You can remember &lt;code&gt;exhaustMap&lt;/code&gt; by thinking that you can't make any new calls because it's exhausted from still emitting.&lt;/p&gt;

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

&lt;p&gt;In the example, you see that the source is called multiple times. Only for the first call are the inner source values emitted (the red ones). All subsequent source calls are ignored, except the last call, since all previous inner values have been emitted.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use case
&lt;/h3&gt;

&lt;p&gt;A good use case would be to prevent double submissions. If a user keeps spamming the submit button, each call will go through. Using &lt;code&gt;exhaustMap&lt;/code&gt; will ignore any subsequent calls. You could use &lt;code&gt;switchMap&lt;/code&gt;, but that would mean that the submission would only go through when the user stopped spamming that submit button.&lt;/p&gt;

&lt;p&gt;You could compare it to a restaurant. You give your order to the waiter, and that will make the kitchen start preparing your order. If you call the waiter again with the same order while they're still busy with your current order in the kitchen, it will not make the kitchen start you on a new order. No, they will prepare it, and when it is ready, you can call the waiter again with that same order.&lt;/p&gt;
&lt;h2&gt;
  
  
  Airport luggage handling analogy
&lt;/h2&gt;

&lt;p&gt;Let's compare all these operators with the handling of luggage at an airport. At this airport, there is only one conveyor belt to handle luggage. When an airplane arrives, all luggage is put on the conveyor belt so each traveler can retrieve their luggage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtaeko110traqfar641p.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtaeko110traqfar641p.jpg" alt="Airport luggage handling"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  With &lt;code&gt;mergeMap&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When an airplane arrives, the luggage is put on the conveyor belt, one after the other. When another airplane arrives as well, the luggage of that one is also put on the conveyor belt, merged with the luggage of the other airplane. So the conveyor belt will show a mix of luggage from the first and second airplane.&lt;/p&gt;
&lt;h3&gt;
  
  
  With &lt;code&gt;switchMap&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When an airplane arrives, the luggage is put on the conveyor belt, one after the other. But as soon as another airplane arrives, they stop putting any luggage from the previous airplane on the conveyor belt. They cancel any further luggage handling for that airplane and begin handling the luggage for the newly arrived airplane.&lt;/p&gt;
&lt;h3&gt;
  
  
  With &lt;code&gt;concatMap&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When an airplane arrives, the luggage is put on the conveyor belt, one after the other. When a new airplane arrives, all the luggage from the first airplane is put on the conveyor belt. Only when all that luggage is handled will the handling of the luggage on the second airplane start.&lt;/p&gt;
&lt;h3&gt;
  
  
  With &lt;code&gt;exhaustMap&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When an airplane arrives, the luggage is put on the conveyor belt, one after the other. When a new airplane arrives and the luggage of the first airplane is still handled, the luggage handling personnel simply ignores the second airplane. The luggage on the second airplane will not be handled.&lt;/p&gt;
&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mergeMap&lt;/code&gt;: come in, merge, come out.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;switchMap&lt;/code&gt;: come in, merge, come out, but cancel when new ones come in.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;concatMap&lt;/code&gt;: come in, merge, come out, but maintain order.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exhaustMap&lt;/code&gt;: come in, merge, come out, but while ongoing, ignore new ones when they come in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're having trouble choosing the correct higher-order mapping operator, have a look at the following decision tree. It is based on the &lt;a href="https://rxjs.dev/operator-decision-tree" rel="noopener noreferrer"&gt;operator decision tree&lt;/a&gt; at RxJS.dev.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jrhzyymukb9hvscko17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jrhzyymukb9hvscko17.png" alt="Higher-order mapping operator decision tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please feel free to play around in the embedded StackBlitz down below. The example images on this blog are based on this StackBlitz.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/angular-ivy-65wdhd?embed=1&amp;amp;file=src%2Fapp%2Fapp.component.ts&amp;amp;theme=light&amp;amp;view=preview" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to contact me!&lt;/p&gt;

</description>
      <category>rxjs</category>
      <category>angular</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What HTML to use for a read-only form?</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Mon, 27 Nov 2023 08:33:07 +0000</pubDate>
      <link>https://dev.to/kinginit/what-html-to-use-for-a-read-only-form-2pm5</link>
      <guid>https://dev.to/kinginit/what-html-to-use-for-a-read-only-form-2pm5</guid>
      <description>&lt;p&gt;Front-end developers will always have come to some point in their career where they have to deal with forms. Creating a registration form, a login form, a form to gather user information, etc. The examples are numerous. Creating such forms is often something that most developers know how to do. Using labels and inputs, applying the correct styling or classes, and &lt;em&gt;woosh&lt;/em&gt;, there is a form that the user can fill in.&lt;/p&gt;

&lt;p&gt;The challenge is when that same form needs to be displayed in a read-only way. Labels and inputs speak for themselves, but what should you choose to display them? A good example would be in a CRUD application (an acronym for Create, Read, Update, and Delete). What often happens is that the HTML of the "create" or "edit" form is taken, but the form controls are then replaced with &lt;code&gt;span&lt;/code&gt; or &lt;code&gt;p&lt;/code&gt; elements. Although this works, it's not the best practice when accessibility (a11y) comes to mind.&lt;/p&gt;

&lt;p&gt;An example of how it is often done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;class=&lt;/span&gt;&lt;span class="s"&gt;"user-settings-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"user-data"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"firstName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;First name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"firstName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;John&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"lastName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Last name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"lastName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;John&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"user-address"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"addressLine1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Address line 1&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"addressLine1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;123 Maple street&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"addressLine2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Address line 2&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"addressLine2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Anytown, PA 17101&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&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;One thing is that &lt;code&gt;label&lt;/code&gt; elements are used to describe the corresponding form control (specifically &lt;a href="https://html.spec.whatwg.org/multipage/forms.html#category-label"&gt;label elements&lt;/a&gt;). This can be done either by using the &lt;code&gt;for&lt;/code&gt; attribute or by putting the form control inside the label element itself. But since there is no longer a form control, the use of the &lt;code&gt;label&lt;/code&gt; element should be discouraged.&lt;/p&gt;

&lt;p&gt;Another thing is that you should strive for semantic HTML. Writing semantic HTML means using HTML elements to structure your content based on each element's meaning, not its appearance. And by keeping the structure of the existing "create" or "edit" form and replacing the form controls with &lt;code&gt;span&lt;/code&gt; or &lt;code&gt;p&lt;/code&gt; elements, that doesn't really fit. Especially &lt;code&gt;div&lt;/code&gt; and &lt;code&gt;span&lt;/code&gt; elements convey no meaning at all. It also makes your HTML quite bulky.&lt;/p&gt;

&lt;h2&gt;
  
  
  What would be a good HTML structure?
&lt;/h2&gt;

&lt;p&gt;Let's keep the previous two things in mind and have a look at what a read-only form actually contains. In general terms, it's a list of questions and answers. E.g., the answer to the question "first name" is "John". &lt;br&gt;
When digging through the (rather big) list of semantic HTML elements, we see the &lt;code&gt;dl&lt;/code&gt; element ("description list"). The definition for a &lt;code&gt;dl&lt;/code&gt; element according to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl#try_it"&gt;mdn&lt;/a&gt; is the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;dl&amp;gt;&lt;/code&gt; element encloses a list of groups of terms (specified using the &lt;code&gt;&amp;lt;dt&amp;gt;&lt;/code&gt; element) and descriptions (provided by &lt;code&gt;&amp;lt;dd&amp;gt;&lt;/code&gt; elements). Common uses for this element are to implement a glossary or to display metadata (a list of key-value pairs).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A "list of key-value pairs" is what we need here. Using a description list not only makes our form semantic but also makes it quite flat. This is a huge benefit when we want to keep style and template separate, because it will be the stylesheet that will tell how the form will look and not the other way around.&lt;/p&gt;

&lt;p&gt;So coming from the bulky code we had for the form in the beginning, this can be transformed to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dl&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;First name&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;John&lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;Last name&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;Doe&lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;Address line 1&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;123 Maple street&lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dt&amp;gt;&lt;/span&gt;Address line 2&lt;span class="nt"&gt;&amp;lt;/dt&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dd&amp;gt;&lt;/span&gt;Anytown, PA 17101&lt;span class="nt"&gt;&amp;lt;/dd&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dl&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Much cleaner, flatter, and less bulky than the previous code. But I hear you say, "Now I should write more code in my stylesheet." That's true, but that's also where it belongs. The HTML now only conveys the meaning of the form; how it should look in the browser is a concern for the stylesheet.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You can still use classes to make your styling more specific. In an Angular component, for example, I would leave those out and style the &lt;code&gt;dl&lt;/code&gt;, &lt;code&gt;dt&lt;/code&gt;, and &lt;code&gt;dd&lt;/code&gt; elements directly due to ViewEncapsulation. Leaving out those classes makes it even cleaner.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To keep a 2-column layout for the form using the new HTML structure, we could harness the power of CSS grids, and the stylesheet could look like this (&lt;em&gt;note&lt;/em&gt;: &lt;code&gt;.user-form&lt;/code&gt; is the class given to the &lt;code&gt;dl&lt;/code&gt; element):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.user-form&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.user-form&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;dt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.user-form&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;dd&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.user-form&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;dt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&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 the original piece of code, there was also a difference between the "user data" and the "user address". That is no longer visible in the HTML now, but if you want to distinguish between them in the stylesheet, you can do so by using the &lt;code&gt;:nth-of-type&lt;/code&gt; pseudo class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.user-form&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;dt&lt;/span&gt;&lt;span class="nd"&gt;:nth-of-type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;2&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
&lt;span class="nc"&gt;.user-form&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="nd"&gt;:nth-of-type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&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 have reached the end of this blog. I hope this guide will give you better insights into how to structure read-only forms in HTML.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to contact me!&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>a11y</category>
    </item>
    <item>
      <title>How to code faster - VS Code edition</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Fri, 24 Nov 2023 07:00:00 +0000</pubDate>
      <link>https://dev.to/kinginit/how-to-code-faster-vs-code-edition-4pa</link>
      <guid>https://dev.to/kinginit/how-to-code-faster-vs-code-edition-4pa</guid>
      <description>&lt;p&gt;Pair programming can be very productive. But there's nothing so annoying as seeing your fellow programmer struggle with his coding. And with struggle, I don't necessarily mean that he lacks experience, but rather that he's coding so slowly. It almost feels like the scene with Flash from Zootopia (a must-see movie).&lt;/p&gt;

&lt;p&gt;  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiz8fhsv26fdej6k6djip.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiz8fhsv26fdej6k6djip.jpg"&gt;&lt;/a&gt;Source: Alphacoders.com&lt;/p&gt;

&lt;p&gt;How to not be Flash? Here are some tips and tricks for coding in Visual Studio Code (VS Code).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I do not own a Mac, so the short keys mentioned here are for Windows only. You can find a translation to Mac &lt;a href="https://www.makeuseof.com/windows-vs-mac-shortcuts/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, but since I can't reproduce them on a physical Mac, I did not include them in this guide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Copy and paste smarter
&lt;/h2&gt;

&lt;p&gt;I've seen people copy-pasting code by doing the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Move the cursor of the mouse to the beginning of the word.&lt;/li&gt;
&lt;li&gt;Hold left-click.&lt;/li&gt;
&lt;li&gt;Drag all the way to the end of the word.&lt;/li&gt;
&lt;li&gt;Release left-click.&lt;/li&gt;
&lt;li&gt;Right-click the selection.&lt;/li&gt;
&lt;li&gt;Click "copy".&lt;/li&gt;
&lt;li&gt;Scroll in the file explorer of VS Code to find the destination file.&lt;/li&gt;
&lt;li&gt;Click the destination file.&lt;/li&gt;
&lt;li&gt;Move the cursor to the desired location within the file.&lt;/li&gt;
&lt;li&gt;Right-click in destination.&lt;/li&gt;
&lt;li&gt;Click "paste".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a somewhat slow process to do. Especially if you need to apply this several times... Some ways to improve your copy-pasting are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;CTRL + C&lt;/code&gt; to &lt;strong&gt;copy&lt;/strong&gt; and &lt;code&gt;CTRL + V&lt;/code&gt; to &lt;strong&gt;paste&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;CTRL + SHIFT + left/right arrow&lt;/code&gt; to &lt;strong&gt;increase/decrease selection by words&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;SHIFT + left/right&lt;/code&gt; arrow to &lt;strong&gt;increase/decrease selection by character&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Clicking a line of code in VS Code and pressing &lt;code&gt;CTRL + X&lt;/code&gt; will &lt;strong&gt;put that line in your clipboard&lt;/strong&gt;. Using &lt;code&gt;CTRL + V&lt;/code&gt; anywhere will &lt;strong&gt;insert that line of code there&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;ALT + up/down arrow&lt;/code&gt; to &lt;strong&gt;move a line of code up/down&lt;/strong&gt; a spot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copy-pasting smarter also means navigating smarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigate smarter
&lt;/h2&gt;

&lt;p&gt;Instead of going through the explorer pane manually, use the key combination &lt;code&gt;CTRL + P&lt;/code&gt;. With this, you can search files by name. This is a "smart" search, meaning that it will not only look for words containing your search text but also a combination, e.g., &lt;code&gt;prodetcon&lt;/code&gt; will also find &lt;code&gt;project-details-container.component.ts&lt;/code&gt;. Using &lt;code&gt;CTRL + P&lt;/code&gt; is a lot faster than seeing someone struggle through their file explorer pane, which is a pain in itself (pun intended).&lt;/p&gt;

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

&lt;p&gt;Instead of looking for some code inside a file by scrolling, use these key combinations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CTRL + G&lt;/code&gt;: go to line&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CTRL + F&lt;/code&gt;: search in file (using the &lt;code&gt;ENTER&lt;/code&gt; key navigates to the next occurrence)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CTRL + click class/function/etc.&lt;/code&gt;: go to definition of said class/function/etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use &lt;code&gt;CTRL + TAB&lt;/code&gt; to switch between the last opened file and the current (or &lt;code&gt;TAB&lt;/code&gt; further to switch to other opened files). This is a lot faster than moving your cursor to the taskbar, looking for the correct tab, and clicking it to open.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: switching between opened files is efficient this way in VS Code. Also, make use of &lt;code&gt;ALT + TAB&lt;/code&gt; in Windows to switch between open windows.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Rename smarter
&lt;/h2&gt;

&lt;p&gt;Do not rename every single occurrence of a variable yourself. It is time-consuming and prone to errors. Instead, go to the definition of that variable and press &lt;code&gt;F2&lt;/code&gt;, rename it, and press &lt;code&gt;ENTER&lt;/code&gt;. This will change every occurrence. Not only does this work on variables, but also on functions, classes, interfaces, etc. This also works across files.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Use Emmet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://emmet.io/" rel="noopener noreferrer"&gt;Emmet&lt;/a&gt; is a content/code assist tool to write code faster and more efficiently. It comes &lt;a href="https://code.visualstudio.com/docs/editor/emmet" rel="noopener noreferrer"&gt;standard with VS Code&lt;/a&gt; so there is no need for any plugin. The concept is simple: you start typing an Emmet abbreviation, press &lt;code&gt;TAB&lt;/code&gt; or 'ENTER', and a full Emmet snippet for that abbreviation will come out.&lt;/p&gt;

&lt;p&gt;An example Emmet abbreviation could be &lt;code&gt;.grid&amp;gt;.col*3&lt;/code&gt;. When you press &lt;code&gt;TAB&lt;/code&gt; or &lt;code&gt;ENTER&lt;/code&gt;, VS Code fills out the entire piece of code for you:&lt;/p&gt;

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

&lt;p&gt;One of the cool things about Emmet is that you can generate &lt;a href="https://docs.emmet.io/abbreviations/lorem-ipsum/" rel="noopener noreferrer"&gt;"lorem ipsum" texts&lt;/a&gt; as well. E.g., &lt;code&gt;ul&amp;gt;li*4&amp;gt;lorem4&lt;/code&gt; will generate an unordered list of 4 elements, with each list item containing 4 random words.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Use a formatter
&lt;/h2&gt;

&lt;p&gt;Use a code formatter inside VS Code to format your code. I highly recommend &lt;a href="https://prettier.io/docs/en/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;. &lt;br&gt;
One of the benefits of using a code formatter is that it also "beautifies" your code. So if you copy-paste code from somewhere that has no layout at all, you can hit the format key combination (&lt;code&gt;CTRL + ALT + F&lt;/code&gt;) et voilá, your code is now "beautified" and, more importantly, readable.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Note: a good tip is to apply formatting on save. You can change this in the settings (look for "Format on save").&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Formatting is not only useful for yourself but for the whole team because it enforces the team's code to be more consistent. Have a look at my other post &lt;a href="https://dev.to/kinginit/enforcing-front-end-guidelines-in-an-angular-project-4199"&gt;Enforcing front-end guidelines in an Angular project&lt;/a&gt; to read more about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use code snippets
&lt;/h2&gt;

&lt;p&gt;Code snippets are templates that will make it easier to write repeating pieces of code, e.g., for loops, while statements, etc.&lt;/p&gt;

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

&lt;p&gt;By making use of code snippets, you can easily create blocks of code by typing in the bare minimum. You can use the built-in code snippets, use extensions that provide snippets, or even create your own!&lt;/p&gt;

&lt;p&gt;The built-in snippets provide templates for a number of languages, such as TypeScript, JavaScript, HTML, CSS, etc. You can use it to easily create a &lt;code&gt;switch&lt;/code&gt; statement, as seen above, for example.&lt;/p&gt;

&lt;p&gt;The VS Code Marketplace has several extensions that provide snippets for you. Examples are &lt;a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2" rel="noopener noreferrer"&gt;Angular snippets&lt;/a&gt;, &lt;a href="https://marketplace.visualstudio.com/items?itemName=evondev.tailwindui-snippets" rel="noopener noreferrer"&gt;Tailwind UI snippets&lt;/a&gt;, &lt;a href="https://marketplace.visualstudio.com/items?itemName=thekalinga.bootstrap4-vscode" rel="noopener noreferrer"&gt;Bootstrap snippets&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;Finally, you can create your own snippets. You can either create global snippets for a specific language or create snippets specific to a project. I won't go into any details here, but have a look at the documentation on &lt;a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets#_create-your-own-snippets" rel="noopener noreferrer"&gt;how to create your own snippets&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make use of "quantum typing"
&lt;/h2&gt;

&lt;p&gt;I call it "quantum typing" because this really speeds up the way you type out code in VS Code. It's all about multi-selection. When you need to change or add text to multiple lines, VS Code allows you to do so by selecting those multiple lines and simply starting to type on those lines at the same time.&lt;/p&gt;

&lt;p&gt;Hold &lt;code&gt;SHIFT + ALT&lt;/code&gt; and drag across multiple lines to make a selection. You'll see that multiple typing cursors appear across those lines. Simply start typing, and the text will be added simultaneously.&lt;/p&gt;

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

&lt;p&gt;If you want to add the same text to several places but they do not align, you can hold &lt;code&gt;ALT&lt;/code&gt; while clicking all the places where you want to type the same text.&lt;/p&gt;

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

&lt;p&gt;You can also hold &lt;code&gt;ALT&lt;/code&gt; and select multiple words at the same time. Instead of clicking a position, simply drag for a selection and release left-click or double-click for a single word selection, all while holding that &lt;code&gt;ALT&lt;/code&gt; key.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Quickly surround selection
&lt;/h2&gt;

&lt;p&gt;Code often has to be surrounded by square, round, or curly brackets. Or something needs to be surrounded by quotes (single or double). To do this, people often go to the start position, type in the starting bracket, move the cursor to the end position, and type in the ending bracket. A more efficient way is to select the parts that need to be surrounded and simply type the starting bracket. VS Code will be smart enough to know that the whole part needs to be surrounded.&lt;/p&gt;

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

&lt;p&gt;This works for &lt;code&gt;(&lt;/code&gt;, &lt;code&gt;{&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;'&lt;/code&gt; and &lt;code&gt;"&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make use of VS Code refactoring skills
&lt;/h2&gt;

&lt;p&gt;You can use VS Code to automatically refactor pieces of your code. E.g., instead of writing your own getters and setters, you could let VS Code generate them for you.&lt;br&gt;
To refactor something, just select what needs to be refactored, right-click, and click &lt;code&gt;Refactor...&lt;/code&gt; or even faster: use &lt;code&gt;CTRL + SHIFT + R&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Depending on the file you're in, VS Code can offer you several kinds of refactoring. E.g., for TypeScript, you could use &lt;code&gt;Extract function&lt;/code&gt;, &lt;code&gt;Extract constant&lt;/code&gt;, or &lt;code&gt;Generate get and set accessors&lt;/code&gt;. See the full list for TypeScript &lt;a href="https://code.visualstudio.com/docs/typescript/typescript-refactoring" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search and replace using RegEx
&lt;/h2&gt;

&lt;p&gt;Regular expressions (RegEx) can be a very powerful tool in your developer toolkit, and it is worth your while to get better acquainted with them. Not only can you use it in your own code (e.g., validation patterns, string replacement, etc.), but you can also use it for an advanced search and replace in VS Code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;You are in a project where some CSS selectors start with &lt;code&gt;app-&lt;/code&gt; and end with &lt;code&gt;-container&lt;/code&gt;. Due to new guidelines, they want you to change the suffix &lt;code&gt;-container&lt;/code&gt; to &lt;code&gt;-wrapper&lt;/code&gt;. You could try a simple search and replace by looking up &lt;code&gt;-container&lt;/code&gt; and replacing it with &lt;code&gt;-wrapper&lt;/code&gt;, but when you do the replacement, you see that some occurrences have been replaced, which should not have been the case (e.g., a CSS selector called &lt;code&gt;.unit-container-highlight&lt;/code&gt; becomes &lt;code&gt;.unit-wrapper-highlight&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;With RegEx, we can search more fine-grained. Using a capturing group, we can extract the words we want to keep while replacing the rest. The RegEx can look like &lt;code&gt;app-([a-z\-]+)-container&lt;/code&gt;. We want to replace the results so they end with &lt;code&gt;-wrapper&lt;/code&gt;. The replacement string will look like &lt;code&gt;app-$1-wrapper&lt;/code&gt;. Just make sure you checked the &lt;code&gt;Use Regular Expression&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Caution: even though a RegEx allows for a more fine-grained search, check the results in the search pane before doing the actual replacement!&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;You can have even more control by allowing the search to be applied only to certain files. Examples could be only HTML files (&lt;code&gt;*.html&lt;/code&gt;) or even an entire folder only (&lt;code&gt;src/app/modules&lt;/code&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1m03sd4p8nffhga5jveb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1m03sd4p8nffhga5jveb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to try out the RegEx before doing the search to be sure it's the correct one, use an online RegEx tester, such as &lt;a href="https://regex101.com/" rel="noopener noreferrer"&gt;Regex101&lt;/a&gt;. If you have no or little experience with RegEx, take a look at &lt;a href="https://regexlearn.com/learn/regex101" rel="noopener noreferrer"&gt;https://regexlearn.com/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use tools to automate monotonous work
&lt;/h2&gt;

&lt;p&gt;Sometimes we have to do monotonous work like creating mock data, creating a function for each field in a class, creating HTML list items based on the properties of an interface, etc. Like the saying goes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Work smarter, not harder!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use tools to automate such kinds of monotonous work instead of doing all the tedious work yourself. Tools I often use are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nimbletext.com/live" rel="noopener noreferrer"&gt;NimbleText&lt;/a&gt;: converts input as rows to a certain output based on a given format.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.mockaroo.com/" rel="noopener noreferrer"&gt;Mockaroo&lt;/a&gt;: generates mock data and outputs it in several formats (JSON, CSV, XML, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://json-generator.com/" rel="noopener noreferrer"&gt;JSON Generator&lt;/a&gt;: also generates mock data, but for JSON specifically. It's a bit more complex, but it allows for tailor-made results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good example of using NimbleText would be creating an entire form in HTML based on a few fields. We have a list of fields that we want to show in a form. Each field will have a label and an input. Let's create some data for NimbleText to convert:&lt;/p&gt;

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

first name, text
last name, text
email, email
street, text
number, number
city, text
postal code, text


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

&lt;/div&gt;

&lt;p&gt;Here we have 7 rows and 2 columns. Each row represents the form field. The first column is the name of the label, and the second column is the type of HTML input.&lt;br&gt;
Inside NimbleText, we leave the settings as is (column separator &lt;code&gt;,&lt;/code&gt; and row separator &lt;code&gt;\n&lt;/code&gt;). &lt;br&gt;
Each form field should be in a &lt;code&gt;div&lt;/code&gt; with the class &lt;code&gt;.form-field&lt;/code&gt;, containing a &lt;code&gt;label&lt;/code&gt; with the text and an &lt;code&gt;input&lt;/code&gt; for the form field. The pattern for NimbleText will look like this:&lt;/p&gt;

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

&amp;lt;div class="form-field"&amp;gt;
  &amp;lt;label for="&amp;lt;% $0.toCamelCase() %&amp;gt;"&amp;gt;&amp;lt;% $0.toSentenceCase() %&amp;gt;:&amp;lt;/label&amp;gt;
  &amp;lt;input id="&amp;lt;% $0.toCamelCase() %&amp;gt;" type="$1"/&amp;gt;
&amp;lt;/div&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;When we have a look at the output, we see that &lt;strong&gt;a lot&lt;/strong&gt; of work has been done for us:&lt;/p&gt;

&lt;div class="highlight js-code-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;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"firstName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;First name:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"firstName"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"lastName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Last name:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"lastName"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"street"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Street:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"street"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Number:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"city"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;City:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"city"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"postalCode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Postal code:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"postalCode"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&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;So be creative and use these tools whenever you can.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Coding faster in VS Code comes down to knowing your short keys and using the power of the IDE to your advantage. Here's a quick round-up of what was mentioned:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use short keys for copy-pasting.&lt;/li&gt;
&lt;li&gt;Navigate more efficiently by searching instead of manually navigating.&lt;/li&gt;
&lt;li&gt;Rename using &lt;code&gt;F2&lt;/code&gt; instead of doing it manually.&lt;/li&gt;
&lt;li&gt;Use Emmet.&lt;/li&gt;
&lt;li&gt;Use a formatter for neat outlining (and other advantages).&lt;/li&gt;
&lt;li&gt;Use code snippets.&lt;/li&gt;
&lt;li&gt;Quantum type, like there's no tomorrow.&lt;/li&gt;
&lt;li&gt;Use VS Code refactoring.&lt;/li&gt;
&lt;li&gt;RegEx to the rescue for search and replace.&lt;/li&gt;
&lt;li&gt;Use tools such as NimbleText to automate monotonous work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope you enjoyed reading this. If you know anyone who might need a little help with coding just a bit faster, feel free to share the article!&lt;/p&gt;

&lt;p&gt;If you have any questions, don't hesitate to reach out! Thanks!&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Coping with i18n</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Fri, 17 Nov 2023 15:21:09 +0000</pubDate>
      <link>https://dev.to/kinginit/coping-with-i18n-1opl</link>
      <guid>https://dev.to/kinginit/coping-with-i18n-1opl</guid>
      <description>&lt;p&gt;Coping with i18n makes it sound like it's some sort of autoimmune disease you have to learn how to live with. I18n (which stands for internationalization) is not a disease, but it is something you have to learn to live with. When we look up the meaning of "to cope with" in the dictionary, it says&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;to cope with: to deal with and attempt to overcome problems and difficulties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I18n does come with its challenges and difficulties. Especially in a project that started off small but is growing into something larger.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun fact: the 18 in i18n represents the 18 letters that stand between "i" and "n" in internationalization. So what would "accessibility" be?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's start with a use case:&lt;/p&gt;

&lt;p&gt;A new project has started. It's not that big yet, but they do want translations for it. When adding internationalization, you just start using translation keys as you see fit. You have a label on one page that needs to be translated to "First name". You add a translation key to your translation file for this label:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First name"&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;Then, you have to create another page that also has a label that needs to be translated to "First name". Great! You can reuse the same translation key.&lt;/p&gt;

&lt;p&gt;But the UX designer decided that on the first page "First name" is okay, but on the other one, it should be "What is your first name?".&lt;/p&gt;

&lt;p&gt;No problem; you can just add a new key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"whatIsYourFirstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What is your first name?"&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;But then a new change in translation comes up... It should no longer be "What is your first name?" but "Your first name please?". Time to update to translation then?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"whatIsYourFirstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your first name please?"&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;That would be really confusing. Can you imagine a whole translation file with such keys?&lt;/p&gt;

&lt;p&gt;Let's go over a few guidelines for i18n so it's easier to cope with it in your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  A clean home is a happy home
&lt;/h2&gt;

&lt;p&gt;Make sure that your translation file is up-to-date. Remove any unused translation keys and make sure all translation keys used in code are actually included in your translation file.&lt;/p&gt;

&lt;p&gt;Some libraries support ways to handle missing translations (e.g., TranslocoMissingHandler from &lt;a href="https://ngneat.github.io/transloco/"&gt;Transloco&lt;/a&gt; or MissingTranslationHandler &lt;br&gt;
 from &lt;a href="https://github.com/ngx-translate/core"&gt;ngx-translate&lt;/a&gt;). So that's a way to find out any missing translations, but that's quite manual because you have to go over every part of the served application.&lt;/p&gt;

&lt;p&gt;Another way is to extract the translations from your template. For Angular i18n, you can use the &lt;a href="https://angular.io/cli/extract-i18n"&gt;extract-i18n&lt;/a&gt; Angular CLI command to extract the marked text in the component into a source language file. For ngx-translate, you can use the plugin &lt;a href="https://github.com/biesbjerg/ngx-translate-extract"&gt;ngx-translate-extract&lt;/a&gt;. And for transloco, there is the &lt;a href="https://github.com/ngneat/transloco-keys-manager"&gt;transloco-keys-manager&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's important to keep the translation file up-to-date. Any keys that are used there that are not in the template may cause confusion. Any key missing in the translation file that is used in the template will hopefully result in an untranslated label (in the worst case, it will throw an error).&lt;/p&gt;
&lt;h2&gt;
  
  
  Be consistent
&lt;/h2&gt;

&lt;p&gt;Some libraries provide different ways to translate stuff in your application. Some of the possibilities are functions, pipes, or directives. Be consistent, and keep using the same ones.&lt;/p&gt;

&lt;p&gt;For an Angular project, for example, use directives in the template for translations. Or pipes. Just don't start mixing, because that would be ... inconsistent.&lt;/p&gt;

&lt;p&gt;Another thing to be consistent about is the translation keys. Choose a certain case (camelCase, PascalCase, etc.) from the beginning and stick with it. If you happen to work with people who are not that proficient in English, it might be worth going all lowercase. One of the benefits of using all lowercase is that there can be no mistake when a word is made up of several words. For example, lowercase "deadline" is easy for everyone to write. But when using camelCase, some people might think deadline is made up of two words, so they come up with "deadLine". Then some other team member wants to use that translation key and uses "deadline" in the template. The result is that the translation is not showing up.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conventions
&lt;/h2&gt;

&lt;p&gt;Introduce conventions when working with translation files. The casing is one thing I already mentioned. Here are some others:&lt;/p&gt;
&lt;h3&gt;
  
  
  Avoid abbreviations
&lt;/h3&gt;

&lt;p&gt;Don't use abbreviations in your translation keys. Most of the time, not everyone is aware of what the abbreviation means. A good example would be when you see the abbreviation "CI". As someone in development, you would think this stands for "Continuous Integration". But you were wrong; the application they used this abbreviation for was for the police department and stands for "Confidential Informant". So use "language" instead of "lang", use "component" instead of "comp", etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use unambiguous names
&lt;/h3&gt;

&lt;p&gt;Unambiguous names have a clear intent and are easy to understand. When choosing a translation key, keep that in mind. E.g., instead of "address1", "address2", use "homeAddress" and "invoiceAddress".&lt;/p&gt;
&lt;h3&gt;
  
  
  Use namespacing
&lt;/h3&gt;

&lt;p&gt;Namespacing your translation keys is a good way to group them into categories. Depending on the translation library used, you could use nesting (like an object structure) or you can use namespacing in the key name (separated with a dot, e.g., "common.buttons.login"). Namespacing your translation keys makes it easier to find a certain key as well.&lt;/p&gt;
&lt;h3&gt;
  
  
  Do not concatenate keys
&lt;/h3&gt;

&lt;p&gt;It's tempting to reuse keys in the template so you can concatenate them to a newly translated value. This might work for the language you're working in, but what if you have to support a language where it does not? An example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{'common.labels.please' | translate}} {{'common.buttons.login' | translate}}&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want a button saying "Please login". This concatenation might work in English, but if you try it in Dutch for example, it gives "Alsjeblieft inloggen", which sounds not so Dutch.&lt;/p&gt;

&lt;p&gt;Therefore, it's better to create a new key with its own dedicated translation and use that key instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use pluralization
&lt;/h3&gt;

&lt;p&gt;Don't implement pluralization yourself in an Angular project by using &lt;code&gt;*ngIf&lt;/code&gt; or another implementation. Make use of &lt;a href="https://angular.io/api/common/NgPlural"&gt;NgPlural&lt;/a&gt;. Also, do not concatenate a number with the translation key, e.g., &lt;code&gt;5 {{ common.labels.days | translate }}&lt;/code&gt;, but pass it as a parameter to the translation key if the library you use allows it. It will provide much more flexibility when you start integrating multiple languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Namespacing
&lt;/h2&gt;

&lt;p&gt;Namespacing your translation keys is not an easy task. Do you group in pages? Do you group in components? Do you group by type (labels, buttons, etc.)? This is something you should agree upon as early as possible. It will not always fit, but just be sure the team agrees on all categories. If you don't know how to begin, this structure works well most of the time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;common&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"common.buttons.test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"common.labels.test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"common.titles.test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"common.messages.test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;component&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specific&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"components.userList.buttons.test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"components.userList.labels.test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"components.userList.titles.test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"components.userList.messages.test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specific&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"pages.home.metadata.description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: This is namespaced in the key, but it might as well be nested.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;code&gt;common&lt;/code&gt; namespace is used for translations that are reused often, like "Save", "Cancel", "Ok",...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"common.buttons.ok"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"common.buttons.cancel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cancel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"common.labels.createdBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Created by {{name}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"common.titles.edit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Edit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"common.messages.required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This field is required"&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;The &lt;code&gt;components&lt;/code&gt; namespace is used for translations per component. That way, translations are easily found. The downside of this approach is that when the component changes its name, the namespace should be renamed as well. It's easier to create component specific translation keys instead of keys for an entire page. This is because components can be reused, which can cause confusion when the component of a specific page is reused on another page (which page specific label would you use then?).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If a translation can be reused over several components, put it in the &lt;code&gt;common&lt;/code&gt; namespace and use that key instead. That way, there won't be duplicates of the same translation. Some people may say that according to UX, the translation should be different (e.g., instead of a generic "save", use "save user" and "save settings"), and they are right. In that case, it should be in the &lt;code&gt;components&lt;/code&gt; namespace. But if that's not the case (even if it ever may be), just use the &lt;code&gt;common&lt;/code&gt; namespace (principle of &lt;a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it"&gt;YAGNI&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-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;"components.confirmDeleteDialog.buttons.ok"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ok, delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"components.confirmDeleteDialog.buttons.cancel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No, do not delete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"components.confirmDeleteDialog.titles.confirm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"About to delete {{name}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"components.confirmDeleteDialog.messages.confirm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deleting the user will imply that he will no longer has access to the application. Do you want to continue?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"components.registerForm.labels.firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What is your first name?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"components.registerForm.labels.lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What is your last name?"&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;There is also the &lt;code&gt;pages&lt;/code&gt; namespace. This namespace is used for page specific translations. What comes to mind is metadata, things like the page title, page description,... Anything that is truly specific to a page can fit under this namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;"pages.home.metadata.description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Building ecological homes with the future in mind."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"pages.home.titles.pageTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Home"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pages.about.metadata.description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Homes of the future is a new brand started in 2023 and available for all your ecological building needs."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"pages.about.titles.pageTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"About"&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;For the &lt;code&gt;common&lt;/code&gt; and &lt;code&gt;components&lt;/code&gt; namespaces, there is a subdivision of namespaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;buttons&lt;/strong&gt; are for button texts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;labels&lt;/strong&gt; are for single-line labels (e.g., labels next to an input field).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;titles&lt;/strong&gt; are for headers (e.g., title of a dialog).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;messages&lt;/strong&gt; are for multiline texts (e.g., paragraphs, dialog text, helper text).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This being said, you have reached the end of this blog. Coping with i18n can be hard sometimes, especially because the needs of the projects can change. I hope this guide will alleviate some of the pain that comes with i18n.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to contact me!&lt;/p&gt;

</description>
      <category>i18n</category>
      <category>angular</category>
      <category>productivity</category>
      <category>cleancoding</category>
    </item>
    <item>
      <title>Enforcing front-end guidelines in an Angular project</title>
      <dc:creator>Thomas King</dc:creator>
      <pubDate>Tue, 14 Nov 2023 09:36:46 +0000</pubDate>
      <link>https://dev.to/kinginit/enforcing-front-end-guidelines-in-an-angular-project-4199</link>
      <guid>https://dev.to/kinginit/enforcing-front-end-guidelines-in-an-angular-project-4199</guid>
      <description>&lt;p&gt;The title of this blog might be a little deceiving, because only a part of it can actually be seen as enforcing guidelines. It’s more about how to make team members work more in sync with each other, making sure everyone is coding more or less the same, like a tiny hive mind. Having those pull requests in which no one has to make comments like “no excessive empty lines”, “remove unused imports” or “clean up console.logs”. &lt;/p&gt;

&lt;p&gt;To try to achieve this, we can set up the Angular project in such a way that team members are more or less forced to write and commit code as the project demands it. Here are a few tips and tricks for setting up an Angular project to help your team be more in sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Communication
&lt;/h2&gt;

&lt;p&gt;It's actually a no-brainer, but I see a lack of communication too often; that's why it comes first. The first thing you should do is ask other team members. Especially if you're new to the team, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;where documentation can be found.&lt;/li&gt;
&lt;li&gt;whether you need specific access.&lt;/li&gt;
&lt;li&gt;if there are any guidelines to be followed.&lt;/li&gt;
&lt;li&gt;whether someone can go through the project with you (project structure, special things, etc.).&lt;/li&gt;
&lt;li&gt;what the rules and guidelines are for committing or pushing code.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Visual Studio code
&lt;/h2&gt;

&lt;p&gt;You can’t force your team members to use a certain IDE, but Visual Studio Code is free and provides a good development experience. If your team members all share the same IDE, it’s better they share a common set of settings, extensions,...&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended extensions
&lt;/h3&gt;

&lt;p&gt;Update or add &lt;code&gt;extensions.json&lt;/code&gt; in the &lt;code&gt;.vscode&lt;/code&gt; folder. This way, all team members are going to use the same set of extensions that are required for the project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: VS Code only suggests downloading these recommended extensions; it is still up to the team member to install them (however recommended)!&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;information&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;visit:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;https://go.microsoft.com/fwlink/?linkid=&lt;/span&gt;&lt;span class="mi"&gt;827846&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"recommendations"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"angular.ng-template"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"johnpapa.angular-essentials"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"streetsidesoftware.code-spell-checker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yzhang.markdown-all-in-one"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"stylelint.vscode-stylelint"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&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;p&gt;These are my five recommended extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Angular Language Service (angular.ng-template): provides a rich editing experience for Angular templates, both inline and external templates.&lt;/li&gt;
&lt;li&gt;Angular Essentials (johnpapa.angular-essentials): all the essential extensions needed for Angular development.&lt;/li&gt;
&lt;li&gt;Code Spell Checker (streetsidesoftware.code-spell-checker): make sure any spelling errors are visible and can be caught.&lt;/li&gt;
&lt;li&gt;Markdown All in One (yzhang.markdown-all-in-one): for any markdown related matters. Especially useful for previewing those README.md’s!&lt;/li&gt;
&lt;li&gt;Stylelint (stylelint.vscode-stylelint): immediately see stylelint errors in VS Code. If you're using SCSS files, be sure to add it to the language ids to be validated in the settings of the Stylelint extension.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project settings
&lt;/h3&gt;

&lt;p&gt;Add a &lt;code&gt;settings.json&lt;/code&gt; file to the project (under the &lt;code&gt;.vscode&lt;/code&gt; folder) that will use project specific settings in Visual Studio Code. This is the &lt;code&gt;settings.json&lt;/code&gt; I usually use (depending on the project):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"editor.codeActionsOnSave"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"source.organizeImports"&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="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"editor.defaultFormatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"editor.formatOnSave"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"editor.lineNumbers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"on"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"editor.trimAutoWhitespace"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"editor.tabSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&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;These settings will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sort imports and remove unused imports on save.&lt;/li&gt;
&lt;li&gt;use the Prettier extension as the default formatter when formatting a file.&lt;/li&gt;
&lt;li&gt;format the file on save.&lt;/li&gt;
&lt;li&gt;show line numbers.&lt;/li&gt;
&lt;li&gt;automatically trim whitespace.&lt;/li&gt;
&lt;li&gt;set the editor tab size to 2 spaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Prettier should be installed as part of the Angular Essentials extension pack.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Add project snippets
&lt;/h3&gt;

&lt;p&gt;Add snippets to your project that help people write code faster and more efficiently, but in a specific way. You can do so by creating a snippets file in the &lt;code&gt;.vscode&lt;/code&gt; folder. You can choose the name, as long as it ends with the extension &lt;code&gt;.code-snippets&lt;/code&gt;. An example snippet may be a snippet for a &lt;em&gt;Given-When-Then&lt;/em&gt; code block for unit tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Given-When-Then"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gwt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"body"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"describe('$0', () =&amp;gt; {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;beforeEach(() =&amp;gt; {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;describe('$1', () =&amp;gt; {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t\t&lt;/span&gt;&lt;span class="s2"&gt;it('$2', () =&amp;gt; {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t\t&lt;/span&gt;&lt;span class="s2"&gt;});"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;});"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"});"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Create a Given-When-Then block"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&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;There are many extensions that provide snippets out of the box. Have a look in the extensions store of VS Code and update each team member to make use of these snippets.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Prettier
&lt;/h2&gt;

&lt;p&gt;Prettier is a code formatter that formats your code to a uniform, consistent style. That way, the code looks the same for everyone using the same Prettier settings.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As stated earlier, the Prettier extension for VS Code itself should already be installed by the Angular Essentials extension pack.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For formatting inside the project, install Prettier in the project via NPM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;prettier &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.prettierrc.json&lt;/code&gt; file in the root of the project that will contain the Prettier configuration. You can use the default that came installed with Prettier or use this one (&lt;em&gt;note&lt;/em&gt;: make sure the tabWidth is the same as the one you defined in the &lt;code&gt;settings.json&lt;/code&gt;!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"tabWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"useTabs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"semi"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"bracketSpacing"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"arrowParens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"avoid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"trailingComma"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"bracketSameLine"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"printWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"endOfLine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auto"&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;What’s the difference with writing the configuration in here instead of in &lt;code&gt;settings.json&lt;/code&gt; (e.g., &lt;code&gt;“prettier.tabWidth”: 2&lt;/code&gt;)? It’s essentially the same; when you format the file, it will look for the Prettier configuration, but the &lt;code&gt;.prettierrc.json&lt;/code&gt; will take precedence over the settings in &lt;code&gt;settings.json&lt;/code&gt;. I like using a separate &lt;code&gt;.prettierrc.json&lt;/code&gt; file because 1) it clearly shows the Prettier configuration in one file, and 2) if the team would step away from VS Code, the Prettier configuration can be reused.&lt;/p&gt;

&lt;p&gt;Add a &lt;code&gt;.prettierignore&lt;/code&gt; file (recommended by Prettier itself) that contains the same content as the .gitignore (unless you have some exceptions of your own).&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Linting with ESlint
&lt;/h2&gt;

&lt;p&gt;Linting is a process that will check your code for potential errors. Quite essential in my opinion! Not only can you check for potential errors, but you can also enforce a certain set of rules (guidelines) with linting.&lt;/p&gt;

&lt;p&gt;Add linting for the Angular project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng add @angular-eslint/schematics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install the &lt;code&gt;@angular-eslint/schematics&lt;/code&gt; package from NPM and will create an &lt;code&gt;.eslintrc.json&lt;/code&gt; file that will contain the linting configuration. It will also update your &lt;code&gt;angular.json&lt;/code&gt; with a new architect target “lint” and create a new script line in your &lt;code&gt;package.json&lt;/code&gt; called “lint”.&lt;/p&gt;

&lt;p&gt;With linting rules, you can enforce a common set of coding standards. When running the &lt;code&gt;@angular-esling/schematics&lt;/code&gt; schematic, it will include a &lt;code&gt;.eslintrc.json&lt;/code&gt; file in your project. It will already extend some rules for ts and html files from the recommended ones. For TypeScript files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;eslint:recommended&lt;/code&gt; is ESLint's inbuilt "recommended" configuration; it turns on a small, sensible set of rules that lint for well-known best practices. See &lt;a href="https://eslint.org/docs/latest/rules/"&gt;https://eslint.org/docs/latest/rules/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;plugin:@typescript-eslint/recommended&lt;/code&gt; is similar to &lt;code&gt;eslint:recommended&lt;/code&gt;, except it turns on TypeScript-specific rules. See &lt;a href="https://typescript-eslint.io/rules/"&gt;https://typescript-eslint.io/rules/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;plugin:@angular-eslint/recommended&lt;/code&gt;, see &lt;a href="https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/src/configs/README.md#recommended"&gt;https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/src/configs/README.md#recommended&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plugin:@angular-eslint/template/process-inline-templates&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For HTML files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;plugin:@angular-eslint/template/recommended&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plugin:@angular-eslint/template/accessibility&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The template specific rules can be seen here: &lt;a href="https://github.com/angular-eslint/angular-eslint/tree/main/packages/eslint-plugin-template#angular-eslinteslint-plugin-template"&gt;https://github.com/angular-eslint/angular-eslint/tree/main/packages/eslint-plugin-template#angular-eslinteslint-plugin-template&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The schematic by default includes two rules for TS files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"@angular-eslint/directive-selector"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attribute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"camelCase"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@angular-eslint/component-selector"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"element"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kebab-case"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&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;p&gt;This will give a linting error when you apply a different prefix for a directive or component other than “app” (it will also check for the correct casing). It is recommended to use a prefix specific for your application (see &lt;a href="https://angular.io/guide/styleguide#component-custom-prefix"&gt;https://angular.io/guide/styleguide#component-custom-prefix&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You are already using the recommended linting rules, which is good! Most of the time, I add some more specific rules for the project, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allow no console.logs.&lt;/li&gt;
&lt;li&gt;enforce no unused imports (if the developer has the organize imports on save action disabled for some reason). For this, I use the &lt;code&gt;[eslint-plugin-unused-imports](&amp;lt;https://www.npmjs.com/package/eslint-plugin-unused-imports&amp;gt;)&lt;/code&gt; package.&lt;/li&gt;
&lt;li&gt;use triple equals.&lt;/li&gt;
&lt;li&gt;enforce naming conventions, such as making boolean variables sound more boolean-like by prefixing is, has, can, etc.&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An example &lt;code&gt;.eslintrc.json&lt;/code&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"root"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ignorePatterns"&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;"projects/**/*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&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;"unused-imports"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"overrides"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"files"&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;"*.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint:recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@typescript-eslint/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@angular-eslint/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@angular-eslint/template/process-inline-templates"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@angular-eslint/directive-selector"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attribute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"toh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"camelCase"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@angular-eslint/component-selector"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"element"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"toh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kebab-case"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/explicit-function-return-type"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/naming-convention"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"selector"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"variable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"types"&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;"boolean"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"format"&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;"PascalCase"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&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;"is"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"should"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"has"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"can"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"did"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"will"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@angular-eslint/prefer-on-push-component-change-detection"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/no-unused-vars"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"unused-imports/no-unused-imports"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"unused-imports/no-unused-vars"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"warn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"vars"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"varsIgnorePattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"after-used"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"argsIgnorePattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^_"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"brace-style"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1tbs"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"eqeqeq"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"no-else-return"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"no-trailing-spaces"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"no-var"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"object-shorthand"&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;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefer-const"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefer-object-spread"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"prefer-template"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"no-console"&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;"error"&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;"allow"&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;"warn"&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="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"files"&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;"*.html"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@angular-eslint/template/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@angular-eslint/template/accessibility"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&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;p&gt;There are so many linting rules you can apply. Use the ones that work for your project and team. Caution though, because some linting has an impact on your code, so make sure you know what you’re doing! If you’re not certain about the impact of a certain rule, set the severity to “warn” instead of “error” and see how many lines it will impact by running the linter.&lt;/p&gt;

&lt;p&gt;Also, have a look at all the Eslint plugins that already exist. They might have a set of rules that you can use for your project. Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;eslint-plugin-jest: &lt;a href="https://www.npmjs.com/package/eslint-plugin-jest"&gt;https://www.npmjs.com/package/eslint-plugin-jest&lt;/a&gt;. Linting rules for your Jest unit tests.&lt;/li&gt;
&lt;li&gt;@ngrx/eslint-plugin: &lt;a href="https://www.npmjs.com/package/@ngrx/eslint-plugin"&gt;https://www.npmjs.com/package/@ngrx/eslint-plugin&lt;/a&gt;. Linting rules when using NGRX.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run &lt;code&gt;ng lint --fix&lt;/code&gt; to run the linting for your project and potentially autofix all problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linting (S)CSS files
&lt;/h3&gt;

&lt;p&gt;Linting can be applied not only to TypeScript and HTML files but also to your stylesheets. To lint stylesheets, you can use &lt;a href="https://stylelint.io/user-guide/get-started/"&gt;Stylelint&lt;/a&gt;. Most of the time, the projects I work on are a bit more complex, so they use SCSS. This is possible with Stylelint by installing an SCSS configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; stylelint stylelint-config-standard-scss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.stylelintrc.json&lt;/code&gt; file in the root of the project that will contain all the rules that will apply to your stylesheet. You can extend the recommended rules but also customize them. When extending the recommended rules, chances are all your existing stylesheets will contain errors. For starters, add the rules that give errors to the list of rules and set them to &lt;code&gt;null&lt;/code&gt; to ignore them for now. This will give you the chance to evaluate the importance of that rule.&lt;/p&gt;

&lt;p&gt;An example &lt;code&gt;.stylelintrc.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&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="s2"&gt;"stylelint-config-standard-scss"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"no-empty-source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&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;p&gt;You can take a look at the different rules here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stylelint rules: &lt;a href="https://stylelint.io/user-guide/rules"&gt;https://stylelint.io/user-guide/rules&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SCSS rules (from the standard config): &lt;a href="https://github.com/stylelint-scss/stylelint-config-standard-scss/blob/main/index.js"&gt;https://github.com/stylelint-scss/stylelint-config-standard-scss/blob/main/index.js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, update the script in your package.json that performs the linting, so it will also include the linting of stylesheets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ng lint &amp;amp;&amp;amp; npx stylelint &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;**/*.scss&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to Prettier, also create a &lt;code&gt;.stylelintignore&lt;/code&gt; file in the root of the project to ignore specific files. It’s ok to copy the contents of the &lt;code&gt;.gitignore&lt;/code&gt; file into this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Husky
&lt;/h2&gt;

&lt;p&gt;Add Husky hooks to prevent team members from committing or pushing faulty code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx husky-init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: If you get the error &lt;code&gt;The token '&amp;amp;&amp;amp;' is not a valid statement separator in this version.&lt;/code&gt;, just run the commands separately.&lt;/p&gt;

&lt;p&gt;This will create a pre-commit hook file from Husky. It will originally contain the command npm test. I suggest updating this with npm run lint. Running tests on a small project will be fast, but as the project grows, it will take longer. So committing code will get cumbersome. Therefore, I recommend linting the project before committing as a first check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"


npm run lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a pre-push hook file that will run the unit tests before pushing the code to Git.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx husky add .husky/pre-push "npm run test"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be done only after a few commits, so it is ok that this takes a bit longer.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Use conventional Commits
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.conventionalcommits.org/en/v1.0.0/"&gt;Conventional Commits&lt;/a&gt; is a specification for writing standardized commit messages. This way, the changes throughout your code are documented in a more consistent and human-readable way. A Conventional Commit message looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;[optional scope]: &amp;lt;description&amp;gt;


[optional body]


[optional footer(s)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix: loading spinner not working on home page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;The benefits of using these types of commit messages are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Semantic Versioning (SemVer) compatibility&lt;/strong&gt;: Conventional Commits are designed to work well with Semantic Versioning. By following a specific format for commit messages, it becomes easier to automatically determine the version number based on the type of changes introduced (e.g., feature, fix, breaking change).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated release notes&lt;/strong&gt;: since Conventional Commits provide a structured and standardized way of writing commit messages, tools can automatically generate release notes from the commit history. This makes it easier to communicate changes to users, contributors, and other stakeholders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clearer commit history&lt;/strong&gt;: Conventional Commits encourage a consistent and clear commit message format. This helps in creating a more readable and understandable commit history, making it easier for team members to track changes and understand the evolution of the codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enables automation&lt;/strong&gt;: many CI/CD (Continuous Integration/Continuous Deployment) and release management tools can take advantage of Conventional Commits to automate tasks such as versioning, changelog generation, and release workflows. This reduces the manual effort required for managing the release process. E.g., Jenkins and Azure DevOps provide such extensions and plugins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration and communication&lt;/strong&gt;: by using a common commit message format, team members can easily understand the nature of changes made in the codebase. This improves collaboration and communication among team members, as everyone follows a consistent style when documenting changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facilitates maintenance&lt;/strong&gt;: over time, projects can grow complex, and maintaining a clear history becomes crucial. Conventional Commits make it easier to navigate and understand the commit history, aiding in maintenance tasks such as bug tracking, troubleshooting, and identifying when specific features were introduced or bugs were fixed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration with tooling&lt;/strong&gt;: many development tools and services support Conventional Commits out of the box or through plugins. This includes version control systems, CI/CD pipelines, code review tools, and more. Utilizing Conventional Commits enhances integration with these tools.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Something important to keep in mind when working with commits is to keep them small. With small commits, it will be easier to come up with a good description for the Conventional Commit message.&lt;/p&gt;
&lt;h3&gt;
  
  
  commitlint
&lt;/h3&gt;

&lt;p&gt;If you agree on using Conventional Commits throughout your project, that's great! Even greater would be that they could be enforced. This can be done by using &lt;a href="https://github.com/conventional-changelog/commitlint/tree/master"&gt;commitlint&lt;/a&gt; and more specifically with the configuration for Angular: &lt;a href="https://www.npmjs.com/package/@commitlint/config-angular"&gt;@commitlint/config-angular&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Commitlint checks if your commit messages meet the conventional commit format. This, in combination with Husky, will ensure that the team follows the Conventional Commits format.&lt;/p&gt;

&lt;p&gt;Run the following in your terminal to install commitlint with the Angular configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @commitlint/config-angular @commitlint/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a &lt;code&gt;.commitlintrc.json&lt;/code&gt; file in the root of your project which will contain the configuration for commitlint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&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;"@commitlint/config-angular"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&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;This configuration file for commitlint will by default extend from &lt;code&gt;@commitlint/config-angular&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now to enforce this with Husky, let's add a hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx husky add .husky/commit-msg &lt;span class="s2"&gt;"npx --no -- commitlint --edit &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;A &lt;code&gt;commit-msg&lt;/code&gt; hook will be created that will process your commitlint configuration to check for a valid commit message format. Now if you want to commit with a commit message that is not valid (e.g., "my faulty commit"), the commit will fail, and the output message would read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⧗   input: my faulty commit
✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]


✖   found 2 problems, 0 warnings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the &lt;code&gt;.commitlintrc.json&lt;/code&gt; file, you could have your own rules for commit message formatting. For a full list of rules, see &lt;a href="https://commitlint.js.org/#/reference-rules"&gt;here&lt;/a&gt;. &lt;br&gt;
E.g., you want to allow the type "hotfix" next to the existing types ("build", "feat",...). You could do so by adding the rule &lt;code&gt;type-enum&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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="err"&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;"@commitlint/config-angular"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type-enum"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hotfix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chore"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ci"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"feat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"perf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"refactor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"revert"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt; &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&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;blockquote&gt;
&lt;p&gt;Note: The "2" is the level. Possible values are 0 (hint), 1 (warning), and 2 (error).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is however recommended to follow the Conventional Commit specification as closely as possible. If you do have any exceptions, make sure the team is aware of them (even new team members that recently joined).&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Keep README.md up-to-date
&lt;/h2&gt;

&lt;p&gt;Keep the README.md file of the project up-to-date. Use this as a starting point for every new team member starting with the project. Even better would be to add a README.md to each folder that might require additional information and point to the README in the base README of the project. You can link to other markdown files by using the hyperlink syntax, e.g., &lt;code&gt;[a relative link](shared/README.md)&lt;/code&gt;.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Communicate with your team members.&lt;/li&gt;
&lt;li&gt;Add recommended extensions, project settings and snippets for VS Code.&lt;/li&gt;
&lt;li&gt;Add Prettier.&lt;/li&gt;
&lt;li&gt;Add linting.&lt;/li&gt;
&lt;li&gt;Add Husky hooks to enforce rules on commit or push.&lt;/li&gt;
&lt;li&gt;Use Conventional Commits.&lt;/li&gt;
&lt;li&gt;Keep the README.md up-to-date.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have any questions, feel free to contact me!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>frontend</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
