<?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: Anirban Mukherjee</title>
    <description>The latest articles on DEV Community by Anirban Mukherjee (@anirbmuk).</description>
    <link>https://dev.to/anirbmuk</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%2F657674%2Ffc1262a9-8424-48c7-b8a5-3b6652316cd3.jpeg</url>
      <title>DEV Community: Anirban Mukherjee</title>
      <link>https://dev.to/anirbmuk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anirbmuk"/>
    <language>en</language>
    <item>
      <title>Vue - build dynamic reactive form</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Sun, 13 Jul 2025 17:46:03 +0000</pubDate>
      <link>https://dev.to/anirbmuk/vue-build-dynamic-reactive-form-141g</link>
      <guid>https://dev.to/anirbmuk/vue-build-dynamic-reactive-form-141g</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/vue-dynamic-form" rel="noopener noreferrer"&gt;
        vue-dynamic-form
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Dynamic and reactive form generation using Vue3
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This article intends to demonstrate &lt;strong&gt;dynamic&lt;/strong&gt; and &lt;strong&gt;reactive&lt;/strong&gt; form generation based on user-defined configurations.&lt;/p&gt;




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




&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This is a Vue 3 application that demonstrates dynamic form generation based on user-defined configurations. The application allows users to specify how many input fields and select drop-downs they want, and then dynamically creates a form with the specified number of fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue-dynamic-form/
├── src/
│   ├── components/
│   │   ├── FormDefinition.vue    # Form configuration interface
│   │   └── FormImplementation.vue # Dynamic form renderer
│   ├── types/
│   │   └── form-definition.d.ts  # TypeScript type definitions
│   ├── App.vue                   # Main application component
│   └── main.ts                   # Application entry point
├── package.json
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Core Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Form Definition Type
&lt;/h3&gt;

&lt;p&gt;The application uses a simple type definition to specify form structure:&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;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FormDefinition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;input&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="c1"&gt;// Number of text input fields&lt;/span&gt;
  &lt;span class="nl"&gt;select&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="c1"&gt;// Number of select dropdown fields&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Component Architecture
&lt;/h3&gt;

&lt;h4&gt;
  
  
  FormDefinition.vue (Configuration Component)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Provides UI for users to specify form structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Features&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Number inputs for input and select field counts&lt;/li&gt;
&lt;li&gt;Real-time validation (minimum 0)&lt;/li&gt;
&lt;li&gt;Emits updates to parent component&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Props&lt;/strong&gt;: Receives current form definition&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Events&lt;/strong&gt;: Emits &lt;code&gt;update:form-definition&lt;/code&gt; when configuration changes&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  FormImplementation.vue (Dynamic Form Renderer)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Dynamically renders form fields based on configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Features&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Reactive field generation&lt;/li&gt;
&lt;li&gt;Memory-efficient ref management&lt;/li&gt;
&lt;li&gt;Automatic cleanup of unused fields&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dynamic Form Generation Logic
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;FormImplementation.vue&lt;/code&gt; component uses a sophisticated reactive system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reactive State Management&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Reactive state management for dynamic form fields&lt;/span&gt;
&lt;span class="c1"&gt;// objectRefs: Stores reactive refs for each form field (input-1, input-2, select-1, etc.)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objectRefs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;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="c1"&gt;// objectRefKeys: Reactive Set to track which keys currently exist&lt;/span&gt;
&lt;span class="c1"&gt;// Used for template iteration and cleanup logic&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objectRefKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reactive&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// objectRefsList: Alternative array representation of refs (currently unused)&lt;/span&gt;
&lt;span class="c1"&gt;// Could be used for bulk operations or debugging&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objectRefsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reactive&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Watcher-Based Field Management&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Watches for changes in the &lt;code&gt;count&lt;/code&gt; prop&lt;/li&gt;
&lt;li&gt;Creates new reactive refs for each required field&lt;/li&gt;
&lt;li&gt;Removes unused refs to prevent memory leaks&lt;/li&gt;
&lt;li&gt;Maintains field state across re-renders&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Field Creation Strategy&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses unique keys (&lt;code&gt;input-1&lt;/code&gt;, &lt;code&gt;input-2&lt;/code&gt;, &lt;code&gt;select-1&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Only creates new refs when they don't exist&lt;/li&gt;
&lt;li&gt;Preserves existing field values during re-renders&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Memory Management
&lt;/h3&gt;

&lt;p&gt;The application implements careful memory management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Selective Creation&lt;/strong&gt;: Only creates refs for fields that don't exist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleanup Logic&lt;/strong&gt;: Removes refs for fields no longer needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Preservation&lt;/strong&gt;: Maintains field values during configuration changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Template Rendering
&lt;/h3&gt;

&lt;p&gt;The template uses Vue's reactive system effectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Dynamic input fields --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"i in count.input"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"`input-${i}`"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"objectRefs[`input-${i}`].value"&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="c"&gt;&amp;lt;!-- Dynamic select fields --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"j in count.select"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"`select-${j}`"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"objectRefs[`select-${j}`].value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Options --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/select&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;h2&gt;
  
  
  Usage Flow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initial State&lt;/strong&gt;: Application starts with 0 input and 0 select fields&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration&lt;/strong&gt;: User adjusts counts in &lt;code&gt;FormDefinition&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Generation&lt;/strong&gt;: &lt;code&gt;FormImplementation&lt;/code&gt; component creates corresponding fields&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Updates&lt;/strong&gt;: Form updates immediately as configuration changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Persistence&lt;/strong&gt;: Field values are preserved during configuration changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Management&lt;/strong&gt;: When components are removed, the associated refs are also deleted, to prevent memory leak.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;——-&lt;/p&gt;

&lt;p&gt;Cheers :-)&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>typescript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Custom Toggle Button Vue Component</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Sat, 06 Apr 2024 10:20:11 +0000</pubDate>
      <link>https://dev.to/anirbmuk/custom-toggle-button-vue-component-35gd</link>
      <guid>https://dev.to/anirbmuk/custom-toggle-button-vue-component-35gd</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/toggle-button-vue" rel="noopener noreferrer"&gt;
        toggle-button-vue
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A toggle-button component using Vue3
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This blog post aims to create a simple Toggle-Button component with Vue3, which can also be integrated with a form, via v-model.&lt;/p&gt;

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

&lt;p&gt;Sometimes it is important to create these UI components on your own, instead of relying on heavier UI libraries. When you do this, you get to learn a few more intricate stuff, which you may ignore while using ready-made solutions, and also, you make it light-weight by excluding features you may not even need.&lt;/p&gt;




&lt;h2&gt;
  
  
  The ToggleButton Component
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Props&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;options&lt;/code&gt; (array)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;modelValue&lt;/code&gt; (string)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  options: {
    type: Array as PropType&amp;lt;KeyValue&amp;lt;string&amp;gt;[]&amp;gt;,
    required: true
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Emits&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;update:model-value&lt;/code&gt; (string)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defineEmits&amp;lt;{
  (e: 'update:model-value', value: string): void
}&amp;gt;()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's talk about the props.&lt;br&gt;
The &lt;code&gt;options&lt;/code&gt; array is a list of key-value objects, which are displayed as buttons.&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;template v-for="option of options" :key="option.value"&amp;gt;
  &amp;lt;button
    type="button"
    :class="{ selected: modelValue === option.value }"
    @click="$emit('update:model-value', option.value)"
  &amp;gt;
    {{ option.label }}
  &amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;modelValue&lt;/code&gt; prop is an interesting one. It &lt;strong&gt;should&lt;/strong&gt; be named &lt;code&gt;modelValue&lt;/code&gt; (case-sensitive), if you want this component to have a data-binding. When a custom component has this prop, and it is bound to a &lt;code&gt;v-model&lt;/code&gt;, the value flows into this component and is applied to the underlying model.&lt;/p&gt;

&lt;p&gt;If you want the component to have a 2-way data-binding, you also need to define an emit called &lt;code&gt;update:model-value&lt;/code&gt; (again, case-sensitive). You write your logic to emit this event with the new value, every time a new button is clicked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
@click="$emit('update:model-value', option.value)"
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that your component is ready for 2-way binding, you can use it in your application:&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;ToggleButton :options="options" v-model="selected" /&amp;gt;
...
const options = [
  {
    label: 'Male',
    value: 'M'
  },
  {
    label: 'Female',
    value: 'F'
  },
  {
    label: 'Diverse',
    value: 'D'
  }
] satisfies KeyValue&amp;lt;string&amp;gt;[]

const selected = ref&amp;lt;string&amp;gt;('F')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all folks. Refer to the &lt;a href="https://github.com/anirbmuk/toggle-button-vue.git" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for the complete code!&lt;/p&gt;




&lt;p&gt;&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>A unique Angular hover directive</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Wed, 22 Jun 2022 17:07:26 +0000</pubDate>
      <link>https://dev.to/anirbmuk/a-unique-angular-hover-directive-dk4</link>
      <guid>https://dev.to/anirbmuk/a-unique-angular-hover-directive-dk4</guid>
      <description>&lt;p&gt;@angular/cli: 13.3.0&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/ng-hover" rel="noopener noreferrer"&gt;
        ng-hover
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Angular 13.3.0 application to build a unique hover directive
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Again, a strange requirement at work and the engineer goes to the drawing board to stretch the framework, and &lt;code&gt;angular&lt;/code&gt; never disappoints!&lt;/p&gt;

&lt;h3&gt;
  
  
  What was needed to be done?
&lt;/h3&gt;

&lt;p&gt;When the user hovers on one part of the page, some css effect should be applied on another specified part of the page, something like this:&lt;/p&gt;

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

&lt;p&gt;Interesting, isn't it? Well there could be a million other simpler solutions, but I thought of building a custom angular directive which could be used in multiple places.&lt;/p&gt;




&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;The directive I built needed two inputs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The reference of elements on which the style is to be applied.&lt;/li&gt;
&lt;li&gt;The list of css classes to be applied.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface IGroupHover {
  elements: HTMLDivElement[];
  classList?: string | undefined;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Input() set appGroupHover(config: IGroupHover) {
  this._elements = config?.elements ? [...config?.elements] : [];
  this._classes = config?.classList?.split(' ') || [];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I have used &lt;code&gt;Tailwindcss&lt;/code&gt; for this demo, but that is just because I find it easy to use. Tailwind is no way related to the original purpose.&lt;/p&gt;

&lt;p&gt;Also, for the sake of simplicity of the demo, I have only targetted &lt;code&gt;HTMLDivElement&lt;/code&gt;, but you can extend this solution to any HTML element.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The directive utilizes &lt;code&gt;@HostListener&lt;/code&gt; for &lt;code&gt;mouseenter&lt;/code&gt; and &lt;code&gt;mouseleave&lt;/code&gt; events.&lt;/p&gt;

&lt;p&gt;On &lt;code&gt;mouseenter&lt;/code&gt;, I apply the classes to the referenced elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@HostListener('mouseenter') onMouseover() {
  if (this._elements &amp;amp;&amp;amp; this._classes) {
    for (const element of this._elements) {
      for (const userClass of this._classes) {
        userClass &amp;amp;&amp;amp; element.classList?.add?.(userClass);
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On &lt;code&gt;mouseleave&lt;/code&gt;, I remove the classes from the referenced elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@HostListener('mouseleave') onMouseleave() {
  if (this._elements &amp;amp;&amp;amp; this._classes) {
    for (const element of this._elements) {
      for (const userClass of this._classes) {
        userClass &amp;amp;&amp;amp; element.classList?.remove?.(userClass);
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And technically, this is all that the directive needs. Now let's see how to use it.&lt;/p&gt;




&lt;h3&gt;
  
  
  The implementation
&lt;/h3&gt;

&lt;p&gt;I have a grid layout of 3 columns, and I intend to hover over the middle column, while alternately applying the specified classes on the left or right columns. I have prepared a similar data-set.&lt;br&gt;
While looping through this data-set, I set a &lt;code&gt;#left&lt;/code&gt; view reference on the left column, and a &lt;code&gt;#right&lt;/code&gt; view reference on the right column.&lt;br&gt;
On the middle column, I apply the directive and pass these references and the classes I want to apply. So each middle column has its own directive instance, with its own HTMLDivElement reference and class-list to apply.&lt;/p&gt;

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

&lt;p&gt;And there you go! You can download the source code from &lt;a href="https://github.com/anirbmuk/ng-hover" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cheers :-)&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Angular lazy loading directive with IntersectionObserver</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Thu, 02 Jun 2022 12:27:27 +0000</pubDate>
      <link>https://dev.to/anirbmuk/angular-lazy-loading-directive-with-intersectionobserver-4m92</link>
      <guid>https://dev.to/anirbmuk/angular-lazy-loading-directive-with-intersectionobserver-4m92</guid>
      <description>&lt;p&gt;@angular/cli: 13.3.0&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/ng-lazy-load" rel="noopener noreferrer"&gt;
        ng-lazy-load
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Angular 13.3.0. application to demonstrate a lazy loading directive using IntersectionObserver API
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;So let's dig into lazy loading once again! Previously, I had written an article &lt;a href="https://dev.to/anirbmuk/angular-infinite-scrolling-using-rxjs-and-ngrx-4p8i"&gt;Angular infinite scrolling using RxJs and NgRx&lt;/a&gt;, which explained the concept of loading more data on reaching the end-of page. But this time, the concept is wider, or more generic.&lt;/p&gt;

&lt;p&gt;This time, I would like to reach a certain part of the viewport, and then load some data specific to that part, or maybe perform some tracking action. So I would observe a specific HTML selector and then do something when that selector comes into view. And that selector could be anywhere in the page, not just the end, something like this:&lt;/p&gt;

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

&lt;p&gt;So of course, we go for the &lt;strong&gt;IntersectionObserver&lt;/strong&gt; API. Almost all modern browsers now support it, so we should ideally have no problem for a modern website.&lt;/p&gt;

&lt;p&gt;Let us once again break down the requirements, one by one.&lt;br&gt;
1) We need a &lt;em&gt;custom directive&lt;/em&gt;, which we can place on any HTML element.&lt;br&gt;
2) This directive will accept a callback method as a parameter, so that the parent component consuming the directive can decide what to do once the child element comes into view.&lt;br&gt;
3) Tracking should happen only once, so that every time the element comes into view (due to user scrolling up and down), the data should not be re-fetched. &lt;em&gt;But this is my specific use-case, you may choose to do differently&lt;/em&gt;.&lt;br&gt;
4) The observer should be disconnected when the element is destroyed.&lt;/p&gt;


&lt;h2&gt;
  
  
  The directive:
&lt;/h2&gt;

&lt;p&gt;Whenever we place a directive on an element, we get a reference to the consuming element. And to be honest, this is all we need.&lt;br&gt;
Almost the entire logic happens in the constructor, since each directive placed on each element creates a new instance of the class.&lt;/p&gt;

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

&lt;p&gt;Let's understand what is being done:&lt;/p&gt;
&lt;h3&gt;
  
  
  The Options:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;root&lt;/strong&gt; - this essentially means the relative component against which your component - the one you would like to observe - should intersect. For our use case, this is the entire document.&lt;br&gt;
&lt;strong&gt;rootMargin&lt;/strong&gt; - this would consider if the document has some margin, so that the intersection logic would consider that during its calculation.&lt;br&gt;
&lt;strong&gt;threshold&lt;/strong&gt; - this is a value between 0 and 1 (or consider 0 and 100%). A value of 1 means, the API would consider my component to be intersecting with the document only when 100% of the element is in view. You can change this as per your need.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Intersection callback and The Observer:
&lt;/h3&gt;

&lt;p&gt;For all components we observe, the callback is executed. For our use case, we have only one target - the element on which our directive is placed. We create a new instance of &lt;code&gt;IntersectionObserver&lt;/code&gt; and assign it to an observer. This observer observes our component, which is injected into our directive class through &lt;code&gt;elementRef: ElementRef&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  So what happens next?
&lt;/h3&gt;

&lt;p&gt;Depending on the threshold value, the &lt;code&gt;entry.isIntersecting&lt;/code&gt; evaluates to true or false, and it is then that we need to do something.&lt;/p&gt;
&lt;h3&gt;
  
  
  And what do we do then?
&lt;/h3&gt;

&lt;p&gt;Our directive takes in a callback as an input, and we fire this callback - &lt;code&gt;this.appTrackable?.();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also, I mentioned before that each directive on each element is a new instance. So we maintain a class level variable - tracked. And once the intersection logic is satisfied and the callback is fired, we do not need to fire the logic again and again. You could go one step ahead and disconnect the observer itself.&lt;/p&gt;

&lt;p&gt;When the component gets destroyed, so does the directive, and you can tap onto the &lt;code&gt;ngOnDestroy&lt;/code&gt; method, to disconnect the observer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngOnDestroy(): void {
  this.observer?.disconnect();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The implementation
&lt;/h2&gt;

&lt;p&gt;The implementation means placing the directive on an element and then passing a callback reference to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;home.component.html&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;app-people [appTrackable]="callback1"&amp;gt;&amp;lt;/app-people&amp;gt;
&amp;lt;app-place [appTrackable]="callback2"&amp;gt;&amp;lt;/app-place&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The callback methods include some logic to fire HTTP calls to fetch data for that element, but that is not what this article is about and so I will not go into its details. But you can always check it out from &lt;a href="https://github.com/anirbmuk/ng-lazy-load" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. &lt;em&gt;Just remember to bind your callback to the service or class instance, as applicable.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;home.component.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class HomeComponent {
  constructor(private readonly data: DataService) {}

  readonly callback1 = this.data.callback.bind(this.data, 'people');
  readonly callback2 = this.data.callback.bind(this.data, 'places');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  So what are the possibilites?
&lt;/h2&gt;

&lt;p&gt;Well you can do whatever you want with the callback thingy! But, I would say, tracking for analytics is one very important use case. You can also use this to execute infinite loading on scroll. Let me know in the comments if you can come up with more use cases!&lt;/p&gt;

&lt;p&gt;Cheers :-)&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>angular</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Handle CAPS-LOCK on/off event in Angular</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Sat, 07 May 2022 20:58:06 +0000</pubDate>
      <link>https://dev.to/anirbmuk/handle-caps-lock-onoff-event-in-angular-52go</link>
      <guid>https://dev.to/anirbmuk/handle-caps-lock-onoff-event-in-angular-52go</guid>
      <description>&lt;p&gt;This is an interesting, yet quite commonly expected, use-case - warn the user that the CAPS-LOCK is ON, specially while entering a password, so that the user is aware of it and can change it, if needed.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/ng-capslock-demo" rel="noopener noreferrer"&gt;
        ng-capslock-demo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Angular 13.3.0 application to demonstrate how to display CAPS-LOCK-ON/OFF message
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;There are a few scenarios handled in this demonstration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Change the message when the user toggles the caps-lock while on the password field.&lt;/li&gt;
&lt;li&gt;Also change the message when the user changes the caps-lock state elsewhere (maybe in another application or browser tab, etc) and then comes back to this application.&lt;/li&gt;
&lt;li&gt;Remove the events when component is destroyed, to prevent memory leaks.&lt;/li&gt;
&lt;li&gt;Run change-detection when &lt;code&gt;ChangeDetectionStrategy&lt;/code&gt; is &lt;code&gt;OnPush&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Let's see about 1 &amp;amp; 2.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By the way, I am on @angular/cli 13.3.0 and @angular/material 13.3.6. For the message, I have used &lt;code&gt;mat-hint&lt;/code&gt; on &lt;code&gt;mat-form-field&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To achieve this, we grab the reference of the password field (using &lt;code&gt;@ViewChild&lt;/code&gt;) and then add a couple of event handlers to the underlying &lt;code&gt;HTMLInputElement&lt;/code&gt; - &lt;code&gt;keyup&lt;/code&gt; and &lt;code&gt;mousedown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;keyup&lt;/code&gt; event handler will toggle the message when the user toggles the CAPS-LOCK button while being on the password field. This generates a &lt;code&gt;KeyboardEvent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mousedown&lt;/code&gt; event handler will toggle the message when the user changes the state elsewhere and the navigates back to the application and clicks on the password field. This will be beneficial for the user since the information is now provided even before something is typed. This is done through a &lt;code&gt;MouseEvent&lt;/code&gt;.&lt;/p&gt;

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




&lt;h3&gt;
  
  
  Some improvements:
&lt;/h3&gt;

&lt;p&gt;To prevent memory leaks, we need to remove these event handlers once the component is destroyed.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7a1mdf49f3qo06ojom2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7a1mdf49f3qo06ojom2z.png" alt="ngOnDestroy" width="520" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;ChangeDetectionStrategy&lt;/code&gt; is set to &lt;code&gt;OnPush&lt;/code&gt;, we need to mark the component for a change detection whenever either of the above events are fired. So, at the end of the event handler, use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.cdRef.markForCheck();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser's password manager may auto-fill the password data for you. This will also fire a &lt;code&gt;keyup&lt;/code&gt; event, but this will not be an instance of &lt;code&gt;KeyboardEvent&lt;/code&gt; and will thus not have the &lt;code&gt;getModifierState&lt;/code&gt; method. So we will ignore this!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (event?.type === 'keyup' &amp;amp;&amp;amp; !(event instanceof KeyboardEvent)) {
  return;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cheers!&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>event</category>
      <category>material</category>
    </item>
    <item>
      <title>Angular material cross field form validation</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Mon, 21 Feb 2022 08:05:56 +0000</pubDate>
      <link>https://dev.to/anirbmuk/angular-material-cross-field-form-validation-45nn</link>
      <guid>https://dev.to/anirbmuk/angular-material-cross-field-form-validation-45nn</guid>
      <description>&lt;p&gt;@angular/cli - 12.0.1&lt;br&gt;
@angular/material - 12.0.1&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/MaterialFormDemo" rel="noopener noreferrer"&gt;
        MaterialFormDemo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Angular material cross field form validation
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This article talks about performing field-level validations across a reactive form using Angular material. The solution aims to perform cross-field form validation and then display the error as mat-error for a selected field.&lt;/p&gt;

&lt;p&gt;This is how it would be:&lt;/p&gt;

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

&lt;p&gt;Both the errors shown above are registered on the FormGroup. But the goal is to display them as mat-error on certain fields.&lt;/p&gt;

&lt;p&gt;So how do we do this? To begin with, let's set up the form and the corresponding cross-field validations.&lt;/p&gt;

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

&lt;p&gt;And we are set up in terms of the code required for the validation part. But how do we display the error as mat-error for a specific field? The mat-error only displays error when the specific field is in an error state. But our requirement is to mark it invalid when the form is invalid (and not just the specific field).&lt;/p&gt;

&lt;p&gt;To achieve this, we use an interface called &lt;code&gt;ErrorStateMatcher&lt;/code&gt;. This interface implements a method &lt;code&gt;isErrorState&lt;/code&gt;, where we can write the logic to mark a form-control as invalid.&lt;/p&gt;

&lt;p&gt;We create a class which implements this interface, and then create two instances of this class to use for the two validation methods.&lt;/p&gt;

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

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

&lt;p&gt;Now we map these instances to the fields on which we would want to see the mat-errors.&lt;/p&gt;

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

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

&lt;p&gt;The &lt;strong&gt;[errorStateMatcher]&lt;/strong&gt; properties are mapped to the respective class instances, which allow the respective fields to be invalid and show mat-error once the form becomes invalid.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>material</category>
    </item>
    <item>
      <title>Global error page in Angular</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Sun, 16 Jan 2022 12:55:24 +0000</pubDate>
      <link>https://dev.to/anirbmuk/global-error-page-in-angular-3744</link>
      <guid>https://dev.to/anirbmuk/global-error-page-in-angular-3744</guid>
      <description>&lt;p&gt;This is a relatively small and simple article, but I felt it is still worth posting because of the utility of the topic.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/angular-error-handler" rel="noopener noreferrer"&gt;
        angular-error-handler
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Angular 12 application to demonstrate global error handling against a REST-based backend
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Any front-end application is all about serving data from a store, using end-points (REST/GraphQL or whichever you can think of). And a big part of your application's success is the way you can handle errors. The more gracefully you handle error situations, the better your users' experience will be.&lt;/p&gt;

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

&lt;p&gt;On that note, let's talk about an approach to handle all sorts of errors in an Angular application.&lt;/p&gt;

&lt;p&gt;The idea behind this article is to manage all possible errors in one location and allow the application to navigate to an &lt;code&gt;error-page&lt;/code&gt; once any error is thrown. Now I would like to clarify that when I say error, I mean server side errors, emanating from your data end-points.&lt;/p&gt;

&lt;p&gt;To do this, we will make use of the one place through which every &lt;code&gt;HTTP&lt;/code&gt; request passes in an angular application - the &lt;code&gt;interceptor&lt;/code&gt;. We usually make use of the interceptor to tap outgoing requests and append headers, tokens etc. But we can also tap onto the incoming response and handle the error situations.&lt;/p&gt;

&lt;p&gt;When the &lt;code&gt;next: HttpHandler&lt;/code&gt; handles the request, the request is sent to the back-end server. We can pipe the observable to tap onto the incoming response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interceptor.service.ts:
intercept(
    req: HttpRequest&amp;lt;any&amp;gt;,
    next: HttpHandler
  ): Observable&amp;lt;HttpEvent&amp;lt;any&amp;gt;&amp;gt; {
    return next.handle(req).pipe(
      catchError((error) =&amp;gt; {
        const { code, message } = error.error;
        this.errorService.addError({
          code: code || error?.status,
          message: message || error?.statusText,
        });
        this.router.navigate(['/error']);
        return EMPTY;
      })
    );
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also navigate to our designated error page, which is designed to handle the error code and message and display it appropriately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional improvisation&lt;/strong&gt;: Use a &lt;code&gt;resolver&lt;/code&gt; for the error component and check if the error observable has any value. If not then redirect to the home-page. This may be helpful when the user refreshes the error page; then it would make more sense to be taken to the home page to try again, instead of showing the same error once again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error.resolver.ts:
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.errorService.error$.pipe(
      take(1),
      tap((data) =&amp;gt; {
        if (!data) {
          throw new Error('No error');
        }
      }),
      catchError(() =&amp;gt; {
        this.router.navigate(['/']);
        return of(null);
      })
    );
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cheers!&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>errors</category>
    </item>
    <item>
      <title>Custom angular form component</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Sat, 14 Aug 2021 14:16:41 +0000</pubDate>
      <link>https://dev.to/anirbmuk/custom-angular-form-component-57mf</link>
      <guid>https://dev.to/anirbmuk/custom-angular-form-component-57mf</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/CustomFormElement" rel="noopener noreferrer"&gt;
        CustomFormElement
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Angular 12 application for custom form element
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Most of our application requirements are fulfilled using standard HTML elements. However, we may sometimes need to stretch ourselves when we are working for large enterprise applications. In such cases, reusability becomes a strong factor which determines ease of development. Today's use case is one such custom requirement.&lt;/p&gt;

&lt;p&gt;This article speaks about creating an Angular component which acts as a lookup - an input field with a search button. The button opens up a modal window, which shows a list of values from which the user may select one. &lt;em&gt;&lt;strong&gt;Additionally, this new component should also angular-form-ready, which means, it should be capable enough to be registered as a template-driven or reactive form element.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Let's first talk about the component itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94nuovcejg5ev73ylg6c.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94nuovcejg5ev73ylg6c.JPG" alt="The GUI" width="599" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkq3wqcch45ads6947e9f.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkq3wqcch45ads6947e9f.JPG" alt="app.component.html" width="753" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;&lt;strong&gt;app-lookup&lt;/strong&gt;&lt;/em&gt; component takes in a couple of inputs - formConfig and lookupConfig. A sample implementation is shown below:&lt;/p&gt;

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

&lt;p&gt;When user clicks on the search button, a modal window opens with data fetched from server (in my case a simple promise). Use selects a record and clicks select. The data gets populated on the input form.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F69rxfnyy3y5uvydn7vhi.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F69rxfnyy3y5uvydn7vhi.JPG" alt="Submitted form 1" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;&lt;strong&gt;allowUnlistedValue&lt;/strong&gt;&lt;/em&gt; is set as true, the user will be able to enter a value which does not exist in the list, and the value will be accepted. If not, then the form element will return empty value.&lt;/p&gt;

&lt;p&gt;So this is all about describing the component.&lt;/p&gt;




&lt;h3&gt;
  
  
  Now let's see how to set it up
&lt;/h3&gt;

&lt;p&gt;We need to extend this component so that Angular recognizes this as a valid form element. Since this element is of input type, I have implemented the interface &lt;strong&gt;&lt;code&gt;ControlValueAccessor&lt;/code&gt;&lt;/strong&gt;. This interface needs to implement 3 methods - &lt;code&gt;writeValue&lt;/code&gt;, &lt;code&gt;registerOnChange&lt;/code&gt; and &lt;code&gt;registerOnTouched&lt;/code&gt;.&lt;br&gt;
The &lt;code&gt;writeValue&lt;/code&gt; method is the one which is responsible to writing your value to the view from your model.&lt;br&gt;
&lt;code&gt;registerOnChange&lt;/code&gt; is used to propagate changes from your model to the view. This is how the form knows that one of its members has changed its value.&lt;br&gt;
&lt;code&gt;registerOnTouched&lt;/code&gt; is used to let the wrapper form element know that one of its elements has been marked as touched.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error handling
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Question&lt;/code&gt;: Now that we are done with setting up the value read/write operations, how about error handling? How do we let the wrapping angular form know if our custom component has an error and needs to be marked as invalid?&lt;br&gt;
&lt;code&gt;Answer&lt;/code&gt;: To do this, we inject an instance of &lt;code&gt;NgControl&lt;/code&gt; into the component, which gives us the &lt;code&gt;FormControl&lt;/code&gt; instance. It is this form-control object which sets the errors in the component conditionally. Remember, it is a custom component, so everything needs to be set by us :-)&lt;br&gt;
&lt;code&gt;Note&lt;/code&gt;: The &lt;code&gt;ErrorStateMatcher&lt;/code&gt; has nothing to do with this implementation, but it is more for the material input component. &lt;code&gt;ErrorStateMatcher&lt;/code&gt; marks the component in red when it has an error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x824oo1b1g60vnw3pmp.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1x824oo1b1g60vnw3pmp.JPG" alt="NgControl" width="389" height="158"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7qoxn4oa60almg0mx0b.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7qoxn4oa60almg0mx0b.JPG" alt="Error handling" width="414" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result, if &lt;em&gt;&lt;strong&gt;allowUnlistedValue&lt;/strong&gt;&lt;/em&gt; is set as false, the user will not be able to enter a value which does not exist in the list, and the component (and subsequently the form) will be marked as invalid. This is demonstrated by disabling the Submit button when form is invalid!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2j3u605hq6my6fz78vm.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2j3u605hq6my6fz78vm.JPG" alt="Submitted form 2" width="396" height="353"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Do note: A much more in-depth set of instructions for creating custom form elements can be found in a blog by &lt;a href="https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html" rel="noopener noreferrer"&gt;Pascal Precht&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And there you go. You have your own angular component ready to be used in a form! You can download the source code from &lt;a href="https://github.com/anirbmuk/CustomFormElement" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and play around with the configurations.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>controlvalueaccessor</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Angular dynamic components with code-splitting</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Tue, 03 Aug 2021 15:53:16 +0000</pubDate>
      <link>https://dev.to/anirbmuk/angular-dynamic-components-with-code-splitting-43ij</link>
      <guid>https://dev.to/anirbmuk/angular-dynamic-components-with-code-splitting-43ij</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/cms-components-demo" rel="noopener noreferrer"&gt;
        cms-components-demo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Angular 12 application to demonstrate code-splitting
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;A lot of times, angular components need to be determined and displayed on the fly. A very common use-case is when the components are determined from a content-management-system (CMS). This is particularly useful when we allow the customer to control the content and layout of the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboaoww1o4dj4y1da1ebh.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboaoww1o4dj4y1da1ebh.JPG" alt="CMS content layout" width="551" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well we do have &lt;code&gt;*ngIf&lt;/code&gt; for that, don't we? Depending on some CMS field value, we can use &lt;code&gt;*ngIf&lt;/code&gt; to determine which component needs to be displayed. This is cool, but there is a major downside to this approach. The problem is, we usually have a large component library, which need to be loaded eagerly in its entirety through one or more &lt;code&gt;modules&lt;/code&gt;. So even if only a fraction of these components may be needed by the customer, we would have to pre-load all of them, which is an unnecessary waste of resources.&lt;/p&gt;

&lt;p&gt;So what are we talking about here? &lt;strong&gt;How about a way where we load only those components out of our library which are required by the customer?&lt;/strong&gt; This is where the concept of &lt;em&gt;&lt;strong&gt;code-splitting&lt;/strong&gt;&lt;/em&gt; comes into use.&lt;/p&gt;

&lt;p&gt;Using code-splitting, we conditionally &lt;strong&gt;import&lt;/strong&gt; the required components at run-time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foa9bzx428ap26t8wpro4.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foa9bzx428ap26t8wpro4.JPG" alt="Lazy loading" width="278" height="426"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvl1l5b4o133vg9hm9zu.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvl1l5b4o133vg9hm9zu.JPG" alt="Lazy Loading" width="547" height="269"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;h3&gt;
  
  
  The Setup
&lt;/h3&gt;

&lt;p&gt;Let's see how to go about it. I have created a few simple custom angular components, which are to be conditionally loaded. So, as expected, these components are &lt;strong&gt;NOT&lt;/strong&gt; part of any application module.&lt;/p&gt;

&lt;p&gt;We need to remember that the entire operation is driven by CMS data. So we need some mechanism to evaluate this data at run-time to determine the components.&lt;/p&gt;

&lt;p&gt;So we would need a &lt;code&gt;custom structural directive&lt;/code&gt; for this. This directive would dynamically create the component instances and inject them into the DOM. Let's first look at the HTML needed at the implementation side, using this directive:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1lqpy0qpsqceggyiums7.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1lqpy0qpsqceggyiums7.JPG" alt="Sample CMS Data" width="800" height="558"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35hvxdwdfvxnstdzykpf.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35hvxdwdfvxnstdzykpf.JPG" alt="Customer Code" width="560" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's take a look at the custom structural directive:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7m7zgnjazfb2q1c05wux.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7m7zgnjazfb2q1c05wux.JPG" alt="Custom Structural Directive" width="746" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most interesting bit is the &lt;strong&gt;import&lt;/strong&gt; statement (line 25). Based on the CMS content, I only import that particular module and component. This is a huge advantage in terms of app-performance, since we do not have to load a module unless it is explicitly asked for, much like a lazily loaded route! When I place this directive on a designated location in the DOM (the &lt;code&gt;ng-container&lt;/code&gt; in this case), I get access to that location's reference, through &lt;code&gt;ViewContainerRef&lt;/code&gt;. I make use of angular's &lt;code&gt;ComponentFactoryResolver&lt;/code&gt; API to build an instance of our required component and the &lt;em&gt;viewContainerRef&lt;/em&gt; injects this component instance at that designated spot.&lt;/p&gt;

&lt;h4&gt;
  
  
  A small, but very important, GOTCHA!
&lt;/h4&gt;

&lt;p&gt;Since our custom components are not included in any module, or any eager import statements, the angular compiler will exclude these &lt;strong&gt;.ts&lt;/strong&gt; files from compilation. To forcefully compile them, so that they can be used at run-time, we need to tell &lt;code&gt;tsconfig.app.json&lt;/code&gt; to include these files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuadvua1sauqrsc8fv98b.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuadvua1sauqrsc8fv98b.JPG" alt="tsconfig.app.json" width="267" height="301"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Cheers!&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Angular infinite scrolling using RxJS and NgRx</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Wed, 21 Jul 2021 14:51:21 +0000</pubDate>
      <link>https://dev.to/anirbmuk/angular-infinite-scrolling-using-rxjs-and-ngrx-4p8i</link>
      <guid>https://dev.to/anirbmuk/angular-infinite-scrolling-using-rxjs-and-ngrx-4p8i</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/angular-scroll-demo" rel="noopener noreferrer"&gt;
        angular-scroll-demo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Angular 12 application to demonstrate infinite scrolling with RxJS and NgRx
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I have seen multiple blog posts on this topic which make use of one method or the other. I just thought of putting everything together under one hood - &lt;code&gt;RxJS&lt;/code&gt;, &lt;code&gt;NgRx&lt;/code&gt;, &lt;code&gt;Angular Material&lt;/code&gt; and in the end, pure &lt;strong&gt;document&lt;/strong&gt; property access. This is what is leads to:&lt;/p&gt;

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

&lt;p&gt;Let's quickly talk about the setup here - I am using an Angular &lt;code&gt;CLI 12.1.0&lt;/code&gt; project. I have &lt;code&gt;NgRx&lt;/code&gt; state management set up, with a root state and a feature state. Of course, NgRx is in no way related to the purpose of this application, but I just thought it would not hurt to implement it. We have to admit, as your application grows in size, NgRx does give you some peace of mind :-)&lt;/p&gt;

&lt;p&gt;The UI is built using &lt;code&gt;angular material&lt;/code&gt;. I have used the mat-list and and the mat-spinner components. I have some hard-coded dummy data, which I have converted into an observable stream, with a delay of 1500 ms, which gives some feeling of having fetched data from a REST service.&lt;/p&gt;

&lt;p&gt;The key logic is to calculate when the user has scrolled down to the edge of the page. I chose a simple formula derived from the document object. Of course there are other fancy approaches like using an &lt;code&gt;IntersectionObserver&lt;/code&gt;, but that's something I felt was too much for me!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgctg6k1yrs6rmebzhmsg.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgctg6k1yrs6rmebzhmsg.PNG" alt="data.service.ts" width="282" height="83"&gt;&lt;/a&gt;&lt;br&gt;
The above formula works great on a desktop, as well as a mobile - but feel free to drop me a note if it doesn't.&lt;/p&gt;

&lt;p&gt;I set up the scroll action using RxJS &lt;code&gt;fromEvent&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmmvqvje4looz5lg7d4i.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmmvqvje4looz5lg7d4i.PNG" alt="data.service.ts" width="484" height="21"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the scroll event is set up, whenever the above formula is satisfied, the next set of data is called for. For my sample use case, I have used a limit and skip value, which I have used to slice off a chunk from my dummy data set. Every time a new set is emitted by my data observable, I have made use of a reducer function to append it to my previous list of data.&lt;/p&gt;

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

&lt;p&gt;This is where I store the next limit and skip values for the next data load, and also make a simple calculation of whether my data load is complete, and set it on my state. Once this flag becomes true, subsequent scroll actions do not trigger any more data fetch.&lt;/p&gt;

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

&lt;p&gt;Cheers :-)&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>rxjs</category>
      <category>ngrx</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Auto-complete with material and RxJS</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Sat, 03 Jul 2021 14:56:36 +0000</pubDate>
      <link>https://dev.to/anirbmuk/auto-complete-with-angular-material-and-rxjs-3b8k</link>
      <guid>https://dev.to/anirbmuk/auto-complete-with-angular-material-and-rxjs-3b8k</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anirbmuk" rel="noopener noreferrer"&gt;
        anirbmuk
      &lt;/a&gt; / &lt;a href="https://github.com/anirbmuk/AutocompleteDemo" rel="noopener noreferrer"&gt;
        AutocompleteDemo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Autocomplete feature with RxJS and angular material
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This article talks about an efficient way to implement auto-complete feature using Angular concepts. The key components used in this demonstration are as follows:&lt;br&gt;
 &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Angular Material (v15) Autocomplete module.&lt;/li&gt;
&lt;li&gt;RxJS for action and data binding.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I have used &lt;a href="https://dummyjson.com/" rel="noopener noreferrer"&gt;Dummy-JSON&lt;/a&gt; for getting fake JSON data.&lt;/p&gt;

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

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

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

&lt;p&gt;Let us now see how we go about it:&lt;br&gt;
 &lt;/p&gt;

&lt;h1&gt;
  
  
  The UI:
&lt;/h1&gt;

&lt;p&gt;The front-end consists of an angular autocomplete module. The input event taps the user's keystrokes and emits a new value into an action subject.&lt;/p&gt;

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

&lt;p&gt;Each key-stroke emits a new value into an action subject declared in the &lt;code&gt;ProductService&lt;/code&gt; class.&lt;/p&gt;

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

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

&lt;h1&gt;
  
  
  The Service:
&lt;/h1&gt;

&lt;p&gt;I selected a &lt;code&gt;Subject&lt;/code&gt;, since I want it emit a value only when the user starts to type. The &lt;code&gt;action$&lt;/code&gt; is an &lt;code&gt;observable&lt;/code&gt; built out of this subject.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyzdpz2hrwjv0er4vkp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyzdpz2hrwjv0er4vkp7.png" alt="autocomplete.service.ts 1" width="478" height="104"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;br&gt;
Every time a new value is emitted into the action stream, it returns an observable from the http &lt;code&gt;GET&lt;/code&gt; request. Since this is a higher-order observable (i.e., an observable returning an observable), we make use of one of the higher order functions like &lt;code&gt;switchMap&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;So why &lt;code&gt;switchMap&lt;/code&gt; (and not other higher order functions like &lt;code&gt;concatMap&lt;/code&gt; or &lt;code&gt;mergeMap&lt;/code&gt;)? The reason is: &lt;code&gt;switchMap&lt;/code&gt; unsubscribes from the previous observable once a new value is emitted by the parent observable.&lt;/p&gt;

&lt;p&gt;What this means is - as soon as the user types in another letter or removes a letter, there is simply no need to subscribe and execute the rest call for the previous values. The user is only interested to see the results of the search according to his/her current input. And &lt;code&gt;switchMap&lt;/code&gt; does this automatically, and thus gets rid of unwanted rest calls.&lt;/p&gt;

&lt;p&gt;We can also get additional control on when to fire the rest service depending on the length of the user's input. For example, in this demo, I fire the rest call only when the user has entered at least 2 characters. If not, then I return an observable of empty array (using &lt;code&gt;of([])&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;distinctUntilChanged&lt;/code&gt; operator to exclude user inputs which have not changed during the debounce period. So the http call will only fire for new input values, and not if the user quickly changed the input and reverted to the old value.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Back to the Component:
&lt;/h1&gt;

&lt;p&gt;We tap onto the above observable and use &lt;code&gt;async pipe&lt;/code&gt; to subscribe to it. Since we are completely using observables, we can also use the &lt;code&gt;OnPush&lt;/code&gt; change-detection-strategy.&lt;/p&gt;

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

&lt;p&gt;And that is all :-)  &lt;/p&gt;

&lt;p&gt;@angular/cli - 15.2.8&lt;br&gt;
@angular/material - 15.2.9&lt;br&gt;&lt;br&gt;
Source: &lt;a href="https://github.com/anirbmuk/AutocompleteDemo.git" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers :-)&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>rxjs</category>
      <category>material</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Faster angular universal with PWA</title>
      <dc:creator>Anirban Mukherjee</dc:creator>
      <pubDate>Thu, 01 Jul 2021 02:00:16 +0000</pubDate>
      <link>https://dev.to/anirbmuk/faster-angular-universal-with-pwa-4lcm</link>
      <guid>https://dev.to/anirbmuk/faster-angular-universal-with-pwa-4lcm</guid>
      <description>&lt;p&gt;This article speaks about an interesting side-effect of mixing angular universal with progressive web application (pwa) - and that's a massive performance boost!&lt;br&gt;
 &lt;/p&gt;
&lt;h3&gt;
  
  
  The Setup
&lt;/h3&gt;

&lt;p&gt;--&lt;br&gt;
Let's start by creating a standard angular-cli application (v12.1.0 in my case). I enable SSR (angular universal) on that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng add @nguniversal/express-engine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once this is done, let's quickly check if SSR is working as per our expectation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build:ssr &amp;amp;&amp;amp; npm run serve:ssr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Node server fires up on port &lt;code&gt;4000&lt;/code&gt; and I check for my webpage's source.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;view-source:http://localhost:4000/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflvbc1rht8js94alxv2m.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fflvbc1rht8js94alxv2m.JPG" alt="SSR" width="800" height="82"&gt;&lt;/a&gt;&lt;br&gt;
Wonderful! Nothing fancy so far, and everything works great! CLI application works and universal works.&lt;br&gt;
 &lt;br&gt;
The next step is to add PWA support.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng add @angular/pwa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No extra configurations so far, and that's how it will be. Let's build our universal application once again and serve it on &lt;code&gt;localhost:4000&lt;/code&gt;.&lt;br&gt;
 &lt;br&gt;
&lt;strong&gt;&lt;code&gt;But wait!!!&lt;/code&gt;&lt;/strong&gt; Now when I view my webpage source on the browser, I get this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft5cf4nckc11h86hol56c.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft5cf4nckc11h86hol56c.JPG" alt="SSR with PWA" width="800" height="71"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;So does this mean that my SSR is broken?&lt;/em&gt;&lt;br&gt;
 &lt;br&gt;
The answer is &lt;strong&gt;Nope! My SSR is perfectly fine :-)&lt;/strong&gt; Let's run a quick check to prove this. Open up POSTMAN and run a &lt;code&gt;GET&lt;/code&gt; request against &lt;code&gt;http://localhost:4000&lt;/code&gt;. And voila! I see my server-side-rendered page once again!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft66k0w3snhzl6dot2lcy.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft66k0w3snhzl6dot2lcy.JPG" alt="POSTMAN" width="769" height="328"&gt;&lt;/a&gt;&lt;br&gt;
So what is happening here?&lt;br&gt;
 &lt;br&gt;
 &lt;/p&gt;

&lt;h3&gt;
  
  
  The conclusion and explanation
&lt;/h3&gt;

&lt;p&gt;--&lt;br&gt;
The reason why we do not see the server-rendered content on the browser source is that, the &lt;code&gt;index.html&lt;/code&gt; is now cached by service-worker at the browser. &lt;em&gt;&lt;strong&gt;The browser does not need to wait for the server to render the content any more, and it simply serves the cached version&lt;/strong&gt;&lt;/em&gt;, and &lt;strong&gt;Angular&lt;/strong&gt; takes over thereafter, like a normal SPA. Open up &lt;code&gt;ngsw-config.json&lt;/code&gt; and verify that &lt;code&gt;index.html&lt;/code&gt; is one of the cached resources.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdc36kwtedpid369zp69.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdc36kwtedpid369zp69.JPG" alt="ngsw-config.json" width="201" height="210"&gt;&lt;/a&gt;&lt;br&gt;
The search-engines/crawlers, on the other hand, would see your website just the way POSTMAN sees it, and will continue to have the entire generated HTML for search-engine-optimization. So this way, you gain the performance boost via service-worker caching, without losing the advantages of angular universal!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note (and a small exercise)&lt;/strong&gt;: If you remove &lt;code&gt;index.html&lt;/code&gt; from &lt;code&gt;ngsw-config.json&lt;/code&gt; and re-build your universal, you would see that the server-rendered content is back on your browser source, since the HTML is now no longer being cached!&lt;br&gt;
 &lt;br&gt;
Cheers -:)&lt;br&gt;
&lt;a href="https://anirbmuk.appspot.com/en" rel="noopener noreferrer"&gt;Anirban Mukherjee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>pwa</category>
      <category>javascript</category>
      <category>universal</category>
    </item>
  </channel>
</rss>
