<?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: Nicola</title>
    <description>The latest articles on DEV Community by Nicola (@nicolalc).</description>
    <link>https://dev.to/nicolalc</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%2F207097%2F288e530c-ebb8-4857-a29d-1cdcd123058f.png</url>
      <title>DEV Community: Nicola</title>
      <link>https://dev.to/nicolalc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nicolalc"/>
    <language>en</language>
    <item>
      <title>Event-Driven Architecture for Clean React Component Communication</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Wed, 04 Dec 2024 12:46:40 +0000</pubDate>
      <link>https://dev.to/nicolalc/event-driven-architecture-for-clean-react-component-communication-fph</link>
      <guid>https://dev.to/nicolalc/event-driven-architecture-for-clean-react-component-communication-fph</guid>
      <description>&lt;p&gt;Are you tired of the endless tangle of props drilling and callback chains in your React applications? Does managing state and communication between deeply nested components feel like wrestling with spaghetti code?&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;event-driven architecture&lt;/strong&gt; can simplify your component interactions, reduce complexity, and make your app more maintainable. In this article, I’ll show you how to use a custom &lt;code&gt;useEvent&lt;/code&gt; hook to decouple components and improve communication across your React app.&lt;/p&gt;

&lt;p&gt;Let me walk you through it, let's start from&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This mechanism is not intended as a replacement for a global state management system but an alternative approach to component communication flow.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem: Props Drilling and Callback Chains
&lt;/h2&gt;

&lt;p&gt;In modern application development, managing state and communication between components can quickly become cumbersome. This is especially true in scenarios involving &lt;strong&gt;props drilling&lt;/strong&gt;—where data must be passed down through multiple levels of nested components—and &lt;strong&gt;callback chains&lt;/strong&gt;, which can lead to tangled logic and make code harder to maintain or debug.&lt;/p&gt;

&lt;p&gt;These challenges often create tightly coupled components, reduce flexibility, and increase the cognitive load for developers trying to trace how data flows through the application. Without a better approach, this complexity can significantly slow down development and lead to a &lt;strong&gt;brittle codebase&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Traditional Flow: Props Down, Callbacks Up
&lt;/h3&gt;

&lt;p&gt;In a typical React application, parent components pass props to their children, and children communicate back to the parent by triggering callbacks. This works fine for shallow component trees, but as the hierarchy deepens, things start to get messy:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Props Drilling&lt;/em&gt;&lt;/strong&gt;: Data must be passed down manually through multiple levels of components, even if only the deepest component needs it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Callback Chains&lt;/em&gt;&lt;/strong&gt;: Similarly, child components must forward event handlers up the tree, creating tightly coupled and hard-to-maintain structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Common Problem: Callback Complexity
&lt;/h3&gt;

&lt;p&gt;Take this scenario, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Parent passes props to &lt;strong&gt;Children A&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;From there, props are drilled down to &lt;strong&gt;GrandChildren A/B&lt;/strong&gt; and eventually to &lt;strong&gt;SubChildren N&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If &lt;strong&gt;SubChildren N&lt;/strong&gt; needs to notify the Parent of an event, it triggers a callback &lt;em&gt;that travels back up through each intermediate component&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup becomes harder to manage as the application grows. Intermediate components often act as nothing more than middlemen, forwarding props and callbacks, which bloats the code and reduces maintainability.&lt;/p&gt;

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

&lt;p&gt;To address &lt;strong&gt;props drilling&lt;/strong&gt;, we often turn to solutions like global state management libraries (e.g., &lt;strong&gt;Zustand&lt;/strong&gt;) to streamline data sharing. But what about managing callbacks?&lt;/p&gt;

&lt;p&gt;This is where an &lt;strong&gt;event-driven approach&lt;/strong&gt; can be a game-changer. By decoupling components and relying on events to handle interactions, we can significantly simplify callback management. Let’s explore how this approach works.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Enter the Event-Driven Approach
&lt;/h2&gt;

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

&lt;p&gt;Instead of relying on direct callbacks to communicate up the tree, &lt;strong&gt;&lt;em&gt;an event-driven architecture decouples components and centralizes communication&lt;/em&gt;&lt;/strong&gt;. Here’s how it works:&lt;/p&gt;

&lt;h4&gt;
  
  
  Event Dispatching
&lt;/h4&gt;

&lt;p&gt;When &lt;strong&gt;SubChildren N&lt;/strong&gt; triggers an event (e.g., onMyEvent), it doesn’t directly call a callback in the Parent.&lt;br&gt;
Instead, &lt;em&gt;it dispatches an event that is handled by a centralized Events Handler&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Centralized Handling
&lt;/h4&gt;

&lt;p&gt;The &lt;strong&gt;Events Handler&lt;/strong&gt; listens for the dispatched event and processes it.&lt;br&gt;
It can notify the Parent (or any other interested component) or trigger additional actions as required.&lt;/p&gt;
&lt;h4&gt;
  
  
  Props Remain Downward
&lt;/h4&gt;

&lt;p&gt;Props are still passed down the hierarchy, ensuring that components receive the data they need to function. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This can be solved with centralized state management tools like zustand, redux, but will not be covered in this article.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;But, &lt;em&gt;how do we implement this architecture?&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  useEvent hook
&lt;/h4&gt;

&lt;p&gt;Let's create a custom hook called &lt;strong&gt;useEvent&lt;/strong&gt;, this hook will be responsible of handling event subscription and returning a dispatch function to trigger the target event.&lt;/p&gt;

&lt;p&gt;As I am using typescript, I need to extend the window &lt;code&gt;Event&lt;/code&gt; interface in order to create custom events:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AppEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Event&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PayloadType&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;useEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknown&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;eventName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;CustomWindowEventMap&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="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;VoidFunction&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="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;By doing so, we can define custom events map and pass custom parameters:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AppEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Event&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PayloadType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CustomWindowEventMap&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;WindowEventMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* Custom Event */&lt;/span&gt;
  &lt;span class="nl"&gt;onMyEvent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// an event with a string payload&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;useEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknown&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;eventName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;CustomWindowEventMap&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="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;VoidFunction&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="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;Now that we defined needed interfaces, let's see the final hook code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Dispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AppEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Event&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PayloadType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CustomWindowEventMap&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;WindowEventMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* Custom Event */&lt;/span&gt;
  &lt;span class="nl"&gt;onMyEvent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppEvent&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="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;useEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unknown&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;eventName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;CustomWindowEventMap&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="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;VoidFunction&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;useEffect&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="o"&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="k"&gt;return&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;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PayloadType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Use `event.detail` for custom payloads&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;EventListener&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&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="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventName&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;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PayloadType&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="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;detail&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Return a function to dispatch the event&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;useEvent&lt;/code&gt; hook is a custom React hook for subscribing to and dispatching custom window events. It allows you to listen for custom events and trigger them with a specific payload.&lt;/p&gt;

&lt;p&gt;What we are doing here is pretty simple, we are using the standard event management system and extending it in order to accommodate our custom events.&lt;/p&gt;

&lt;h4&gt;
  
  
  Parameters:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;eventName&lt;/code&gt; (string): The name of the event to listen for.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;callback&lt;/code&gt; (optional): A function to call when the event is triggered, receiving the payload as an argument.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event Listener&lt;/strong&gt;: It listens for the specified event and calls the provided &lt;code&gt;callback&lt;/code&gt; with the event's &lt;code&gt;detail&lt;/code&gt; (custom payload).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dispatching Events&lt;/strong&gt;: The hook provides a &lt;code&gt;dispatch&lt;/code&gt; function to trigger the event with a custom payload.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example:
&lt;/h4&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;onMyEvent&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;data&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// To dispatch an event&lt;/span&gt;
&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// when dispatched, the event will trigger the callback&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok cool but, what about a&lt;/p&gt;

&lt;h2&gt;
  
  
  Real World Example?
&lt;/h2&gt;

&lt;p&gt;Check out this StackBlitz (&lt;em&gt;if it does not load, please check it &lt;a href="https://stackblitz.com/edit/event-drive-arch?file=src%2FApp.tsx" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/event-drive-arch?embed=1&amp;amp;file=src%2FApp.tsx&amp;amp;hideExplorer=1&amp;amp;hideNavigation=1" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This simple example showcases the purpose of the &lt;code&gt;useEvent&lt;/code&gt; hook, basically the body's button is dispatching an event that is intercepted from Sidebar, Header and Footer components, that updates accordingly.&lt;/p&gt;

&lt;p&gt;This let us define cause/effect reactions without the need to propagate a callback to many components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
As pointed out in the comments remember to memoize the callback function using &lt;code&gt;useCallback&lt;/code&gt; in order to avoid continous event removal and creation, as the callback itself will be a dependency of the &lt;code&gt;useEvent&lt;/code&gt; internal useEffect.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Use Cases for &lt;code&gt;useEvent&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Here are some &lt;strong&gt;real-world use cases&lt;/strong&gt; where the &lt;code&gt;useEvent&lt;/code&gt; hook can simplify communication and decouple components in a React application:&lt;/p&gt;




&lt;h4&gt;
  
  
  1. Notifications System
&lt;/h4&gt;

&lt;p&gt;A notification system often requires global communication.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When an API call succeeds, a "success" notification needs to be displayed across the app.&lt;/li&gt;
&lt;li&gt;Components like a "Notifications Badge" in the header need to update as well.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Use the &lt;code&gt;useEvent&lt;/code&gt; hook to dispatch an &lt;code&gt;onNotification&lt;/code&gt; event with the notification details. Components like the &lt;code&gt;NotificationBanner&lt;/code&gt; and &lt;code&gt;Header&lt;/code&gt; can listen to this event and update independently.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Theme Switching
&lt;/h4&gt;

&lt;p&gt;When a user toggles the theme (e.g., light/dark mode), multiple components may need to respond.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;ThemeToggle&lt;/code&gt; component dispatches a custom &lt;code&gt;onThemeChange&lt;/code&gt; event.&lt;/li&gt;
&lt;li&gt;Components like the Sidebar and Header listen for this event and update their styles accordingly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;: No need to pass the theme state or callback functions through props across the entire component tree.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Global Key Bindings
&lt;/h4&gt;

&lt;p&gt;Implement global shortcuts, such as pressing "Ctrl+S" to save a draft or "Escape" to close a modal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;A global keydown listener dispatches an &lt;code&gt;onShortcutPressed&lt;/code&gt; event with the pressed key details.&lt;/li&gt;
&lt;li&gt;Modal components or other UI elements respond to specific shortcuts without relying on parent components to forward the key event.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Real-Time Updates
&lt;/h4&gt;

&lt;p&gt;Applications like chat apps or live dashboards require multiple components to react to real-time updates.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;A WebSocket connection dispatches &lt;code&gt;onNewMessage&lt;/code&gt; or &lt;code&gt;onDataUpdate&lt;/code&gt; events when new data arrives.&lt;/li&gt;
&lt;li&gt;Components such as a chat window, notifications, and unread message counters can independently handle updates.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  5. Form Validation Across Components
&lt;/h4&gt;

&lt;p&gt;For complex forms with multiple sections, validation events can be centralized.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;A form component dispatches &lt;code&gt;onFormValidate&lt;/code&gt; events as users fill out fields.&lt;/li&gt;
&lt;li&gt;A summary component listens for these events to display validation errors without tightly coupling with form logic.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  6. Analytics Tracking
&lt;/h4&gt;

&lt;p&gt;Track user interactions (e.g., button clicks, navigation events) and send them to an analytics service.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Dispatch &lt;code&gt;onUserInteraction&lt;/code&gt; events with relevant details (e.g., the clicked button’s label).&lt;/li&gt;
&lt;li&gt;A central analytics handler listens for these events and sends them to an analytics API.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  7. Collaboration Tools
&lt;/h4&gt;

&lt;p&gt;For collaborative tools like shared whiteboards or document editors, events can manage multi-user interactions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Dispatch &lt;code&gt;onUserAction&lt;/code&gt; events whenever a user draws, types, or moves an object.&lt;/li&gt;
&lt;li&gt;Other clients and UI components listen for these events to reflect the changes in real time.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By leveraging the &lt;code&gt;useEvent&lt;/code&gt; hook in these scenarios, you can create &lt;strong&gt;modular, maintainable, and scalable applications&lt;/strong&gt; without relying on deeply nested props or callback chains.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Events can transform the way you build React applications by reducing complexity and improving modularity. Start small—identify a few components in your app that would benefit from decoupled communication and implement the useEvent hook.&lt;/p&gt;

&lt;p&gt;With this approach, you’ll not only simplify your code but also make it easier to maintain and scale in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use Events?&lt;/strong&gt;&lt;br&gt;
Events shine when you need your components to react to something that happened elsewhere in your application, without introducing unnecessary dependencies or convoluted callback chains. This approach reduces the cognitive load and avoids the pitfalls of tightly coupling components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Recommendation&lt;/strong&gt;&lt;br&gt;
Use events for inter-component communication—when one component needs to notify others about an action or state change, regardless of their location in the component tree.&lt;br&gt;
Avoid using events for intra-component communication, especially for components that are closely related or directly connected. For these scenarios, rely on React's built-in mechanisms like props, state, or context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Balanced Approach&lt;/strong&gt;&lt;br&gt;
While events are powerful, overusing them can lead to chaos. Use them judiciously to simplify communication across loosely connected components, but don’t let them replace React’s standard tools for managing local interactions.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Simple alert styling using SASS MAPS</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Tue, 04 Aug 2020 14:06:15 +0000</pubDate>
      <link>https://dev.to/nicolalc/simple-alert-styling-using-scss-maps-125b</link>
      <guid>https://dev.to/nicolalc/simple-alert-styling-using-scss-maps-125b</guid>
      <description>&lt;p&gt;Hi folks! 🖖&lt;/p&gt;

&lt;p&gt;In this little tutorial, we'll learn how to use &lt;strong&gt;&lt;em&gt;sass maps&lt;/em&gt;&lt;/strong&gt; to create some simple variants to a custom alert component.&lt;/p&gt;

&lt;p&gt;The idea is to use sass &lt;strong&gt;&lt;em&gt;maps&lt;/em&gt;&lt;/strong&gt; to define a complex set of CSS variables. These variables will be cycled using &lt;em&gt;@each&lt;/em&gt; mixin to create the final set of classes for our alert.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I'll use SCSS syntax instead of pure SASS. I prefer this syntax, but you can use what you like.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  SASS MAPS?
&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="https://sass-lang.com/documentation/values/maps" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Maps in Sass hold pairs of keys and values, and make it easy to look up a value by its corresponding key. They’re written (: , : ). The expression before the : is the key, and the expression after is the value associated with that key. The keys must be unique, but the values may be duplicated. Unlike lists, maps must be written with parentheses around them. A map with no pairs is written ().&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;sass maps are complex variables (we can define them as an &lt;em&gt;object&lt;/em&gt; variable).&lt;/p&gt;

&lt;p&gt;We will use the following methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;map-&lt;strong&gt;get&lt;/strong&gt;: returns an object value by key&lt;/li&gt;
&lt;li&gt;map-&lt;strong&gt;keys&lt;/strong&gt;: returns a list of object keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final result will be something like that:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/NicolaCastellaniDev/embed/abNoWMx?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note - this tutorial will cover only the map management and loop part, any other CSS styles and HTML / Javascript code is included in the pen, but not necessary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Defining the map
&lt;/h2&gt;

&lt;p&gt;First of all, we need to define the map variable in our scss file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// maps of maps, used to define different alert type properties&lt;/span&gt;
&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#12cbc4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"titleColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#833471&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"messageColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#4a4a4a&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"info"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#7ed6df&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"titleColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#30336b&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"messageColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#4a4a4a&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"warning"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#f0932b&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"titleColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#2c2c54&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"messageColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#4a4a4a&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"backgroundColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#ee5253&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"titleColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#ff9f43&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"messageColor"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#4a4a4a&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see this map is an object composed by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;key&lt;/em&gt;&lt;/strong&gt;: the name of the class modifier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;value&lt;/em&gt;&lt;/strong&gt;: a &lt;em&gt;scss map&lt;/em&gt; used to define some properties like:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;backgroundColor&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;titleColor&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;messageColor&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating the loop for the class definitions
&lt;/h2&gt;

&lt;p&gt;We can now use the &lt;strong&gt;&lt;em&gt;@each&lt;/em&gt;&lt;/strong&gt; mixin to loop through our &lt;strong&gt;&lt;em&gt;$alerts&lt;/em&gt;&lt;/strong&gt; map keys. This will let us define the properties for each alert type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.alert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;map-keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// define the props here     &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;next we use &lt;strong&gt;&lt;em&gt;$alertType&lt;/em&gt;&lt;/strong&gt; var as a selector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.alert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;map-keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$alertType&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// .alert-default compiled (for example)&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 mixin will generate the following css:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.alert.alert-default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.alert.alert-info&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.alert.alert-warning&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.alert.alert-error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we define the custom properties based on current class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;strong&gt;&lt;em&gt;map-get&lt;/em&gt;&lt;/strong&gt; to retrieve class related properties
&lt;/h2&gt;

&lt;p&gt;We can use the &lt;strong&gt;&lt;em&gt;map-get&lt;/em&gt;&lt;/strong&gt; method to get the &lt;em&gt;backgroundColor&lt;/em&gt; property for a specific class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.alert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;map-keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$alertType&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;backgroundColor&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;This will generate the following css:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.alert.alert-default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#12cbc4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.alert.alert-info&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#7ed6df&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.alert.alert-warning&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f0932b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.alert.alert-error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ee5253&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Nested classes properties
&lt;/h2&gt;

&lt;p&gt;I don't want to go too far or bore you with unnecessary concepts, so I will give you the complete styling for nested classes as follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.alert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;map-keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$alertType&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;backgroundColor&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;.alert-title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;titleColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;.alert-message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;messageColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;.alert-close&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$alerts&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$alertType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;backgroundColor&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course this is only an example, you can use your custom selectors and HTML structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;This little tutorial shows how you can handle different type of modifiers/classes with a little bit of scss code. Instead of defining the same properties N times (&lt;em&gt;with N = number of variations we want to handle&lt;/em&gt;), we can use sass maps to handle them smartly.&lt;/p&gt;

&lt;p&gt;What do you think? Do you agree with this method? Do you have any advice?&lt;/p&gt;

&lt;p&gt;Thanks for reading and good coding 🐱‍👤&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>css</category>
    </item>
    <item>
      <title>How to become a Game Developer?</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Mon, 27 Jul 2020 10:02:09 +0000</pubDate>
      <link>https://dev.to/nicolalc/how-to-become-a-game-developer-4mlj</link>
      <guid>https://dev.to/nicolalc/how-to-become-a-game-developer-4mlj</guid>
      <description>&lt;p&gt;Hi folks!😍&lt;/p&gt;

&lt;p&gt;Today I want to start a discussion about &lt;strong&gt;how to become a game developer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But first a little bit of&lt;/p&gt;

&lt;h2&gt;
  
  
  premises ❗
&lt;/h2&gt;

&lt;p&gt;I'm a full-stack web developer, I've worked on the web since 7 years ago, for different customers.&lt;/p&gt;

&lt;p&gt;During this time I've worked a lot on Unity in my free time, because of the complexity and different skills to handle while working on a game, I've fallen in love with game development.&lt;/p&gt;

&lt;p&gt;I'm a creative developer, I love to develop, but also to design, create music and storylines, but I work mainly with banks, insurances and pharma agencies. So my work is not as creative as I want.&lt;/p&gt;

&lt;p&gt;After these years, I'm so sick and tired working on the web, and frontend development in general. That's because it seems than every day I do the same things, in an infinite loop.&lt;/p&gt;

&lt;p&gt;I want to &lt;strong&gt;change&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The game development idea
&lt;/h2&gt;

&lt;p&gt;So, what can fit my needs, to code and design at the same time?&lt;/p&gt;

&lt;p&gt;Of course, &lt;em&gt;game development!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every time I work on a game idea, I spent a lot of hours per day, and I stop working on it only for physical needs (like, of course, sleeping 🤣).&lt;/p&gt;

&lt;p&gt;The next day, I wake up with a lot of ideas in mind, I feel really happy to work on a personal game. And this changes completely my lifecycle.&lt;/p&gt;

&lt;p&gt;So I've decided to become a &lt;strong&gt;&lt;em&gt;game developer&lt;/em&gt;&lt;/strong&gt;! 👨‍💻&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems
&lt;/h2&gt;

&lt;p&gt;There are 2 big problems I've found looking for a game developer job:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I live in &lt;strong&gt;Italy&lt;/strong&gt;, where there aren't a lot of possibilities in this industry.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Experience&lt;/strong&gt;, I've worked on Unity for a lot of time, but I'm still a junior dev, and here is hard to find a job as a junior unity developer (2 years of working experience at least needed).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So basically it's hard to find a job as unity developer here, and I have 2 solutions ahead:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Working abroad 🐱‍🏍
&lt;/h2&gt;

&lt;p&gt;This is a big challenge, working abroad, starting a new career as a junior developer, could be an amazing challenge, but also stressy.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Create a game software house 🐱‍🐉
&lt;/h2&gt;

&lt;p&gt;The other solution is to create a software house here in Italy. This is a great challenge but could be my real mission.&lt;br&gt;
The pros of this choice are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create something &lt;em&gt;unique&lt;/em&gt; and &lt;em&gt;personal&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Give others the &lt;em&gt;possibility&lt;/em&gt; I didn't have in the future&lt;/li&gt;
&lt;li&gt;Be part of the &lt;em&gt;rise of the gaming industry in Italy&lt;/em&gt;, and one of the pioneers in this sector.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm choosing what to do in the next year, which will be the most important in my career to choose my future life.&lt;/p&gt;

&lt;p&gt;What do you think? Do you have any advice? Have you ever had a similar choice to do?&lt;/p&gt;

&lt;p&gt;Let me know, I will be more than happy to hear tips from you all!&lt;/p&gt;

&lt;p&gt;Cheers 🐱‍👤&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>GSAP Animated Select</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Mon, 29 Jun 2020 09:06:25 +0000</pubDate>
      <link>https://dev.to/nicolalc/gsap-animated-select-2ngk</link>
      <guid>https://dev.to/nicolalc/gsap-animated-select-2ngk</guid>
      <description>&lt;p&gt;Hi to all!&lt;/p&gt;

&lt;p&gt;I want to show you all a cool example of an animated select I've made using &lt;a href="https://greensock.com/" rel="noopener noreferrer"&gt;GreenSock&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As we know the &lt;strong&gt;&lt;em&gt;select&lt;/em&gt;&lt;/strong&gt; HTML component is one of the hardest HTML element to customize. It's hard to create a unique styled select component using the native &lt;em&gt;select&lt;/em&gt; HTML tag.&lt;/p&gt;

&lt;p&gt;So often we need to create a custom HTML template to handle custom styled selects.&lt;/p&gt;

&lt;p&gt;In this example, I've wanted to create a cool animation (still basic btw) on my custom select using GreenSock and CSS transitions, here there is the final result:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/NicolaCastellaniDev/embed/vYLegjZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;What do you think about it? Do you have any suggestion? Let me know in the comments 😎😎&lt;/p&gt;

</description>
      <category>programming</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>GSAP Animations in Angular - Handle animateOut</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Wed, 17 Jun 2020 14:53:41 +0000</pubDate>
      <link>https://dev.to/nicolalc/gsap-animations-in-angular-handle-animateout-38ej</link>
      <guid>https://dev.to/nicolalc/gsap-animations-in-angular-handle-animateout-38ej</guid>
      <description>&lt;h1&gt;
  
  
  Handle the out animation of our components
&lt;/h1&gt;

&lt;p&gt;Now that we have done the &lt;strong&gt;animationIn&lt;/strong&gt; of our components, we want to handle also the &lt;strong&gt;animationOut&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, we want to &lt;em&gt;hide&lt;/em&gt; our HTML element with a fancy fade out animation, but if we use the structural directive *ngIf of angular the animation will not work, because angular will remove physically the element from the view.&lt;/p&gt;

&lt;p&gt;So how can we do it? Let's start with the classic *ngIf directive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Toggle HTML elements
&lt;/h2&gt;

&lt;p&gt;Let's proceed with the logic to toggle our HTML elements, in our &lt;strong&gt;app.component.ts&lt;/strong&gt; we need to add this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-app-title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;showP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;toggleP&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;showP&lt;/span&gt; &lt;span class="o"&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;showP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method &lt;em&gt;toggleP&lt;/em&gt; will toggle the boolean &lt;em&gt;showP&lt;/em&gt;, which will be used in our &lt;strong&gt;app.component.html&lt;/strong&gt; to show/hide our elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"showP"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  That's a cool effect, or not?
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;
  &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"showP"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  This too, but a little bit delayed
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Let's add a button to call &lt;em&gt;toggleP&lt;/em&gt; method (animated too 😎):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"showP"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  That's a cool effect, or not?
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;
  &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"showP"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  This too, but a little bit delayed
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;
  &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"toggleP()"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{showP ? "Hide P" : "Show P"}}
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run the application, as you will see the animationOut will not be triggered:&lt;/p&gt;

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

&lt;p&gt;As you can see the directive removes directly the HTML element, so how can we handle it without deleting the HTML element?&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;strong&gt;&lt;em&gt;ngIfAnimated&lt;/em&gt;&lt;/strong&gt; directive
&lt;/h2&gt;

&lt;p&gt;We can create a custom &lt;strong&gt;structural directive&lt;/strong&gt;, create a directory inside &lt;code&gt;directives/&lt;/code&gt; folder, called &lt;em&gt;structural&lt;/em&gt;, and a file named &lt;code&gt;ngIf-animated.directive.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Directive&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;EmbeddedViewRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TemplateRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ViewContainerRef&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;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;CoreAnimationDirective&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;../gsap/core-animation.directive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[ngIfAnimated]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NgIfAnimatedDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;childViewRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EmbeddedViewRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CoreAnimationDirective&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;templateRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TemplateRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;viewContainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ViewContainerRef&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;ngIfAnimated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;show&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;show&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;childViewRef&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;viewContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createEmbeddedView&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;templateRef&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;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;childViewRef&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;node&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;childViewRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rootNodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;animate-out&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;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;parentViewRef&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;viewContainer&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="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 directive will show and hide an embedded &lt;strong&gt;viewRef&lt;/strong&gt; using an @Input parameter called &lt;strong&gt;ngIfAnimated&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If passed &lt;strong&gt;&lt;em&gt;show&lt;/em&gt;&lt;/strong&gt; boolean is true, then it will create and &lt;strong&gt;embeddedView&lt;/strong&gt;, else it will dispatch a &lt;strong&gt;CustomEvent&lt;/strong&gt; on the first &lt;em&gt;rootNode&lt;/em&gt;, passing the &lt;strong&gt;viewContainer&lt;/strong&gt; reference. We will see why in a moment.&lt;/p&gt;

&lt;p&gt;We need to handle the event trigger inside our &lt;strong&gt;&lt;em&gt;CoreAnimationDirective&lt;/em&gt;&lt;/strong&gt;, the component will receive the event, run the animation out and clear the parent view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CoreAnimationDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;reverseComplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TimelineMax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;protected&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;ElementRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// handle animate-out event&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;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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;animate-out&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;detail&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;animateOut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentViewRef&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;timeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TimelineMax&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;complete&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;onReverseComplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;reverseComplete&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;paused&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="na"&gt;reversed&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;protected&lt;/span&gt; &lt;span class="nf"&gt;animateIn&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isActive&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;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kill&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;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;animateOut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parentViewRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ViewContainerRef&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isActive&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;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kill&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeScale&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;duration&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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;parentViewRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;parentViewRef&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="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;duration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&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;delay&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&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;As you can see we have added 2 new thing to our CoreAnimationDirective:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;animate-out&lt;/em&gt;&lt;/strong&gt; event handler - handle the event on HTML element and call the method &lt;strong&gt;animateOut&lt;/strong&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;animateOut&lt;/em&gt;&lt;/strong&gt; method - this method play the animation of the directive, but &lt;em&gt;reversed&lt;/em&gt;. It kills the timeline if is running, and set a timeout to clear the &lt;em&gt;parentViewRef&lt;/em&gt;, according to the animation duration and delay.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we have only to declare our &lt;strong&gt;ngIfAnimated&lt;/strong&gt; inside the &lt;em&gt;app.module&lt;/em&gt; and replace the previous *ngIf with *ngIfAnimated on our html elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;FadeInAnimationDirective&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;NgIfAnimatedDirective&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;BrowserModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;AppRoutingModule&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;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;*ngIfAnimated=&lt;/span&gt;&lt;span class="s"&gt;"showP"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  That's a cool effect, or not?
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;
  &lt;span class="na"&gt;*ngIfAnimated=&lt;/span&gt;&lt;span class="s"&gt;"showP"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  This too, but a little bit delayed
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;
  &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"toggleP()"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{showP ? "Hide P" : "Show P"}}
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn5vm7u7h70odg88oxjs4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn5vm7u7h70odg88oxjs4.gif" alt="Animate out result" width="552" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What will come next
&lt;/h2&gt;

&lt;p&gt;In the next parts of this series we will take a look on how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Handle animations with &lt;strong&gt;&lt;em&gt;MouseEvent&lt;/em&gt;&lt;/strong&gt;, for example to scale up a button.&lt;/li&gt;
&lt;li&gt;How to keep all &lt;strong&gt;&lt;em&gt;stateless&lt;/em&gt;&lt;/strong&gt;, using ngrx, to handle complex animations while routing.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>tutorial</category>
      <category>angular</category>
      <category>typescript</category>
      <category>greensock</category>
    </item>
    <item>
      <title>GSAP Animations in Angular - Apply directive to html</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Wed, 17 Jun 2020 14:53:36 +0000</pubDate>
      <link>https://dev.to/nicolalc/gsap-animations-in-angular-apply-directive-to-html-3kbp</link>
      <guid>https://dev.to/nicolalc/gsap-animations-in-angular-apply-directive-to-html-3kbp</guid>
      <description>&lt;h1&gt;
  
  
  Let's apply the directive to our HTML elements!
&lt;/h1&gt;

&lt;p&gt;Now we can apply the directive to our HTMLElements. First of all we need to declare the &lt;strong&gt;&lt;em&gt;FadeInDirective&lt;/em&gt;&lt;/strong&gt; inside the &lt;strong&gt;AppModule&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BrowserModule&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;@angular/platform-browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgModule&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;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppRoutingModule&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;./app-routing.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppComponent&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;./app.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;FadeInAnimationDirective&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;./directives/gsap/fade-in-animation.directive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;FadeInAnimationDirective&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;BrowserModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;AppRoutingModule&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;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&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;And in your &lt;em&gt;app.component.html&lt;/em&gt; add this HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  That's a cool effect, or not?
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are creating a &lt;strong&gt;&lt;em&gt;paragraph&lt;/em&gt;&lt;/strong&gt; animated with a fadeIn animation using our directive, with a duration of &lt;em&gt;1 second&lt;/em&gt; and a delay of &lt;em&gt;1 second&lt;/em&gt; too! This should be the result:&lt;/p&gt;

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

&lt;p&gt;As you can see, the animation is working! You can also combine different animations using different delays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  That's a cool effect, or not?
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;fadeInAnimation&lt;/span&gt;
  &lt;span class="na"&gt;[duration]=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;[delay]=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  This too, but a little bit delayed
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

</description>
      <category>tutorial</category>
      <category>angular</category>
      <category>typescript</category>
      <category>greensock</category>
    </item>
    <item>
      <title>GSAP Animations in Angular - Animation Directives</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Wed, 17 Jun 2020 14:53:31 +0000</pubDate>
      <link>https://dev.to/nicolalc/gsap-animations-in-angular-animation-directives-14pi</link>
      <guid>https://dev.to/nicolalc/gsap-animations-in-angular-animation-directives-14pi</guid>
      <description>&lt;h1&gt;
  
  
  Create a directive for animation
&lt;/h1&gt;

&lt;p&gt;As the second part of this tutorial we will create an &lt;strong&gt;&lt;a href="!https://angular.io/guide/attribute-directives"&gt;attribute-directive&lt;/a&gt;&lt;/strong&gt;, which will define a specific animation and its attributes.&lt;/p&gt;

&lt;p&gt;We will start with a simple &lt;strong&gt;&lt;em&gt;FadeIn&lt;/em&gt;&lt;/strong&gt; animation.&lt;/p&gt;

&lt;p&gt;But before starting with the real directive, we are going to create a generic class which will be extended by arbitrary directives, called &lt;strong&gt;CoreAnimationDirective&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The goal of this directive is to define the standard methods and attributes for our future animation directives, to prevent a lot of repeats and hard-to-mantain directives.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The &lt;strong&gt;&lt;em&gt;CoreAnimationDirective&lt;/em&gt;&lt;/strong&gt; class
&lt;/h3&gt;

&lt;p&gt;Let's create! Before doing anything, let's create a specific folder for gsap directive.&lt;/p&gt;

&lt;p&gt;From 'src/app' run in terminal &lt;code&gt;mkdir directives\gsap&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: use \ or / directory separator according to your system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your project should look like this:&lt;/p&gt;

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

&lt;p&gt;Let's create the class, move to the gsap directory &lt;code&gt;cd directives\gsap &amp;amp; echo &amp;gt; core-animation.directive.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the file and write the following:&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;ElementRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Output&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;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;TimelineMax&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;gsap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CoreAnimationDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;reverseComplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TimelineMax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;protected&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;ElementRef&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;A little bit of explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@Input() duration&lt;/strong&gt; - the duration of the animation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@Input() delay&lt;/strong&gt; - the delay of the animation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@Output() complete&lt;/strong&gt; - event emitter for the animation complete callback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@Output() reverseComplete&lt;/strong&gt; - event emitter for the animation reverseComplete callback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;protected timeline: TimelineMax&lt;/strong&gt; - the timeline for animation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check the docs about &lt;em&gt;TimelineMax&lt;/em&gt; and &lt;em&gt;eventCallbacks&lt;/em&gt; &lt;a href="https://greensock.com/docs/v2/TimelineMax" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;constructor&lt;/em&gt;&lt;/strong&gt; have only 1 param, the element (ElementRef), it's the ref to the native element which uses the directive.&lt;/p&gt;

&lt;p&gt;We need to instantiate our &lt;strong&gt;&lt;em&gt;timeline&lt;/em&gt;&lt;/strong&gt; before animating it inside the constructor:&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="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;protected&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;ElementRef&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;timeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TimelineMax&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;complete&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;onReverseComplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;reverseComplete&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;paused&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="na"&gt;reversed&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;This piece of code will create a new timeline, paused and not reversed, with a &lt;strong&gt;&lt;em&gt;onComplete&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;onReverseComplete&lt;/em&gt;&lt;/strong&gt; callback.&lt;/p&gt;

&lt;p&gt;Let's create the &lt;strong&gt;&lt;em&gt;animateIn&lt;/em&gt;&lt;/strong&gt; method:&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;protected&lt;/span&gt; &lt;span class="nf"&gt;animateIn&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isActive&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;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kill&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;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&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 method will kill the animation if in progress (you can return if is active so it will not stop), and play the current animation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;strong&gt;&lt;em&gt;FadeInDirective&lt;/em&gt;&lt;/strong&gt; class
&lt;/h3&gt;

&lt;p&gt;Let's proceed with the next class, this class will perform the real animation.&lt;/p&gt;

&lt;p&gt;It will extend the &lt;strong&gt;&lt;em&gt;CoreAnimationClass&lt;/em&gt;&lt;/strong&gt;, as we don't need to repeat some portions of code.&lt;/p&gt;

&lt;p&gt;Inside the &lt;em&gt;gsap&lt;/em&gt; folder we've created previously, run &lt;code&gt;echo &amp;gt; fade-in-animation.directive.ts&lt;/code&gt; and write the following code inside:&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;Directive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ViewContainerRef&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;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&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;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TimelineMax&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;gsap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CoreAnimationDirective&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;./core-animation.directive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[fadeInAnimation]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FadeInAnimationDirective&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;CoreAnimationDirective&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;protected&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;ElementRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform animation&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;animateIn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;animateIn&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;timeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&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;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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Expo.easeInOut&lt;/span&gt;&lt;span class="dl"&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;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;animateIn&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 component extends the CoreAnimationDirective, so we don't need to define the @Input, @Output and other properties twice.&lt;/p&gt;

&lt;p&gt;We need to create the opacity animation using &lt;strong&gt;this.timeline.from&lt;/strong&gt; as follow:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;this.timeline.from(this.element.nativeElement, this.duration, {opacity:'0', ease:"Expo.easeInOut"}, this.delay);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will perform an animation on element opacity, from 0 to 1 (or to element opacity current value).&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>angular</category>
      <category>typescript</category>
      <category>greensock</category>
    </item>
    <item>
      <title>GSAP Animations in Angular - Getting Started</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Wed, 17 Jun 2020 14:53:14 +0000</pubDate>
      <link>https://dev.to/nicolalc/gsap-animations-in-angular-getting-started-15bg</link>
      <guid>https://dev.to/nicolalc/gsap-animations-in-angular-getting-started-15bg</guid>
      <description>&lt;h1&gt;
  
  
  What is GSAP and what will we learn in this tutorial
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Greensock Animation API&lt;/em&gt;&lt;/strong&gt; &lt;a href="https://greensock.com/" rel="noopener noreferrer"&gt;GSAP&lt;/a&gt; is an animation library written in JavaScript. It works with &lt;em&gt;ES6 and above&lt;/em&gt; javascript environments, and lets you create animations without struggles. It's the most used animation library in the world, and for specific reasons, it is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Performant&lt;/li&gt;
&lt;li&gt;Easy to use&lt;/li&gt;
&lt;li&gt;Easy to understand&lt;/li&gt;
&lt;li&gt;Handle SVG animations seamlessly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this tutorial series we will learn how to use GSAP in Angular, using attribute and structural directives.&lt;/p&gt;

&lt;p&gt;This is what we will create:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/angular-gsap-directives?" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: This tutorial will cover only a 1% of GSAP functionalities, for more visit the library &lt;a href="https://greensock.com/" rel="noopener noreferrer"&gt;website&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Angular base knowledge&lt;/li&gt;
&lt;li&gt;npm basic knowledge&lt;/li&gt;
&lt;li&gt;GSAP basic knowledge&lt;/li&gt;
&lt;li&gt;Angular and Node installed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Part 1. Install GSAP
&lt;/h2&gt;

&lt;p&gt;Create a new angular app with the following command: &lt;code&gt;ng new myApp&lt;/code&gt;, choose the name you want for the app, angular routing and SCSS as the main style preprocessor (or what you prefer).&lt;/p&gt;

&lt;p&gt;Installing GSAP in Angular is pretty simple using &lt;strong&gt;npm&lt;/strong&gt;, from the root of your angular app type &lt;code&gt;npm install --save gsap @types/gsap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the installations are successful you will get a message in the terminal as follow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1qjlmsdlkm80e3us8ekt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1qjlmsdlkm80e3us8ekt.png" alt="Installation successful" width="611" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will install GSAP and its types as a dependency of your project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: you could get different packages version, these are the latest versions nowadays.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next episode we will create the core directive and our first animation!&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks to
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://clideo.com/" rel="noopener noreferrer"&gt;clideo.com&lt;/a&gt; - an amazing tool to edit videos online (you can also make memes 😎)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.onlineconverter.com/" rel="noopener noreferrer"&gt;onlineconverter.com&lt;/a&gt; - an online tool to convert video (and other files)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.tabnine.com/" rel="noopener noreferrer"&gt;TabNine&lt;/a&gt; - a plugin for a lot of IDEs which uses deep learning to perform code completion - see the article &lt;a href="https://dev.to/nicolalc/tabnine-put-your-coding-speed-to-the-next-level-4e6a"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>angular</category>
      <category>typescript</category>
      <category>greensock</category>
    </item>
    <item>
      <title>TabNine - Put your coding speed to the next level</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Wed, 10 Jun 2020 16:17:48 +0000</pubDate>
      <link>https://dev.to/nicolalc/tabnine-put-your-coding-speed-to-the-next-level-4e6a</link>
      <guid>https://dev.to/nicolalc/tabnine-put-your-coding-speed-to-the-next-level-4e6a</guid>
      <description>&lt;h1&gt;
  
  
  Deep learning at the rescue! 👨‍💻👩‍💻
&lt;/h1&gt;

&lt;p&gt;In this article I'll talk about &lt;strong&gt;&lt;em&gt;TabNine&lt;/em&gt;&lt;/strong&gt;, an AI Code Completion system for all languages, with a focus on JavaScript.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="http://tabnine.com/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=nicolac"&gt;TabNine&lt;/a&gt;&lt;/em&gt; is a plugin owned and operated by &lt;a href="http://codota.com/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=nicolac"&gt;Codota&lt;/a&gt;, who offers also a plugin for Java Code Completions.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  What is TabNine?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TabNine&lt;/strong&gt; helps developers writing code with some magics. It's based on a system of &lt;strong&gt;deep learning&lt;/strong&gt; to help you writing code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;FASTER&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EASIER&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLEANER&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a &lt;strong&gt;free&lt;/strong&gt; (yes, &lt;strong&gt;&lt;em&gt;free&lt;/em&gt;&lt;/strong&gt;) plugin for major IDEs like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IntelliJ PyCharm&lt;/li&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;li&gt;Sublime&lt;/li&gt;
&lt;li&gt;IntelliJ PhpStorm&lt;/li&gt;
&lt;li&gt;VIM&lt;/li&gt;
&lt;li&gt;Atom&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and many others:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgyhku5mjaluasf890er0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgyhku5mjaluasf890er0.png" alt="TabNine supported IDEs" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  How does it works?
&lt;/h1&gt;

&lt;p&gt;TabNine indexes your code and finds statistical patterns to create customized suggestions based on &lt;strong&gt;how you write your own code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Take the following example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgvy1pdunltpcan54i1mn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgvy1pdunltpcan54i1mn.gif" alt="Auto var declaration" width="320" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As shown TabNine learns automatically my variable declaration pattern while writing it, and suggest me the best match for the code I'll write after. By this way you can speed up &lt;em&gt;variable declarations&lt;/em&gt;, if you use a well defined naming convention.&lt;/p&gt;

&lt;p&gt;TabNine offers different solutions while writing, and displays a &lt;strong&gt;percentage&lt;/strong&gt; value based on the best match he find:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqnr7tkycr04qp2jxg9ji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqnr7tkycr04qp2jxg9ji.png" alt="Percent on suggestions" width="503" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a simple example to show how TabNine helps you write your code, the next examples will show more complex and ordinary-like use cases of this amazing tool!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This article is written in MarkDown and TabNine is helping me writing it! That's pretty cool! 😎&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F21rjdy7gyx4zxldb0gra.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F21rjdy7gyx4zxldb0gra.gif" alt="Markdown edit with TabNine" width="600" height="122"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Install
&lt;/h1&gt;

&lt;p&gt;TabNine is an IDE plugin, so the installation process depends on which IDE you are using. I'll show the installation process for some of the most used IDEs:&lt;/p&gt;

&lt;h4&gt;
  
  
  Visual Studio Code
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Press &lt;strong&gt;CTRL + P&lt;/strong&gt; to open the command prompt.&lt;/li&gt;
&lt;li&gt;Run the following command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  ext &lt;span class="nb"&gt;install &lt;/span&gt;TabNine.tabnine-vscode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Reload VS Code manually or by after-install prompt.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  IntelliJ Idea
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Press &lt;strong&gt;CTRL + Alt + S&lt;/strong&gt; to open the settings popup&lt;/li&gt;
&lt;li&gt;Go under &lt;em&gt;Plugins/Marketplace&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Search &lt;em&gt;TabNine&lt;/em&gt; and install&lt;/li&gt;
&lt;li&gt;Manually reload the IDE&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Atom
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Under &lt;strong&gt;&lt;a href="https://atom.io/packages/search?q=TabNine" rel="noopener noreferrer"&gt;packages&lt;/a&gt;&lt;/strong&gt; you can simply search and install &lt;em&gt;TabNine&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;You can check installation process for other IDE &lt;a href="https://www.tabnine.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Examples
&lt;/h1&gt;

&lt;p&gt;Let's go deep on &lt;em&gt;how&lt;/em&gt; to use TabNine and &lt;em&gt;why&lt;/em&gt;. There are a lot of examples I could show you but I'll focus on some specific use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1. Comment-Driven code completition
&lt;/h3&gt;

&lt;p&gt;With TabNine we can use &lt;a href="https://jsdoc.app/" rel="noopener noreferrer"&gt;jsdoc&lt;/a&gt; to generate functions and complex objects dinamically. This could be useful by defining the interface first and then the implementation.&lt;/p&gt;

&lt;p&gt;Take this example, we want to define a &lt;strong&gt;sum&lt;/strong&gt; function:&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="cm"&gt;/**
 * @description return a sum between a and b
 * @name        sumBy
 * @param       {number} a
 * @param       {number} b
 * @return      {number} the sum between a and b
 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;TabNine&lt;/em&gt; will read the jsdoc params and suggest you the correct code definition.&lt;br&gt;
I can just type Alt + Space (or Tab) to write the function:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frhfjiernnia7r7lah71h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frhfjiernnia7r7lah71h.gif" alt="Comment driven completition" width="600" height="302"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Classes development and extension
&lt;/h4&gt;

&lt;p&gt;You can also use this tool with class definition. Take this 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="cm"&gt;/**
 * @description Animal class
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * @constructor
   * @param {string} name - name of the animal
   * @param {boolean} quadruped
   */&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quadruped&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&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;quadruped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quadruped&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * @description returns the name of the animal
   * @returns {string} - name of the animal
   */&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;name&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * @description sets the name of the animal
   * @param {string} name - name of the animal
   */&lt;/span&gt;
  &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&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;We want to extend this basic class with a Cat class, TabNine will learn about the &lt;strong&gt;Animal&lt;/strong&gt; class and suggest the method implementation and comments:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw1ynoolwyzkghopg42uv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw1ynoolwyzkghopg42uv.gif" alt="Comment driven completition with classes" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 2. Function parameters auto completition
&lt;/h3&gt;

&lt;p&gt;Often in Javascript it's hard to complete the function parameters without typings. TabNine is useful in this case because it learns from your code and suggests the method implementation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F381vxrmhnpc3mc1qp81d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F381vxrmhnpc3mc1qp81d.gif" alt="Function parameter auto completition" width="640" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The parameters of methods &lt;strong&gt;sumBy&lt;/strong&gt; and &lt;strong&gt;diffBy&lt;/strong&gt; are displayed automatically by TabNine, so you don't have to check the method implementation directly to check what kind of parameters the methods accepts.&lt;/p&gt;




&lt;h2&gt;
  
  
  TabNine and Typescript
&lt;/h2&gt;

&lt;p&gt;There aren't a lot of differences for TabNine behaviours between JavaScript and TypeScript. TabNine will give you more precise suggestions because of Typings, so will get all the advantages types gives to your code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frfvxt0v8pvqlweufgclp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frfvxt0v8pvqlweufgclp.png" alt="Function parameter completion using TypeScript" width="712" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, I've defined &lt;strong&gt;param1&lt;/strong&gt;, &lt;strong&gt;param2&lt;/strong&gt; and &lt;strong&gt;param3&lt;/strong&gt; in different orders and types compared to the &lt;em&gt;foo&lt;/em&gt; function.&lt;br&gt;
TabNine is recognizing the variable types and suggest to you the correct order.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thanks to:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://codota.com/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=nicolac"&gt;Codota&lt;/a&gt; for letting me writing this article and be part of they're amazing project&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://clideo.com" rel="noopener noreferrer"&gt;clideo.com&lt;/a&gt;, an amazing online tool for video editing (you can also make memes with it 😎)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://onlineconverter.com" rel="noopener noreferrer"&gt;onlineconverter.com&lt;/a&gt;, to convert video to GIF, and much more!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I'm creating an entire web OS as my personal website for 2021</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Mon, 25 May 2020 08:04:52 +0000</pubDate>
      <link>https://dev.to/nicolalc/i-m-creating-an-entire-web-os-as-my-personal-website-for-2021-hc4</link>
      <guid>https://dev.to/nicolalc/i-m-creating-an-entire-web-os-as-my-personal-website-for-2021-hc4</guid>
      <description>&lt;p&gt;Hi to all!&lt;/p&gt;

&lt;p&gt;About every 2 years I go to work to create an updated version of my website. Every time I try to focus on my skills and apply them to the project itself.&lt;/p&gt;

&lt;p&gt;This year I found myself faced with the need to create a single site that would show all my skills in the web and 3D fields.&lt;/p&gt;

&lt;p&gt;Creating a website capable of combining everything is a very difficult undertaking, above all because it could be too large or difficult to understand.&lt;/p&gt;

&lt;p&gt;The solution? Create an entire web operating system, where the applications are personal projects and the images and/or links are related to the projects themselves.&lt;/p&gt;

&lt;p&gt;This solution allows me not only to incorporate many different things in the same site but also to manage its contents in a more immediate and immersive way for the user.&lt;/p&gt;

&lt;p&gt;So NICAOS was born, the first entirely online operating system! Created using Angular 9 with a stateless pattern in mind. All the stiles and assets are created by myself! At the moment it is still in its first steps, and it will never be comparable to a real operating system since it would take years to set it up.&lt;/p&gt;

&lt;p&gt;Give it a look, and if you have any suggestions don't hesitate to share them!&lt;/p&gt;

&lt;p&gt;Take a look here: &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/xOU3ZVLeppI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This is still a WIP obviously, the project will end by December 2020.&lt;/p&gt;

&lt;p&gt;If you have any suggestions, or just want to know how I'm creating this web application, just let me know in the comments! 😎&lt;/p&gt;

&lt;p&gt;Project repo: &lt;a href="https://github.com/NicolaLC/nica-os" rel="noopener noreferrer"&gt;https://github.com/NicolaLC/nica-os&lt;/a&gt;&lt;br&gt;
Live demo: &lt;a href="https://nicolalc.github.io/nicolalc/" rel="noopener noreferrer"&gt;https://nicolalc.github.io/nicolalc/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>angular</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>A cool way to handle scss color variables</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Mon, 27 Apr 2020 13:05:35 +0000</pubDate>
      <link>https://dev.to/nicolalc/a-cool-way-to-handle-scss-color-variables-3njp</link>
      <guid>https://dev.to/nicolalc/a-cool-way-to-handle-scss-color-variables-3njp</guid>
      <description>&lt;p&gt;In my career, I've tried a lot of different ways to handle colours variables in SCSS (or CSS of course).&lt;/p&gt;

&lt;p&gt;Every time I try different approaches to handle them, but finally, I've found a cool way to.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;The issue with different theme colours management was the naming convention. Basically I was using something like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nv"&gt;$background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lawngreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#FFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;...&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$background&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$dark&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/** white on black */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method has some limitations especially while using different themes palettes. Sometimes switching between dark and light themes doesn't mean than the light colour or the background one might be in contrast with the opposite themes, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** LIGHT THEME */&lt;/span&gt;
&lt;span class="nv"&gt;$background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lawngreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#FFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** DARK THEME */&lt;/span&gt;
&lt;span class="nv"&gt;$background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lawngreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#FFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;...&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$background&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$dark&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/** black on black with dark theme */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, you will get unexpected behaviours if you don't set variables and/or CSS properties properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;I've tried a lot of different solutions during my career to handle these issues with theming. The best one I've found so far is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** CONTRAST VARIABLES */&lt;/span&gt;
&lt;span class="err"&gt;$&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;variable-name&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="na"&gt;on-&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;variable-name&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method allows you to define a colour variable and a contrast colour variable for it.&lt;/p&gt;

&lt;p&gt;So if we define two different themes it comes easier to understand and to write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** LIGHT THEME */&lt;/span&gt;
&lt;span class="nv"&gt;$background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$on-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lawngreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$on-primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** DARK THEME */&lt;/span&gt;
&lt;span class="nv"&gt;$background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$on-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;lawngreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$on-primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;...&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$background&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$on-background&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/** black on white with dark theme */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This system lets you define each variable with its contrast colour, which lets you organize better your themes and styles.&lt;/p&gt;

&lt;p&gt;Another cool advantage with this system is the &lt;strong&gt;reverse&lt;/strong&gt; state, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;...&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nt"&gt;pre&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$primary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$on-primary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;.reversed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$on-primary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$primary&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;Easy! That's all!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;This is a cool way to define SCSS (and CSS) variables, I'm using this system in different projects in production and create a new theme is really easy to do.&lt;/p&gt;

&lt;p&gt;What do you think about that? Do you know a better method to handle this case? If yes let me know in the comments section!&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>design</category>
      <category>tips</category>
    </item>
    <item>
      <title>Bootstrap Layout with CSS Grid? It's possible, but with some limitations.</title>
      <dc:creator>Nicola</dc:creator>
      <pubDate>Wed, 19 Feb 2020 17:19:58 +0000</pubDate>
      <link>https://dev.to/nicolalc/bootstrap-layout-with-css-grid-layout-it-s-possible-but-with-some-limitations-49c7</link>
      <guid>https://dev.to/nicolalc/bootstrap-layout-with-css-grid-layout-it-s-possible-but-with-some-limitations-49c7</guid>
      <description>&lt;p&gt;Hello developers!&lt;/p&gt;

&lt;h1&gt;
  
  
  Preface
&lt;/h1&gt;

&lt;p&gt;Bootstrap is an amazing tool, this article isn't indented as a negative idea about Bootstrap. This article does not want to denigrate or diminish the library. It's just an experiment.&lt;/p&gt;

&lt;p&gt;This is a WIP so there might be other limitations I've not found during this experiment.&lt;/p&gt;

&lt;p&gt;Feel free to collaborate 🐱‍👤&lt;/p&gt;




&lt;p&gt;In my freelance career, I've found a lot of projects with Bootstrap library (at least about a 80% of the projects I've seen).&lt;/p&gt;

&lt;p&gt;The reasons behind its use was different between projects, but I've defined 2 common cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"We use Bootstrap because we want to prototype fast a web application/website and we need its responsive behaviours".&lt;/li&gt;
&lt;li&gt;"We use Bootstrap because it helps us with responsive issues, but we don't need its components (only container/row/col classes)".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first case is good because using a big library like Bootstrap could be a big time saver. &lt;/p&gt;

&lt;p&gt;But the second one isn't good in my opinion nowadays, maybe it was 5/6 years ago, but now you don't need to download an entire library to make your applications responsive (thanks to flex and grid layout).&lt;/p&gt;




&lt;p&gt;I'm teaching to my collaborators how to use flex/grid layout to make their applications responsive, without any library and any third-party code.&lt;/p&gt;

&lt;p&gt;If they don't need IE support, I teach them how to use grid layout, and why.&lt;br&gt;
If they need IE support, we make some polyfill or we use flex layout.&lt;/p&gt;

&lt;p&gt;But one day I've found &lt;a href="https://medium.com/wdstack/bootstrap-is-still-better-than-css-grid-for-creating-layouts-522b7baf0411" rel="noopener noreferrer"&gt;this&lt;/a&gt; article, which explains why Bootstrap is still better than grid layout for creating layouts.&lt;/p&gt;

&lt;p&gt;I think this article is right, sometimes using CSS grids could be a waste of time if you don't really know it or you need to create complex layouts, and it could be not so clear to read.&lt;/p&gt;
&lt;h2&gt;
  
  
  So, what now? Turn back to Bootstrap for large projects?
&lt;/h2&gt;

&lt;p&gt;No, of course, I love CSS grids and I think they could help me and my customers to create cool layouts without any library.&lt;/p&gt;

&lt;p&gt;So I've tried to learn deeply Bootstrap and to replicate its layout and responsive behaviours using CSS grid layout.&lt;/p&gt;

&lt;p&gt;Here there is the result:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/NicolaCastellaniDev/embed/YzXqxbz?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Basically I've tried to replicate Bootstrap layout using only grid properties.&lt;/p&gt;

&lt;p&gt;There are some issues (especially with variable width content), but it seems to work pretty good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Equal width multi-line
&lt;/h3&gt;

&lt;p&gt;Isn't possible with CSS grids and auto flows - you need to split the line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aligment
&lt;/h3&gt;

&lt;p&gt;I didn't develop the align-{alignProp} classes, so I don't think they will work.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;What do you think about this experiment? Do you have any advice or just some tips to help me converting Bootstrap using css grids?&lt;/p&gt;

&lt;p&gt;Let me know!&lt;/p&gt;

</description>
      <category>bootstrap</category>
      <category>scss</category>
      <category>experimental</category>
    </item>
  </channel>
</rss>
