<?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: Aakash Goplani</title>
    <description>The latest articles on DEV Community by Aakash Goplani (@aakashgoplani).</description>
    <link>https://dev.to/aakashgoplani</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%2F762073%2F1c5f508c-a071-45ef-9d97-41fef941e2b5.jpeg</url>
      <title>DEV Community: Aakash Goplani</title>
      <link>https://dev.to/aakashgoplani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aakashgoplani"/>
    <language>en</language>
    <item>
      <title>Comprehensive Guide to SvelteKitAuth: Secure Authentication for SvelteKit Apps</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sun, 14 Jul 2024 17:02:00 +0000</pubDate>
      <link>https://dev.to/playfulprogramming/comprehensive-guide-to-sveltekitauth-secure-authentication-for-sveltekit-apps-227k</link>
      <guid>https://dev.to/playfulprogramming/comprehensive-guide-to-sveltekitauth-secure-authentication-for-sveltekit-apps-227k</guid>
      <description>&lt;p&gt;I've been working on an exciting series about authentication in SvelteKit using SvelteKitAuth. This comprehensive guide covers everything from the basics of SvelteKitAuth and its configuration to how it operates under the hood. You'll find detailed steps for integrating built-in providers like Auth0, as well as custom providers. The series also delves into sign-in and sign-out flows, session management, and advanced configurations such as callbacks, events, and custom pages. My goal is to simplify the authentication process in SvelteKit applications, making it both secure and efficient. Here's what you'll learn:&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 1: Introduction to SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;SvelteKitAuth is an extension of NextAuth, now part of the Auth.js project, providing robust authentication for SvelteKit applications. It supports OAuth and OpenID Connect with 68+ providers like Google and Facebook, and offers various authentication methods including email/passwordless and username/password. SvelteKitAuth handles the entire authentication flow, from configuration to session management, and can use database sessions or JWT. It also includes built-in security features like CSRF protection and server-only cookies, making it a comprehensive solution for integrating authentication in SvelteKit apps. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/introduction-to-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 1(b): How OAuth Operates: A Simple Breakdown
&lt;/h4&gt;

&lt;p&gt;OAuth is a secure way for websites to share information without giving full access. It involves a user granting permission to a website to access specific information from another account (like Google) without sharing passwords. OAuth with PKCE adds extra security by using a secret code to ensure only the legitimate app can access the information. This process enhances security and convenience for users. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/how-oauth-operates-a-simple-breakdown" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 2: Setting Up Auth0 and Adding SvelteKitAuth to Your App
&lt;/h4&gt;

&lt;p&gt;Integrate SvelteKitAuth with SvelteKit using Auth0 by first setting up an Auth0 application. Configure the application with appropriate callback URLs and allowed web origins. Then, choose between using built-in OAuth providers like Auth0 for ease and security or custom OAuth providers for more control and customization. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/setting-up-auth0-and-adding-sveltekitauth-to-your-app" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 3: Step-by-Step Guide to Using built-in (Auth0) OAuth provider with SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;Integrate Auth0 OAuth with SvelteKitAuth by configuring essential properties like &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;clientId&lt;/code&gt;, &lt;code&gt;clientSecret&lt;/code&gt;, and &lt;code&gt;issuer&lt;/code&gt;. Place the authentication code in &lt;code&gt;hooks.server.ts&lt;/code&gt; to ensure secure access to protected resources. Advanced options like &lt;code&gt;callbacks&lt;/code&gt;, &lt;code&gt;logger&lt;/code&gt;, and &lt;code&gt;events&lt;/code&gt; can enhance the developer experience. Set necessary environment variables for a streamlined authentication process. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/step-by-step-guide-to-using-built-in-auth0-oauth-provider-with-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 4: Step-by-Step Guide to using custom OAuth provider with SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;Integrating a custom OAuth provider with SvelteKitAuth allows for extensive customization in your authentication mechanism. This guide covers the necessary configurations, including &lt;code&gt;authorization&lt;/code&gt;, &lt;code&gt;token&lt;/code&gt;, and &lt;code&gt;userinfo&lt;/code&gt; properties, to tailor the authentication process to your needs. The article also provides a code snippet for the custom provider and emphasizes the flexibility of including multiple providers in the same configuration. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/step-by-step-guide-to-using-custom-oauth-provider-with-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 5: How to Integrate Multiple OAuth Providers in SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;Integrating multiple OAuth providers in SvelteKitAuth enhances user experience by offering diverse sign-in options like Google, GitHub, and LinkedIn. This flexibility improves user convenience and broadens the potential user base. The article provides a step-by-step guide to configure multiple providers, ensuring a smooth and secure authentication process. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/how-to-integrate-multiple-oauth-providers-in-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 6: Enhancing SvelteKitAuth with Custom Type Additions
&lt;/h4&gt;

&lt;p&gt;Enhancing SvelteKitAuth with custom types involves creating a custom typings file, updating the TypeScript configuration, and restarting your IDE to ensure all necessary types are recognized, reducing errors and improving code quality. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/enhancing-sveltekitauth-with-custom-type-additions" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 7: Streamlining Client-Side Sign-In and Sign-Out Processes
&lt;/h4&gt;

&lt;p&gt;In this article, we explore how to streamline client-side sign-in and sign-out processes using SvelteKitAuth. We cover the &lt;code&gt;signIn()&lt;/code&gt; and &lt;code&gt;signOut()&lt;/code&gt; methods from &lt;code&gt;@auth/sveltekit/client&lt;/code&gt;, detailing their properties and options for a seamless user experience. The article also provides links to official documentation and a GitHub repository for further reference. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/streamlining-client-side-sign-in-and-sign-out-processes" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 8: Optimizing Server-Side Login and Logout Processes
&lt;/h4&gt;

&lt;p&gt;Optimizing server-side login and logout processes involves using form actions provided by &lt;code&gt;@auth/sveltekit&lt;/code&gt; or programmatically handling authentication, especially when using third-party vendors. The sign-in flow includes preparing a payload, making a POST call, and redirecting users, while the sign-out flow requires reloading the page after logging out. Understanding both client-side and server-side authentication ensures robust and flexible mechanisms in applications. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/optimizing-server-side-login-and-logout-processes" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 9: User Sign Out: Application vs OAuth Provider
&lt;/h4&gt;

&lt;p&gt;In this article, we discussed the differences between signing out a user from the Application layer and the OAuth layer. We explained how SvelteKitAuth handles user sign-out by clearing the session token and resetting the session, while the OAuth provider's session remains active. We also provided a method to log out users from the OAuth provider's session layer using the OIDC endpoint and emphasized the importance of configuring the Allowed Logout URLs in Auth0 for a secure and seamless user experience. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/user-sign-out-application-vs-oauth-provider" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 10: How to Manage Sessions in SvelteKit with SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;Managing sessions in SvelteKit with SvelteKitAuth involves server-side session management using the &lt;code&gt;auth()&lt;/code&gt; method to access user information and session expiration details, and client-side session management using the &lt;code&gt;$page&lt;/code&gt; store for component-level and route-level authorization checks. This ensures secure and efficient session handling in SvelteKit applications. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/how-to-manage-sessions-in-sveltekit-with-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 11: How to Implement Refresh Token Rotation in SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;Implementing refresh token rotation in SvelteKitAuth involves creating an API route to refresh tokens, configuring &lt;code&gt;jwt&lt;/code&gt; and &lt;code&gt;session&lt;/code&gt; callbacks to handle token rotation, and invoking the refresh process from the client side. This ensures secure and seamless user sessions by automatically updating &lt;code&gt;access_token&lt;/code&gt; without requiring user re-authentication. For detailed steps and code, refer to the provided GitHub repository. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/how-to-implement-refresh-token-rotation-in-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 12: How to Exchange Data Between Client and Server Using SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;This article explains how to exchange data between the client and server using SvelteKitAuth. It covers the importance of JWT and session callbacks, and how to synchronize and store sessions effectively. The process involves configuring the &lt;code&gt;jwt&lt;/code&gt; and &lt;code&gt;session&lt;/code&gt; callbacks, creating an update endpoint, and initiating update requests from the client. Additionally, it discusses how the server can send information back to the client through hydration using server load functions. The article provides a step-by-step guide to ensure seamless data synchronization in SvelteKit applications. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/how-to-exchange-data-between-client-and-server-using-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 13: Steps to Build Custom Pages and Handle Events in SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;Steps to build custom pages and handle events in SvelteKitAuth:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Pages&lt;/strong&gt;: Auth.js allows creating custom authentication pages for sign-in, sign-out, and error handling to match your app's design. Configure these by specifying the path in the &lt;code&gt;SvelteKitAuthConfig&lt;/code&gt; object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Events&lt;/strong&gt;: Auth.js provides hooks for actions like sign-in, sign-out, and session management. Configure these events to execute custom code for logging, analytics, or other side effects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Customizing pages and handling events enhances user experience and functionality. For more details, refer to the provided links and GitHub repository. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/steps-to-build-custom-pages-and-handle-events-in-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 14: Managing Shared Sessions Across Multiple Applications in SvelteKitAuth
&lt;/h4&gt;

&lt;p&gt;Managing shared sessions across multiple applications in SvelteKitAuth involves configuring session cookies for same-domain apps and using a proxy identity server for cross-domain apps. For same-domain apps, update the cookie's domain property. For different domains, set up a proxy server to handle OAuth callbacks, centralizing authentication and ensuring seamless session sharing. Detailed steps and configurations are provided for both scenarios. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/managing-shared-sessions-across-multiple-applications-in-sveltekitauth" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chapter 15: Drawbacks of SvelteKitAuth You Should Know
&lt;/h4&gt;

&lt;p&gt;SvelteKitAuth has several drawbacks, including the need for workarounds in complex scenarios, limited updates and focus on Next.js, poor documentation, minimal community support, and subpar developer experience. These issues make it less suitable for enterprise-level applications or projects with intricate authentication requirements. Get more insights by reading the &lt;a href="https://blog.aakashgoplani.in/drawbacks-of-sveltekitauth-you-should-know" rel="noopener noreferrer"&gt;full blog&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;In conclusion, SvelteKitAuth offers a comprehensive and robust solution for integrating authentication into SvelteKit applications. With support for a wide range of OAuth and OpenID Connect providers, it simplifies the authentication process while ensuring security through features like CSRF protection and server-only cookies. The guide covers everything from setting up Auth0 and integrating multiple providers to managing sessions and implementing refresh token rotation. Despite some drawbacks, such as limited updates and community support, SvelteKitAuth remains a powerful tool for developers looking to enhance their SvelteKit apps with secure and flexible authentication mechanisms. Here is the link to the &lt;a href="https://github.com/aakash14goplani/SvelteKitAuth" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; with the codebase.&lt;/p&gt;

</description>
      <category>sveltekit</category>
      <category>sveltekitauth</category>
      <category>authjs</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Internationalization in SvelteKit with svelte-i18n, sveltekit-i18n and typesafe-i18n</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Wed, 02 Aug 2023 14:55:25 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/internationalization-in-sveltekit-with-svelte-i18n-sveltekit-i18n-and-typesafe-i18n-3olj</link>
      <guid>https://dev.to/aakashgoplani/internationalization-in-sveltekit-with-svelte-i18n-sveltekit-i18n-and-typesafe-i18n-3olj</guid>
      <description>&lt;p&gt;In this series, I'll be demonstrating internationalization in SvelteKit with three different libraries: svelte-i18n, sveltekit-i18n and typesafe-i18n.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internationalization in SvelteKit with svelte-i18n
&lt;/h2&gt;

&lt;p&gt;This is the first article of three-part series to demonstrate i18n in SvelteKit. In this article, we will work on integrating &lt;em&gt;svelte-i18n&lt;/em&gt; with SvelteKit.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;svelte-i18n&lt;/em&gt; helps you localize your app using the reactive tools Svelte provides. By using stores to keep track of the current &lt;code&gt;locale&lt;/code&gt;, &lt;code&gt;dictionary&lt;/code&gt; of messages and &lt;code&gt;format&lt;/code&gt; messages, it keeps everything neat, in sync and easy to use on svelte files.&lt;/p&gt;

&lt;p&gt;Under the hood, &lt;em&gt;svelte-i18n&lt;/em&gt; uses &lt;a href="https://formatjs.io/" rel="noopener noreferrer"&gt;formatjs&lt;/a&gt; for localizing messages. It allows &lt;em&gt;svelte-i18n&lt;/em&gt; to support the ICU message syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Structure
&lt;/h3&gt;

&lt;p&gt;Before we begin, I want to give you a detailed walkthrough of the application that we will be working on. You can find the code in the &lt;a href="https://github.com/aakash14goplani/sveltekit-with-sveltei18n" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1690286047702%2F54c0dc32-f5c3-453e-85b0-7f986af6c5d7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1690286047702%2F54c0dc32-f5c3-453e-85b0-7f986af6c5d7.png" alt="svelte-i18n"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see from the image, this will be a simple single-page application demonstrating i18n features like &lt;em&gt;locale switching&lt;/em&gt;, &lt;em&gt;pluralization&lt;/em&gt; and &lt;em&gt;formatting&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the next section, we will work on integrating the &lt;em&gt;svelte-i18n&lt;/em&gt; library with SvelteKit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration with SvelteKit
&lt;/h3&gt;

&lt;p&gt;Read the complete integration flow on my &lt;a href="https://blog.aakashgoplani.in/internationalization-in-sveltekit-with-svelte-i18n" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Internationalization in SvelteKit with sveltekit-i18n
&lt;/h2&gt;

&lt;p&gt;This is the second article of three-part series to demonstrate i18n in SvelteKit. In the previous article, we worked our way with &lt;em&gt;svelte-i18n&lt;/em&gt; and in this article, we will work on integrating &lt;em&gt;sveltekit-i18n&lt;/em&gt; with SvelteKit.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;sveltekit-i18n&lt;/em&gt; is a tiny library with no external dependencies, built for Svelte and SvelteKit. Key features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SvelteKit ready.&lt;/li&gt;
&lt;li&gt;SSR support.
&lt;/li&gt;
&lt;li&gt;Custom data sources: no matter if you are using local files or remote API to get your translations.
&lt;/li&gt;
&lt;li&gt;Module-based: your translations are loaded for visited pages only (and only once!)
&lt;/li&gt;
&lt;li&gt;Component-scoped translations: you can create multiple instances with custom definitions.
&lt;/li&gt;
&lt;li&gt;Custom modifiers: you can modify the input data the way you need.
&lt;/li&gt;
&lt;li&gt;TS support.
&lt;/li&gt;
&lt;li&gt;No external dependencies.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Application Structure
&lt;/h3&gt;

&lt;p&gt;Before we begin, I want to give you a detailed walkthrough of the application that we will be working on. You can find the code in the &lt;a href="https://github.com/aakash14goplani/sveltekit-with-sveltekiti18n" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1690909653107%2F8f1d9d88-1a94-4660-a08f-f863c731a37b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1690909653107%2F8f1d9d88-1a94-4660-a08f-f863c731a37b.png" alt="sveltekit-i18n"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see from the image, this will be a simple single-page application demonstrating i18n features like &lt;em&gt;locale switching&lt;/em&gt;, &lt;em&gt;pluralization&lt;/em&gt; and &lt;em&gt;formatting&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the next section, we will work on integrating the &lt;em&gt;sveltekit-i18n&lt;/em&gt; library with SvelteKit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration with SvelteKit
&lt;/h3&gt;

&lt;p&gt;Read the complete integration flow on my &lt;a href="https://blog.aakashgoplani.in/internationalization-in-sveltekit-with-sveltekit-i18n" rel="noopener noreferrer"&gt;blog&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Internationalization in SvelteKit with typesafe-i18n
&lt;/h2&gt;

&lt;p&gt;This is the final article of three-part series to demonstrate i18n in SvelteKit. In the previous article, we worked our way with &lt;em&gt;sveltekit-i18n&lt;/em&gt; and in this article, we will work on integrating &lt;em&gt;typesafe-i18n&lt;/em&gt; with SvelteKit.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;typesafe-i18n&lt;/em&gt; is a fully type-safe and lightweight internationalization library for all your TypeScript and JavaScript projects. One thing that makes &lt;em&gt;typesafe-i18n&lt;/em&gt; stand out is that it is a generic library and not limited to Svelte, you can use it with any of your JavaScript or TypeScript projects.&lt;/p&gt;

&lt;p&gt;This library introduces a full-fledged flow for maintaining localization in your application. The moment you install this library, it generates a specific folder structure encompassing all the i18n-specific files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Structure
&lt;/h3&gt;

&lt;p&gt;Before we begin, I want to give you a detailed walkthrough of the application that we will be working on. You can find the code in the &lt;a href="https://github.com/aakash14goplani/sveltekit-with-typesafe18n" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1690910323040%2Fd14c6da9-0986-485f-b88f-7bd56b4a3c0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1690910323040%2Fd14c6da9-0986-485f-b88f-7bd56b4a3c0a.png" alt="typesafe-i18n"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see from the image, this will be a simple single-page application demonstrating i18n features like &lt;em&gt;locale switching&lt;/em&gt;, &lt;em&gt;pluralization&lt;/em&gt; and &lt;em&gt;formatting&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the next section, we will work on integrating the &lt;em&gt;typesafe-i18n&lt;/em&gt; library with SvelteKit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration with SvelteKit
&lt;/h3&gt;

&lt;p&gt;Read the complete integration flow on my &lt;a href="https://blog.aakashgoplani.in/internationalization-in-sveltekit-with-typesafe-i18n" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparing i18n libraries in SvelteKit: svelte-i18n, sveltekit-i18n and typesafe-i18n
&lt;/h2&gt;

&lt;p&gt;Based on my learnings from localizing applications in SvelteKit with &lt;em&gt;svelte-i18n&lt;/em&gt;, &lt;em&gt;sveltekit-i18n&lt;/em&gt; and &lt;em&gt;typesafe-i18n&lt;/em&gt;, I've come up with advantages and limitations of each of these libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  svelte-i18n
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It is a simple and minimalistic library that uses &lt;a href="https://formatjs.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;formatjs&lt;/strong&gt;&lt;/a&gt; for localizing messages and supports the ICU message syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It offers to load translations in a synchronous as well as asynchronous manner as per requirement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provides a decent number of options for formatting and pluralization.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ease of Use
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Since this library uses native Svelte stores for implementing localization, it feels like part of the ecosystem and hence very easy to get started with!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you have a simple requirement of changing translations based on a given locale with limited formatting, this should be your go-to library.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Size
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;As of v3.7.0, the size of the &lt;em&gt;svelte-i18n&lt;/em&gt; package is 48.3 kB in the minified form and 14.2 kB in minified + gzipped form. (&lt;a href="https://bundlephobia.com/package/svelte-i18n@3.7.0" rel="noopener noreferrer"&gt;source&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Community Support
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It has &lt;a href="https://www.npmjs.com/package/svelte-i18n" rel="noopener noreferrer"&gt;29,978 downloads/week&lt;/a&gt; as of the time of writing this article.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The only downside is, this library is not actively managed. Several issues are on the rise and resolution is almost zero.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Limitations
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;There are very less options available for formatting and pluralization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As mentioned before, the library is not actively managed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  sveltekit-i18n
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It is &lt;strong&gt;built for SvelteKit&lt;/strong&gt; and has good SSR support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can load translations from API, database and local file system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The translations are loaded for visited pages only. (and only once!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Component-scoped translations: you can create multiple instances with custom definitions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It provides good TS support and has no external dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports ICU syntax + provides a native parsing engine as well.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ease of Use
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;It is very easy to use. I found it even easier while working with the ICU parser (instead of the default parser).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Size
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;As of v2.4.2, the size of the &lt;em&gt;sveltekit-i18n&lt;/em&gt; package is 14 kB in the minified form and 4.6 kB in minified + gzipped form. (&lt;a href="https://bundlephobia.com/package/sveltekit-i18n@2.4.2" rel="noopener noreferrer"&gt;source&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Community Support
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It has &lt;a href="https://www.npmjs.com/package/sveltekit-i18n" rel="noopener noreferrer"&gt;3,052 downloads/week&lt;/a&gt; as of the time of writing this article.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even though the number of downloads is less than the &lt;em&gt;svelte-i18n&lt;/em&gt; but good news is that this library is actively maintained.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Limitations
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;While working with pluralization, understanding the syntax of the default parser could be a bit challenging at the start.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  typesafe-i18n
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Features
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It is a lightweight, easy-to-use syntax and has no external dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because of its strong typings, it prevents you from making mistakes (also in plain JavaScript projects).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unlike the other two libraries, typesafe-i18n can be used with any framework and supports both TypeScript and JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creates boilerplate code for you which ensures the well-structured flow of i18n in your codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports plural rules and allows formatting of values e.g. locale-dependent date or number formats.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It also supports switch-case statements e.g. for gender-specific output.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provides an option for asynchronous loading of locales.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It supports SSR (Server-Side Rendering) and can be used for frontend, backend and API projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import and Export translations from/to files or services.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Ease of Use
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It has some initial learning curve but as soon as we become familiar with the &lt;em&gt;typesafe-i18n&lt;/em&gt; ecosystem, this library is not only easy to use but super convenient as well!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Personally, this is my go-to library for i18n&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Size
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;As of v5.26.0, the size of the &lt;em&gt;typesafe-i18n&lt;/em&gt; package is 2.8 kB in the minified form and 1.3 kB in minified + gzipped form. (&lt;a href="https://bundlephobia.com/package/typesafe-i18n@5.26.0" rel="noopener noreferrer"&gt;source&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Community Support
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It has &lt;a href="https://www.npmjs.com/package/typesafe-i18n" rel="noopener noreferrer"&gt;13,588 downloads/week&lt;/a&gt; as of the time of writing this article.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This library is actively maintained.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Limitations
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;It has a huge eco-system (generators, detectors, importers, exporters etc.) and hence learning curve is a bit steep.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sveltekit</category>
      <category>sveltei18n</category>
      <category>sveltekiti18n</category>
      <category>typesafei18n</category>
    </item>
    <item>
      <title>Avoid shared state on the server in SvelteKit - Be extra cautious when using stores in SSR mode</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sun, 09 Jul 2023 17:39:58 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/avoid-shared-state-on-the-server-in-sveltekit-be-extra-cautious-when-using-stores-in-ssr-mode-2b99</link>
      <guid>https://dev.to/aakashgoplani/avoid-shared-state-on-the-server-in-sveltekit-be-extra-cautious-when-using-stores-in-ssr-mode-2b99</guid>
      <description>&lt;p&gt;State management is a crucial part when working with complex web applications. Svelte does provide us with elegant native stores that can be used in such scenarios. However, we must be cautious while using them otherwise our application may result in unwanted behavior and could produce bugs that are difficult to trace and fix!&lt;/p&gt;

&lt;p&gt;One such example is using stores in the backend i.e. in the SSR flow. This article will focus on a few edge cases where we must be extremely cautious in the way we use stores or rather state management in general.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the problem?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Using stores in the backend (SSR mode) causes data leaks between clients.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But Why?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Servers are stateless i.e. one common space on the server is shared by multiple clients (users). In other words, the state on Server is global by default that will be shared by all of its clients. The servers are often long-lived and shared by multiple users. For that reason, it's important not to store data in shared variables. For example, consider the following scenario:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HAQ28B2L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688891933795/8861edca-c071-469d-9e2e-df40f070168e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HAQ28B2L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1688891933795/8861edca-c071-469d-9e2e-df40f070168e.png" alt="Arch" width="668" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Multiple users have been logged into the system and they are interacting with a common application server. Now each user interacts with the server, independently, via the browser. &lt;strong&gt;A store is contextual to each instance of your app&lt;/strong&gt;. This essentially means that the state on the client side is always stateful. If we save any store value on the client side for a particular user, it will remain local to that user and will not be shared with other users.&lt;/p&gt;

&lt;p&gt;On the other hand, the state of the server is shared with all the users simultaneously and hence if user "A" updates the store value, that will be reflected on user "B" as well, thus leaking data! In addition, when user "A" returns to the site later in the day, the server may have restarted, losing their data. &lt;strong&gt;The main thing to understand is that as soon as you create a store, it becomes global server-side in an SSR context (= your store is a singleton in memory server-side, so it is shared by all HTTP requests hitting your server).&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to fix this problem?
&lt;/h3&gt;

&lt;p&gt;Read rest of the article on my &lt;a href="https://blog.aakashgoplani.in/avoid-shared-state-on-the-server-in-sveltekit"&gt;blogging site&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sveltekit</category>
      <category>state</category>
      <category>ssr</category>
      <category>stores</category>
    </item>
    <item>
      <title>Migration Guide from Routify to SvelteKit Router</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sat, 10 Jun 2023 20:13:39 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/migration-guide-from-routify-to-sveltekit-router-2cge</link>
      <guid>https://dev.to/aakashgoplani/migration-guide-from-routify-to-sveltekit-router-2cge</guid>
      <description>&lt;h3&gt;
  
  
  What is the need for migration?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I had a few personal projects created using Svelte which I am now migrating to SvelteKit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Svelte did not provide any out-of-box navigation mechanism and hence I was forced to look out for third-party libraries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SvelteKit, on the other hand, has a built-in mechanism for routing and is constantly evolving for good. Since we have a built-in solution available now, it makes sense to adhere to it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Before we proceed ahead, I want to stress on this point that Routify is an excellent library. I have used that across many personal and professional projects and the experience has been awesome. The only reason I am migrating from Routify to SvelteKit's built-in router is just my personal opinion which is - I installed Routify only because Svelte didn't have any routing mechanism but SvelteKit does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Does Routify support SvelteKit?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The current version of Routify i.e. v2.18 DOES NOT support SvelteKit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will need to upgrade that to &lt;a href="https://v3.routify.dev/"&gt;v3-next&lt;/a&gt; and as the name suggests, that is still in beta state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Just upgrading the package will not be sufficient, we will need to do a couple of more configurations that are specified in their &lt;a href="https://v3.ci.routify.dev/docs/guide/introduction"&gt;documentation&lt;/a&gt;. I am sure when they release a stable v3 version, they will have a migration guide (from v2 to v3) ready by then.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Process of Migration
&lt;/h3&gt;

&lt;p&gt;Now that we are done with the introduction, let's go through the migration process.&lt;/p&gt;

&lt;p&gt;Read rest of the article on my &lt;a href="https://blog.aakashgoplani.in/migration-guide-from-routify-to-sveltekit-router"&gt;blogging site&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sveltekit</category>
      <category>routify</category>
      <category>migration</category>
    </item>
    <item>
      <title>Generate Breadcrumb and Navigation in SvelteKit</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sat, 10 Jun 2023 19:43:19 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/generate-breadcrumb-and-navigation-in-sveltekit-1mk8</link>
      <guid>https://dev.to/aakashgoplani/generate-breadcrumb-and-navigation-in-sveltekit-1mk8</guid>
      <description>&lt;p&gt;Liquid syntax error: Unknown tag 'endraw'&lt;/p&gt;
</description>
      <category>sveltekit</category>
      <category>breadcrumb</category>
      <category>navigationbar</category>
    </item>
    <item>
      <title>SvelteKitAuth with Salesforce OAuth provider</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sun, 04 Jun 2023 11:40:28 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/sveltekitauth-with-salesforce-oauth-provider-321l</link>
      <guid>https://dev.to/aakashgoplani/sveltekitauth-with-salesforce-oauth-provider-321l</guid>
      <description>&lt;p&gt;Before we proceed ahead with this article, I would recommend reading my &lt;a href="https://dev.to/aakashgoplani/sveltekit-authentication-using-sveltekitauth-and-oauth-providers-a-comprehensive-guide-270e"&gt;previous blog post&lt;/a&gt; which gives a detailed idea of what SvelteKitAuth is, how it works and basic configuration details. In this blog post, we will go through the configuration for the Salesforce OAuth provider.&lt;/p&gt;

&lt;p&gt;We will begin this post by installing the required dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@auth/core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@auth/sveltekit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"latest"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have the required dependencies installed, we will go through two configurations i.e.,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuring using a built-in provider:&lt;/strong&gt; SvelteKitAuth provides &lt;a href="https://github.com/nextauthjs/next-auth/tree/main/packages/next-auth/src/providers"&gt;60+ built-in&lt;/a&gt; providers. If our requirement regarding the configuration is straightforward or in other words does not require any customization, we can select this approach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration using the custom provider&lt;/strong&gt;: If our requirement needs some tweaks i.e., we have a custom URL setup for fetching tokens or user details, we will select custom providers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Working with a built-in provider
&lt;/h3&gt;

&lt;p&gt;SvelteKitAuth provides a built-in &lt;a href="https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/salesforce.ts"&gt;&lt;em&gt;SalesforceProvider&lt;/em&gt;&lt;/a&gt;. Let's walk through the required configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SalesforceProvider&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@auth/core/providers/salesforce&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;SalesforceProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;wellKnown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://my.salesforce.com/.well-known/openid-configuration&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the built-in provider, we need minimal configuration details like &lt;strong&gt;clientId&lt;/strong&gt;, &lt;strong&gt;clientSecret&lt;/strong&gt; and &lt;strong&gt;wellKnown&lt;/strong&gt;. With this minimal configuration, SvelteKitAuth will complete the authentication process and fetch the required tokens and user details as mentioned in &lt;code&gt;wellKnown&lt;/code&gt; config file. I have already covered a detailed explanation of these properties in my &lt;a href="https://dev.to/aakashgoplani/sveltekit-authentication-using-sveltekitauth-and-oauth-providers-a-comprehensive-guide-270e#heading-configuring-sveltekitauth-built-in-auht0-provider"&gt;previous article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next section, we will go through the configuration required to set up a custom provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Working with a custom provider
&lt;/h3&gt;

&lt;p&gt;In many scenarios, our organization would have configured dedicated URLs for authorization, token and user information which will not be available in standard &lt;code&gt;wllKnown&lt;/code&gt; configuration file, in such scenarios we must use custom providers.&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="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salesforce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Salesforce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;oidc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;token_endpoint_auth_method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;client_secret_post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://my-custom-issuer-url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://my-custom-authorization-url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refresh_token web openid id api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;response_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;code&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;response_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;redirect_uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://my-custom-redirect-url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://my-custom-token-url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userinfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://my-custom-user-information-url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;checks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pkce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have already covered a detailed explanation of every property that is used within the custom provider configuration in my &lt;a href="https://dev.to/aakashgoplani/sveltekit-authentication-using-sveltekitauth-and-oauth-providers-a-comprehensive-guide-270e#heading-configuring-sveltekitauth-custom-provider"&gt;previous article&lt;/a&gt;, in this blog post, I'll cover a few important configurations that are required specifically for the Salesforce custom provider.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;For the Salesforce custom provider, we have to set the &lt;code&gt;type&lt;/code&gt; property to &lt;strong&gt;oidc.&lt;/strong&gt; For the built-in provider, it is set to &lt;strong&gt;oauth.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we have to specify the &lt;em&gt;client token endpoint authentication method&lt;/em&gt; which is generally "&lt;em&gt;client_secret_post&lt;/em&gt;". This particular configuration is subjective and may or may-not-be required in your use case.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, the last required property here is &lt;code&gt;checks&lt;/code&gt; which are set to &lt;strong&gt;pkce&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;Now that we have our &lt;code&gt;providers&lt;/code&gt; configuration ready, we can put all the required configurations together in &lt;strong&gt;&lt;em&gt;src/hooks.server.ts&lt;/em&gt;&lt;/strong&gt; file.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SvelteKitAuth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@auth/sveltekit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Handle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sveltejs/kit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SvelteKitAuthConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
  &lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_VERCEL_ENV&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_VERCEL_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...},&lt;/span&gt;
  &lt;span class="na"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...},&lt;/span&gt;
  &lt;span class="na"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...},&lt;/span&gt;
  &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// revoke token&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://revoke-token-url?token=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SvelteKitAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important point to highlight is revoking the access token as soon as the user logs out. Salesforce by default does not revoke the token, it is our responsibility as a developer to trigger the event (via POST request) and let Salesforce know that the user has logged out and we should revoke the access token.&lt;/p&gt;

&lt;p&gt;For the explanation on the rest of the above-mentioned properties and a few of the other important details like callback URL, redirect URL, sign-in, sign-out and managing session all of which I have covered in detail in my &lt;a href="https://dev.to/aakashgoplani/sveltekit-authentication-using-sveltekitauth-and-oauth-providers-a-comprehensive-guide-270e"&gt;previous article&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>sveltekit</category>
      <category>sveltekitauth</category>
      <category>salesforce</category>
      <category>authentication</category>
    </item>
    <item>
      <title>SvelteKit Authentication using SvelteKitAuth and OAuth providers: A Comprehensive Guide</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sun, 04 Jun 2023 11:35:52 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/sveltekit-authentication-using-sveltekitauth-and-oauth-providers-a-comprehensive-guide-270e</link>
      <guid>https://dev.to/aakashgoplani/sveltekit-authentication-using-sveltekitauth-and-oauth-providers-a-comprehensive-guide-270e</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: The contents of this article are now outdated. Please refer the updated content here: &lt;a href="https://blog.aakashgoplani.in/series/sveltekitauth-sveltekit" rel="noopener noreferrer"&gt;Authentication in SvelteKit using SvelteKitAuth&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are multiple ways in which we can authenticate a user over the web, few of them are: matching user credentials in the database, delegating responsibility to an external OAuth provider etc. We can extend those similar concepts in SvelteKit too and implement authentication.&lt;/p&gt;

&lt;p&gt;SvelteKit does not provide out-of-box authentication. We can extend the means that we discussed above and implement authentication in SvelteKit. This guide will focus on implementing authentication in SvelteKit using SvelteKitAuth and OAuth providers. After reading this guide, you'll have a decent understanding of implementing authentication mechanisms in SvelteKit.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SvelteKitAuth is part of the &lt;a href="https://authjs.dev/" rel="noopener noreferrer"&gt;Auth.js&lt;/a&gt; project - Authentication for Web which is an open-source library that is easy to use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SvelteKitAuth is an extension of &lt;em&gt;NextAuth&lt;/em&gt; - a popular authentication framework from the &lt;em&gt;Next&lt;/em&gt; / &lt;em&gt;React&lt;/em&gt; world. NextAuth is now getting a major overhaul and is now becoming &lt;em&gt;Auth.js&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It can be used with any OAuth2 or OpenID Connect provider and has built-in support for 68+ popular services like Google, Facebook, Auth0, Apple etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apart from OAuth authentication, it has built-in support for authentication using email/passwordless/magic link/username/password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can configure SvelteKitAuth to use database sessions (MySQL, Postgres, MSSQL, MongoDB etc.) or JWT.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It comes with a built-in security mechanism having features like Signed, prefixed, server-only cookies, has built-in CSRF protection &amp;amp; doesn't rely on client-side JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Why choose SvelteKitAuth?
&lt;/h4&gt;

&lt;p&gt;Although there are other options available as well, the reason I choose SvelteKitAuth is that it supports &lt;strong&gt;OAuth 1.0&lt;/strong&gt;, &lt;strong&gt;1.0A&lt;/strong&gt;, &lt;strong&gt;2.0&lt;/strong&gt; and &lt;strong&gt;OpenID Connect&lt;/strong&gt; and has built-in support for the most popular sign-in services like Google, GitHub, Auth0, Salesforce etc. It also supports multiple popular database adapters like MySQL, Postgres, MSSQL, MongoDB etc. Apart from that it provides a mechanism to create a custom OAuth provider and custom database adapter as well.&lt;/p&gt;

&lt;p&gt;Another reason for going ahead with SvelteKitAuth is it has bigger community support and is backed by Vercel which makes it runtime agnostic, runs anywhere &amp;amp; supports Vercel Edge Functions, Node.js, and Serverless.&lt;/p&gt;

&lt;h4&gt;
  
  
  How does SvelteKitAuth work under the hood?
&lt;/h4&gt;

&lt;p&gt;To understand how SvelteKitAuth works under the hood, let's explore its internal architecture and the steps involved in the authentication flow.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;: When setting up SvelteKitAuth, you define a configuration file that specifies authentication providers, such as Google, GitHub, or a custom provider. The configuration also includes settings like secret keys, session storage options, and callback URLs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication Providers&lt;/strong&gt;: SvelteKitAuth supports multiple authentication providers, and you can choose the ones you want to enable. Each provider has its configuration options, such as client ID, client secret, scopes, and authorization URLs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Flow&lt;/strong&gt;: When a user initiates the authentication process, SvelteKitAuth handles the flow by redirecting them to the respective authentication provider's login page. This typically involves generating a state and storing it in a server-side session to prevent CSRF attacks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Callback URL&lt;/strong&gt;: After successful authentication with the provider, the user is redirected back to a callback URL specified in the SvelteKitAuth configuration. This URL is typically an API route that SvelteKitAuth exposes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-Side Flow&lt;/strong&gt;: SvelteKitAuth receives the callback request on the specified API route. It validates the received data, including the state parameter, to ensure it matches the stored session state. This step prevents CSRF attacks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token Exchange&lt;/strong&gt;: SvelteKitAuth then exchanges the authorization code received from the authentication provider with an access token. This token allows SvelteKitAuth to make authenticated API requests on behalf of the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Information&lt;/strong&gt;: With the access token, SvelteKitAuth retrieves the user's profile information from the authentication provider's API. It can fetch details like name, email, profile picture, or any other data that the provider makes available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Session Management&lt;/strong&gt;: SvelteKitAuth creates a session for the authenticated user, typically using a secure HTTP-only cookie or a JWT (JSON Web Token). This session contains the user's data and is used for subsequent authenticated requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Persistent Sessions&lt;/strong&gt;: SvelteKitAuth can optionally store session information in a database or other storage mechanisms. This allows users to remain logged in even if the server restarts or the user refreshes the page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hooks and Events&lt;/strong&gt;: SvelteKitAuth provides various hooks and events that you can use to customize the authentication flow, add additional functionality, or integrate with external systems. Examples include the &lt;code&gt;$page.data.session&lt;/code&gt; for accessing the session data in components and event hooks like &lt;code&gt;signIn&lt;/code&gt; or &lt;code&gt;signOut&lt;/code&gt; for performing actions on authentication events.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Overall, SvelteKitAuth abstracts away the complexities of authentication and provides a unified API for integrating with multiple authentication providers. It handles the authentication flow, token exchange, and session management, allowing developers to focus on building their applications without getting caught up in the intricacies of authentication protocols.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does OAuth work?
&lt;/h3&gt;

&lt;p&gt;As I mentioned earlier that this guide will focus on implementing authentication in SvelteKit using SvelteKitAuth and OAuth providers, we must know how OAuth works.&lt;/p&gt;

&lt;p&gt;Auth.js has given a detailed explanation on this topic and I will be quoting that from their &lt;a href="https://authjs.dev/concepts/oauth" rel="noopener noreferrer"&gt;site&lt;/a&gt; as is. Without going into too much detail, the OAuth flow generally has 6 parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The application requests authorization to access service resources from the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the user authorized the request, the application receives an authorization grant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The application requests an access token from the authorization server (API) by presenting authentication of its own identity, and the authorization grant.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the application identity is authenticated and the authorization grant is valid, the authorization server (API) issues an access token to the application. Authorization is complete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The application requests the resource from the resource server (API) and presents the access token for authentication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the access token is valid, the resource server (API) serves the resource to the application.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more details, check out Aaron Parecki's blog post - &lt;a href="https://aaronparecki.com/oauth-2-simplified/" rel="noopener noreferrer"&gt;OAuth2 Simplified&lt;/a&gt; or Postman's blog post - &lt;a href="https://blog.postman.com/pkce-oauth-how-to/" rel="noopener noreferrer"&gt;OAuth 2.0: Implicit Flow is Dead, Try PKCE Instead&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring SvelteKitAuth with Auth0
&lt;/h3&gt;

&lt;p&gt;For more details, please read rest of article on my &lt;a href="https://blog.aakashgoplani.in/series/sveltekit-authentication" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sveltekit</category>
      <category>sveltekitauth</category>
      <category>authentication</category>
      <category>auth0</category>
    </item>
    <item>
      <title>State Management with Custom Svelte Store Wrapper</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sun, 05 Feb 2023 03:41:46 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/state-management-with-custom-svelte-store-wrapper-14jb</link>
      <guid>https://dev.to/aakashgoplani/state-management-with-custom-svelte-store-wrapper-14jb</guid>
      <description>&lt;p&gt;A custom store is an object that provides, at the minimum, the same functionality as any one of the native stores (readable or writable), and that can also provide additional functionality geared more toward domain-specific logic. When this object contains a “properly implemented” subscribe method, the object fulfills the &lt;a href="https://www.youtube.com/watch?v=T3XBiCbm97M" rel="noopener noreferrer"&gt;store contract&lt;/a&gt;. This allows the object to be treated as a store. Its value becomes reactive, and the store can be referenced with the &lt;code&gt;$&lt;/code&gt; auto-subscription prefix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do we need Custom Store?
&lt;/h3&gt;

&lt;p&gt;It is considered a good pattern (though quite opinionated) that a Component should NOT mutate the state of data. Instead, it should dispatch the action to some middleware (like redux) and that in turn should update the state of data. It encourages state management in one place with components sending messages (actions) about what the user did instead of how the state should update.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Store in Action
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;reduxify&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./reduxify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;debugKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_update&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;param&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;returnValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;debugKey&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;reduxify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;returnValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;As the wrapper exposes &lt;em&gt;set&lt;/em&gt; and &lt;em&gt;update&lt;/em&gt; actions that have the same name as the methods exposed by the writable store, it becomes easy for a developer to use it without having to learn any new thing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This wrapper follows the pattern that we have been discussing throughout – components will not directly mutate the state of data, they will only trigger actions (&lt;em&gt;set&lt;/em&gt; and &lt;em&gt;update&lt;/em&gt; as exposed by wrapper) which in turn will mutate the state of data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to use this wrapper
&lt;/h3&gt;

&lt;p&gt;Changes involved will be minimal as components will use the same syntax as before, only utilities defining stores must be updated.&lt;/p&gt;

&lt;p&gt;This is how we have been using stores traditionally for managing states:&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="c1"&gt;// 1. Define store in (say) store.ts file&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;writable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;someStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Use them in components&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;someStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;someStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;someStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="nx"&gt;currentState&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how we will be using stores with wrapper:&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="c1"&gt;// 1. Define store in (say) store.ts file but this time,&lt;/span&gt;
&lt;span class="c1"&gt;// configure using wrapper instead of 'svelte/store'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;someStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configureStore&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Use them in components&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;someStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;someStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;someStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="nx"&gt;currentState&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Including custom actions
&lt;/h3&gt;

&lt;p&gt;We can extend this wrapper and append custom actions as well, for example:&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="c1"&gt;// Definition&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counterStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createWritableStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;counterStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decrement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;counterStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decrement&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;counterStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;

&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="nx"&gt;$counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="nx"&gt;$counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$counter&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Easy Debugging
&lt;/h3&gt;

&lt;p&gt;Debugging becomes super simple with this wrapper. Examples discussed below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We now have a single point of the location where we can apply a debugger point and trace which component has triggered action to update the state.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// apply debugger here&lt;/span&gt;
    &lt;span class="nf"&gt;_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;param&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// apply debugger here&lt;/span&gt;
    &lt;span class="nf"&gt;_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Another debugging advantage is that this wrapper provides the option &lt;em&gt;debugKey&lt;/em&gt; which if provided can print the trace in Redux browser-dev-tool using &lt;em&gt;reduxify&lt;/em&gt; utility.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some Context on &lt;em&gt;reduxify&lt;/em&gt; utility: We can connect our custom stores with Redux dev tools. There is an awesome open-source utility available (&lt;a href="https://github.com/unlocomqx/svelte-reduxify" rel="noopener noreferrer"&gt;https://github.com/unlocomqx/svelte-reduxify&lt;/a&gt;) that enables us to connect the svelte store to redux dev tools with the minimal code change. All we need is to pass our return values within reduxify callback.&lt;/p&gt;

</description>
      <category>moderation</category>
      <category>devrel</category>
      <category>softwaredevelopment</category>
      <category>productivity</category>
    </item>
    <item>
      <title>CSS rules implied when working with percentage (%) unit</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Wed, 16 Feb 2022 21:42:17 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/css-rules-implied-when-working-with-percentage-unit-2b3e</link>
      <guid>https://dev.to/aakashgoplani/css-rules-implied-when-working-with-percentage-unit-2b3e</guid>
      <description>&lt;p&gt;Recently I was working on an assignment where-in I was positioning element w.r.t. parent element and setting height of 100%. I expected that, the child container will take up all the available parent height but that was not the case. On digging-down further, I understood few of basic CSS principles which I can summarize in two sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using percentage unit on an element with &lt;code&gt;position&lt;/code&gt; property set.&lt;/li&gt;
&lt;li&gt;Fixing height set to 100% on an element with &lt;code&gt;position&lt;/code&gt; property set.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using percentage unit on an element with &lt;code&gt;position&lt;/code&gt; property set
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Using percentage unit on an element with position set to &lt;code&gt;fixed&lt;/code&gt;&lt;/strong&gt;   &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When we set position &lt;code&gt;fixed&lt;/code&gt; on an element, it gets detached from the regular document flow. So the parent of such element is not the nearest div but the viewport!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U4op6D6f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635003977983/DjGGinV-R.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U4op6D6f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635003977983/DjGGinV-R.png" alt="image.png" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;here child element (with red border) has position set to &lt;code&gt;fixed&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;if we use percentage here, e.g. &lt;code&gt;width: 60%&lt;/code&gt; then it will be 60% of the viewport's width and NOT that of parent (with blue border) width&lt;/li&gt;
&lt;li&gt;reason is, when we used &lt;code&gt;fixed&lt;/code&gt; property, the element gets detached from regular DOM flow &amp;amp; now the reference parent element will be viewport&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Using percentage unit on an element with position set to &lt;code&gt;absolute&lt;/code&gt;&lt;/strong&gt;   &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When we set position &lt;code&gt;absolute&lt;/code&gt; on an element, the parent of such element is the nearest element with position set to either of &lt;code&gt;relative&lt;/code&gt;, &lt;code&gt;absolute&lt;/code&gt;, &lt;code&gt;fixed&lt;/code&gt; or &lt;code&gt;sticky&lt;/code&gt;. In other words parent element will be the element with position property other than &lt;code&gt;static&lt;/code&gt; (browser default). The dimension includes length of content + padding.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XYq9Swco--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635004484729/NXq_QcGIu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XYq9Swco--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635004484729/NXq_QcGIu.png" alt="image.png" width="800" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;here child element (with red border) has position set to &lt;code&gt;absolute&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;if we use percentage here, e.g. &lt;code&gt;width: 60%&lt;/code&gt; then it will be 60% of the parent element's width.&lt;/li&gt;
&lt;li&gt;here &lt;code&gt;width = content width of parent + padding&lt;/code&gt;. Example, If parent element has 16px of padding set, 1px of border and 16px of margin and the content takes dimension of (900 x 400). With these figures, the parent element's will be calculated as 900 + 16 + 16 = 932px i.e. width of content plus padding. So the child's width will be 60% of 932px.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Using percentage unit on an element with position set to &lt;code&gt;relative&lt;/code&gt; or &lt;code&gt;static&lt;/code&gt;&lt;/strong&gt;   &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When we set position &lt;code&gt;relative&lt;/code&gt; or &lt;code&gt;static&lt;/code&gt; on an element, the parent of such element is the nearest block level element. The dimension includes length of content only.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wCpVKvUm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635005227026/eLOaBL5P-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wCpVKvUm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635005227026/eLOaBL5P-.png" alt="image.png" width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;here child element (with red border) has position set to &lt;code&gt;relative&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;if we use percentage here, e.g. &lt;code&gt;width: 60%&lt;/code&gt; then it will be 60% of the parent element's width.&lt;/li&gt;
&lt;li&gt;here &lt;code&gt;width = content width of parent&lt;/code&gt;. Example, If parent element has 16px of padding set, 1px of border and 16px of margin and the content takes dimension of (900 x 400). With these figures, the parent element's will be calculated as 900px i.e. width of content. So the child's width will be 60% of 900px&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fixing height set to 100% on an element with &lt;code&gt;position&lt;/code&gt; property set
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Using percentage unit on an element with position set to &lt;code&gt;relative&lt;/code&gt; or &lt;code&gt;static&lt;/code&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;As discussed above, setting position to &lt;code&gt;relative&lt;/code&gt; makes the parent reference element to the nearest block level element. So the height will be inherited from the nearest parent (body, in this case). It will push the entire content after the backdrop, refer the screenshot below:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2-p6jQHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635006066323/CCRVwmOlsf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2-p6jQHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635006066323/CCRVwmOlsf.png" alt="image.png" width="800" height="1299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using percentage unit on an element with position set to &lt;code&gt;absolute&lt;/code&gt; &amp;amp; &lt;code&gt;fixed&lt;/code&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;When using &lt;code&gt;absolute&lt;/code&gt; position, the parent reference element to the nearest element with position property other than &lt;code&gt;static&lt;/code&gt;. In our example (refer stackbliz) it will be viewport, which will be the same for &lt;code&gt;fixed&lt;/code&gt; as well. So the height will be inherited from the viewport and it will overlap all the body elements, refer the screenshot below:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s0bqOMeQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635006543530/3QgEKoHtH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s0bqOMeQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1635006543530/3QgEKoHtH.png" alt="image.png" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackblitz.com/edit/web-platform-rarcd1?file=index.html"&gt;stackblitz example&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>A simple approach towards handling errors in Angular</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sun, 06 Feb 2022 09:51:39 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/a-simple-approach-towards-handling-errors-in-angular-2pd7</link>
      <guid>https://dev.to/aakashgoplani/a-simple-approach-towards-handling-errors-in-angular-2pd7</guid>
      <description>&lt;p&gt;Angular errors can be broadly classified into two types:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;HTTP Errors&lt;/li&gt;
&lt;li&gt;Client Errors&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;HTTP errors occurs whenever we deal with external APIs example, we made call to an endpoint and the network went down or while making the call server was not able to process the request properly and in return sends back error etc. All such scenarios which involve server's response status of 5xx and 4xx  role comes under this category. In Angular, they are identified by &lt;code&gt;HttpErrorResponse&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RK6m7Pel--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/13452115/133273630-c3c291bc-fede-4fa0-9245-2b88852003c7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RK6m7Pel--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/13452115/133273630-c3c291bc-fede-4fa0-9245-2b88852003c7.png" alt="image" width="698" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Client (Browser) Error is the error that mostly occurs at runtime because of developers mistake while writing the code. Types of these errors are: &lt;code&gt;EvalError&lt;/code&gt;, &lt;code&gt;InternalError&lt;/code&gt;, &lt;code&gt;RangeError&lt;/code&gt;, &lt;code&gt;ReferenceError&lt;/code&gt;, &lt;code&gt;SyntaxError&lt;/code&gt;, &lt;code&gt;URIError&lt;/code&gt;, &lt;code&gt;TypeError&lt;/code&gt;. One such example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;windows&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;abc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pqr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// here property `abc` is not defined on global window object so&lt;/span&gt;
&lt;span class="c1"&gt;// `(windows as any).abc` will result into undefined and&lt;/span&gt;
&lt;span class="c1"&gt;// undefined.pqr will throw TypeError: stating that we are&lt;/span&gt;
&lt;span class="c1"&gt;// trying to set something on a property that does not exists&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So any such errors that are induced by developers comes under Client (Browser) Error category.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g7T4bjaY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/13452115/133273671-1d3f0f89-8a19-4640-9525-315f0ede9553.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g7T4bjaY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/13452115/133273671-1d3f0f89-8a19-4640-9525-315f0ede9553.png" alt="image" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under both the circumstances its the end user that suffer the most. Whenever any such error occurs, execution of JavaScript stops and the screen freezes giving end user a bad experience. So, the good practice is to handle such errors and perform a relevant action like routing users to error page and displaying some custom message like &lt;code&gt;Something Went Wrong! Please try again later!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Angular comes up with class &lt;code&gt;ErrorHandler&lt;/code&gt; that provides default method &lt;code&gt;handleError(error: Error)&lt;/code&gt; which we can utilize to catch those errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyErrorHandler&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ErrorHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do something with the exception like router.navigate(['/error-page']);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use &lt;code&gt;handleError(error: Error)&lt;/code&gt; to catch the error and redirect user to a generic &lt;code&gt;error-page&lt;/code&gt;. One problem here is how do we inject the helper service in our custom &lt;code&gt;ErrorHandler&lt;/code&gt; implementation?&lt;/p&gt;

&lt;p&gt;If we inject the service as we generally do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;){}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will throw error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Error: NG0200: Circular Dependency in DI detected for ErrorHandler&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gfaiWKES--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/13452115/133276587-a1a039d8-47b8-4394-a26e-d0662cd73bd0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gfaiWKES--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/13452115/133276587-a1a039d8-47b8-4394-a26e-d0662cd73bd0.png" alt="image" width="689" height="348"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Angular creates &lt;code&gt;ErrorHandler&lt;/code&gt; before providers otherwise it won't be able to catch errors that occurs in early phase of application. Hence the providers will not be available to &lt;code&gt;ErrorHandler&lt;/code&gt;. So, we need to inject dependent services using injectors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyErrorHandler&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ErrorHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Injector&lt;/span&gt;&lt;span class="p"&gt;){}&lt;/span&gt;

  &lt;span class="nx"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/error-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solves one problem but leads to another.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Navigation triggered outside Angular zone, did you forget to call &lt;code&gt;ngZone.run()&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OuA4xm22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/13452115/133276468-7d04b25d-c24d-4c9e-a34c-f64532efc152.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OuA4xm22--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/13452115/133276468-7d04b25d-c24d-4c9e-a34c-f64532efc152.png" alt="image" width="800" height="16"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem here is exactly same as before while injecting our helper services. ErrorHandle runs outside of regular ngZone. So, the navigation should take place outside of the zone so that regular flow of Change Detection is not hampered&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyErrorHandler&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ErrorHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Injector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NgZone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;){}&lt;/span&gt;

  &lt;span class="nx"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/error-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error Caught: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we had achieved this, we need to provide this service to root module, example AppModule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="na"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ErrorHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;useClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyErrorHandler&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can add more customization to above &lt;code&gt;handleError&lt;/code&gt; method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;HttpErrorResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// HTTP related error&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;TypeError&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;ReferenceError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Runtime exceptions mostly induced by Developer's code&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// catch-all: catch rest of errors&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>angular</category>
      <category>errors</category>
    </item>
    <item>
      <title>Create a pull request from a reverted remote branch</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sun, 23 Jan 2022 19:30:09 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/create-a-pull-request-from-a-reverted-remote-branch-38mh</link>
      <guid>https://dev.to/aakashgoplani/create-a-pull-request-from-a-reverted-remote-branch-38mh</guid>
      <description>&lt;p&gt;Recently I landed across the situation where I had made commits directly to &lt;code&gt;dev&lt;/code&gt; branch (which happens to be our &lt;code&gt;release&lt;/code&gt; branch) instead of &lt;code&gt;feature&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;The general process that is followed in my company (and perhaps many others) is that we make changes to our &lt;code&gt;feature&lt;/code&gt; branch and raise a pull request against &lt;code&gt;dev&lt;/code&gt; (release) branch which is then reviewed and finally merged.&lt;/p&gt;

&lt;p&gt;Accidently I pushed commits directly to &lt;code&gt;dev&lt;/code&gt; branch instead of &lt;code&gt;feature&lt;/code&gt; branch &amp;amp; I quickly reverted those commits back by simple git command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git revert &amp;lt;revert-commit-hash&amp;gt;
git commit -m "reverting accidental commits"
git push 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that I quickly checked out to my &lt;code&gt;feature&lt;/code&gt; branch, made those changes again, pushed all changes to &lt;code&gt;feature&lt;/code&gt; branch. As per next step, I had to raise PR of my latest changes against &lt;code&gt;dev&lt;/code&gt; branch, and when I did that, I got message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There isn’t anything to compare.&lt;br&gt;&lt;br&gt;
dev is up to date with all commits from feature branch. Try switching the base for your comparison.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem here is &lt;code&gt;dev&lt;/code&gt; branch is ahead of the &lt;code&gt;feature&lt;/code&gt; branch (because of revert commit). You will notice that your previous work which was reverted will be gone! The solution to this is reverting the reverted commit!&lt;/p&gt;

&lt;p&gt;I had to follow 4 steps to fix this problem which I read from this &lt;a href="https://medium.com/@shanikae/create-pull-request-from-a-reverted-git-branch-27219cadf9b5"&gt;awesome article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Create and checkout to a new branch tracking &lt;code&gt;dev&lt;/code&gt; branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b temp-branch -t dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Revert the commit that was made by mistake (here commit will be reverted back from dev branch since our temp branch is tracking dev)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git revert &amp;lt;revert-commit-hash&amp;gt;
git commit -m "reverting the reverted commits"
git push -u origin temp-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Checkout the original &lt;code&gt;feature&lt;/code&gt; branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout feature-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Raise PR against dev branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push -u origin feature-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pictorial representation of scenarios discussed above:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4ooBwjjg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1634319597245/4p44KUwbW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4ooBwjjg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1634319597245/4p44KUwbW.png" alt="image.png" width="800" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
    </item>
    <item>
      <title>Angular Dynamic Form Validation - Template and Reactive Forms</title>
      <dc:creator>Aakash Goplani</dc:creator>
      <pubDate>Sun, 23 Jan 2022 19:25:12 +0000</pubDate>
      <link>https://dev.to/aakashgoplani/angular-dynamic-form-validation-template-and-reactive-forms-5c7k</link>
      <guid>https://dev.to/aakashgoplani/angular-dynamic-form-validation-template-and-reactive-forms-5c7k</guid>
      <description>&lt;p&gt;In this article I will present a way to validate Angular forms, both - model driven and template driven.&lt;/p&gt;

&lt;p&gt;For this we will need two directives:&lt;br&gt;&lt;br&gt;
(1) &lt;em&gt;form-control-validation:&lt;/em&gt; validates single input (form) control&lt;br&gt;&lt;br&gt;
(2) &lt;em&gt;form-group-directive:&lt;/em&gt; validates group of form controls.&lt;br&gt;&lt;br&gt;
These directives will be attached to input elements &amp;amp; hence we can easily access core &lt;code&gt;ngModel&lt;/code&gt; / &lt;code&gt;FormControl&lt;/code&gt; instances and validate them.&lt;/p&gt;

&lt;p&gt;We will use concept of dynamic components to create Error Component that has custom error validation message &amp;amp; inject it in DOM.&lt;/p&gt;

&lt;p&gt;This is general overview of what we are trying to implement:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1637004182096%2F7PwzcyVqA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1637004182096%2F7PwzcyVqA.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DOM Structure:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As mentioned we will be injecting those directives on input elements within DOM, one thing that we need to take care of is DOM structure. The whole POC is designed with the concept that directive will search for the nearest div / span with class "form-group" and attach the dynamic component with error message as child of that div / span.&lt;/p&gt;

&lt;p&gt;So all our input elements must be wrapped within "form-group" class. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- snippet from template form --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group user-data"&lt;/span&gt; &lt;span class="na"&gt;ngModelGroup=&lt;/span&gt;&lt;span class="s"&gt;"userData"&lt;/span&gt; &lt;span class="na"&gt;appFormGroupValidation&lt;/span&gt; &lt;span class="na"&gt;validationMsgId=&lt;/span&gt;&lt;span class="s"&gt;"userData"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"firstname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"firstname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;First Name:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;ngModel&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"firstname"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;[pattern]=&lt;/span&gt;&lt;span class="s"&gt;"validationPatterns.name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lastname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"lastName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Last Name:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;ngModel&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"lastName"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;[pattern]=&lt;/span&gt;&lt;span class="s"&gt;"validationPatterns.name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- snippet from reactive form --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group address"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"address"&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"address"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Address:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;formControlName=&lt;/span&gt;&lt;span class="s"&gt;"address"&lt;/span&gt; &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;appFormControlValidation&lt;/span&gt; &lt;span class="na"&gt;validationMsgId=&lt;/span&gt;&lt;span class="s"&gt;"address"&lt;/span&gt; &lt;span class="na"&gt;[pattern]=&lt;/span&gt;&lt;span class="s"&gt;"validationPatterns.address"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;We will be creating two directives - &lt;code&gt;appFormControlValidation&lt;/code&gt; and &lt;code&gt;appFormGroupValidation&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;appFormControlValidation&lt;/code&gt; - validates single input element i.e. &lt;code&gt;ngModel&lt;/code&gt; (in case of template driven form) and &lt;code&gt;FormControlName&lt;/code&gt; (in case of model driven form). It iterates over the object to check for "validator" property (only if "errors" property is defined) &amp;amp; sets the error to the input control in case of falsy value and removes the error in case of truthy value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Need to add required error - template driven forms.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;targetFormControl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;targetFormControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setErrors&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;targetFormControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Need to add required error - reactive forms.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;targetFormControl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;targetFormControl&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;setErrors&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;targetFormControl&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;appFormGroupValidation&lt;/code&gt; - validates group of input elements i.e. &lt;code&gt;FormGroup&lt;/code&gt;. It works exactly same as previous directive i.e. iterates over the object to check for "validator" property (only if "errors" property is defined) &amp;amp; sets the error to the input control in case of falsy value and removes the error in case of truthy value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;targetFormGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;NgModelGroup&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;targetFormGroup&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;statusChanges&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusChangeSubscription&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusChangeSubscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;targetFormGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusChanges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INVALID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;targetFormGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;touched&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dynamic component:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the validation is done, we display error messages dynamically using concept of Angular Dynamic Components.&lt;/p&gt;

&lt;p&gt;As soon as the validation is falsy i.e. user typed incorrect input, we invoke component factory resolver with view reference of given input element &amp;amp; inject the error component dynamically. Once the user has corrected the input value, we remove that reference (dynamic component) from the DOM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dynamicItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;componentFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentFactoryResolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolveComponentFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dynamicItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parentNode&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;vcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;componentFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;vcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;componentRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;componentFactory&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newChild&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;componentRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ErrorComponent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;elementRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;vcr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newChild&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;componentRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;DynamicComponent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dynamicItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Helper Functions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this POC, we need to helper utilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic error message generation service:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;It enables to generate error message dynamically.&lt;/li&gt;
&lt;li&gt;We can provide the key via &lt;code&gt;validationMsgId&lt;/code&gt; input property of directive. This key is use to construct error message which we then inject in DOM.&lt;/li&gt;
&lt;li&gt; Example: If the given field is required, then &lt;code&gt;ngModel&lt;/code&gt; / &lt;code&gt;FormControlName&lt;/code&gt; will have error property set to &lt;code&gt;{ required: true }&lt;/code&gt;. This service picks up the &lt;code&gt;required&lt;/code&gt; key and appends it to &lt;code&gt;validationMsgId&lt;/code&gt; (say for example address) provided by user i.e. address-required. If the given field has any pattern and id provided by user is "firstname", so generate key will be "firstname-pattern"&lt;/li&gt;
&lt;li&gt;If id is not provided by user, it defaults to "generic-required".
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;appFormControlValidation&lt;/span&gt; &lt;span class="na"&gt;validationMsgId=&lt;/span&gt;&lt;span class="s"&gt;"address"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorMessages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;generic-required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This field is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;generic-pattern&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pattern does not match&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;address-required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please enter complete postal address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;address-pattern&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Only Alpha-Numeric values and characters like `_ . / &amp;amp;` are allowed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
   &lt;span class="nf"&gt;getValidationMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errorMessages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errorMessages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`generic-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Validation on form submit:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Our directives only get invoked in case of "blur" or "change" event i.e. only when user interacts with the field. What if user never interacts with fields and directly tries to submit the form?&lt;/li&gt;
&lt;li&gt;In that use case, we need a mechanism to let user know to provide valid input before submission.&lt;/li&gt;
&lt;li&gt;On every submission, we can loop over &lt;code&gt;FormGroup&lt;/code&gt;, mark all inputs as "dirty" and "touched" and re-validate them using &lt;code&gt;updateValueAndValidity()&lt;/code&gt;, this enables Angular to perform validation once more.&lt;/li&gt;
&lt;li&gt;To optimize this, we can add &lt;code&gt;{ onlySelf: true }&lt;/code&gt; to update value and validity for given control only and not its parent elements.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validateForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbstractControl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
       &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markAsDirty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markAllAsTouched&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="nf"&gt;validateForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateValueAndValidity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;onlySelf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markAsDirty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markAsTouched&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateValueAndValidity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;onlySelf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://stackblitz.com/edit/angular-ivy-m4cjn4?file=src/app/app.component.ts" rel="noopener noreferrer"&gt;StackBliz Example&lt;/a&gt;&lt;/p&gt;

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