<?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: Shane McGowan</title>
    <description>The latest articles on DEV Community by Shane McGowan (@shane).</description>
    <link>https://dev.to/shane</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%2F26663%2F8f24c4c7-858f-4484-8981-9b8b1351f3f8.jpg</url>
      <title>DEV Community: Shane McGowan</title>
      <link>https://dev.to/shane</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shane"/>
    <language>en</language>
    <item>
      <title>Path Aliases in TypeScript (with Vite or Webpack bundlers)</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Sat, 09 Aug 2025 16:30:00 +0000</pubDate>
      <link>https://dev.to/shane/path-aliases-in-typescript-with-vite-or-webpack-bundlers-3nmb</link>
      <guid>https://dev.to/shane/path-aliases-in-typescript-with-vite-or-webpack-bundlers-3nmb</guid>
      <description>&lt;p&gt;A &lt;code&gt;Path Alias&lt;/code&gt; in TypeScript lets us simplify our import paths with an &lt;code&gt;alias&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So rather than doing ugly relative imports like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;User&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;../../model/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can do something like clean like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;User&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;@model/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To set this up, go to your &lt;code&gt;tsconfig.json&lt;/code&gt; and add the following under &lt;code&gt;compilerOptions&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsconfig.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;compiler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;options&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@model/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"./src/model/*"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see this change come into affect in your editor, restart your TypeScript language server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path Aliases with a bundler
&lt;/h2&gt;

&lt;p&gt;If you are using a bundler you will also need to let your bundler know about your new alias. I won't give an example for every bunlder out there but here is how to do it in either &lt;code&gt;Vite&lt;/code&gt; or &lt;code&gt;Webpack&lt;/code&gt;. I am covering those specifically as I currently have active TypeScript based projects using both and don't care to migrate the Webpack one to Vite as Webpack still works fine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vite
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;vite.config.js&lt;/code&gt; add the following (or create a &lt;code&gt;vite.config.js&lt;/code&gt; file in the root of your project (beside your package.json) if you haven't created one yet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vite.config.js&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;defineConfig&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;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&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;path&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="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Webpack
&lt;/h3&gt;

&lt;p&gt;Basically the same as your Vite config above (probably intentionally similar), add the following to your &lt;code&gt;webpack.config.js&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... some other config here&lt;/span&gt;
  &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@model&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/model&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;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// I can't remember if this is needed so remove it if it isn't&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;👋 Checkout more of my stuff at &lt;a href="//shanemcgowan.com"&gt;shanemcgowan.com&lt;/a&gt; or feel free to reach out to me at my email &lt;a href="mailto:hi@shanemcgowan.com"&gt;hi@shanemcgowan.com&lt;/a&gt; 👋&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>vite</category>
    </item>
    <item>
      <title>Configure M1 Mac to use JDK8 with Maven</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Sun, 23 May 2021 00:28:33 +0000</pubDate>
      <link>https://dev.to/shane/configure-m1-mac-to-use-jdk8-with-maven-4b4g</link>
      <guid>https://dev.to/shane/configure-m1-mac-to-use-jdk8-with-maven-4b4g</guid>
      <description>&lt;p&gt;Getting started with the new ARM based M1 Macs can be a bit awkward so here is how you get Maven working with JDK 8.&lt;/p&gt;

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

&lt;p&gt;Homebrew is what we will use to install &lt;code&gt;Maven&lt;/code&gt;. You can instructions on downloading Brew here &lt;a href="https://brew.sh/"&gt;https://brew.sh/&lt;/a&gt; or by simply running this script in your terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Install Maven via Homebrew
&lt;/h1&gt;

&lt;p&gt;Run the following command in your terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install maven
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Install ARM based JDK 8 from Azul
&lt;/h1&gt;

&lt;p&gt;We need to get a version of JDK 8 that works on the ARM based M1 Mac, Azul provide just what we need. At the link below, enter the following if the link doesn't populate it for you.&lt;/p&gt;

&lt;p&gt;Java Version - Java 8 (LTS)&lt;br&gt;
Operating System - macOS&lt;br&gt;
Architecture - ARM 64-bit&lt;br&gt;
Java Package - JDK&lt;/p&gt;

&lt;p&gt;Download the .dmg file here&lt;br&gt;
&lt;a href="https://www.azul.com/downloads/?version=java-8-lts&amp;amp;os=macos&amp;amp;architecture=arm-64-bit&amp;amp;package=jdk"&gt;https://www.azul.com/downloads/?version=java-8-lts&amp;amp;os=macos&amp;amp;architecture=arm-64-bit&amp;amp;package=jdk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install the .dmg file&lt;/p&gt;
&lt;h1&gt;
  
  
  Set JAVA_HOME environment variable
&lt;/h1&gt;

&lt;p&gt;Now you need to set the &lt;code&gt;JAVA_HOME&lt;/code&gt; environment variable to point at our new JDK 8 install. This is the environment variable that Maven looks for.&lt;br&gt;
To add the environment variable, you need to add it to your zsh profile. This can be done by adding the following line to your &lt;code&gt;.zshrc&lt;/code&gt; file.&lt;br&gt;
The &lt;code&gt;.zshrc&lt;/code&gt; file should be located in home directory.&lt;br&gt;
You can navigate to it via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Navigate to directory
cd ~
# Editing the file
vim .zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following line to the file and then save&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now restart your terminal&lt;/p&gt;

&lt;h1&gt;
  
  
  That's it!
&lt;/h1&gt;

&lt;p&gt;When running Maven from your terminal then now it will use JDK8&lt;/p&gt;

</description>
      <category>maven</category>
      <category>jdk8</category>
      <category>m1</category>
      <category>arm</category>
    </item>
    <item>
      <title>YYYY vs yyyy - The day the Java Date Formatter hurt my brain</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Wed, 09 Sep 2020 16:36:13 +0000</pubDate>
      <link>https://dev.to/shane/yyyy-vs-yyyy-the-day-the-java-date-formatter-hurt-my-brain-4527</link>
      <guid>https://dev.to/shane/yyyy-vs-yyyy-the-day-the-java-date-formatter-hurt-my-brain-4527</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;Dates in programming are hard. The ISO-8601 Date standard made them easier but to be entirely honest I'm not ISO-8601 Certified so I'm not very good at my job. What I do know though is the very important difference between &lt;code&gt;YYYY&lt;/code&gt; and &lt;code&gt;yyyy&lt;/code&gt; when formatting dates.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Difference between y and Y
&lt;/h1&gt;

&lt;p&gt;According to the DateTimeFormatter Java Docs (which implements the ISO-8601 specification)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;y (lowercase) is year&lt;/li&gt;
&lt;li&gt;Y (uppercase) is 'week-based-year'.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This difference will cause your code to work perfectly fine, except for when dealing with dates at the very end of some years. &lt;/p&gt;

&lt;p&gt;Here is an example that I had the absolute PLEASURE of dealing with last year. For the date 31/12/2019 (December 31st 2019), &lt;code&gt;yyyy&lt;/code&gt; will output 2019 but &lt;code&gt;YYYY&lt;/code&gt; will output 2020. The reason for this is the week that the 31st of December falls in technically is the first week of 2020. This issue can be a pain to notice and debug.&lt;br&gt;
In my case, 31/12/2019 was being sent from the frontend, being stored correctly in the DB, but was turning into 31/12/2020 when being returned and no one had any idea why. Our default JSON date formatter was the culprit, using &lt;code&gt;YYYY&lt;/code&gt; where it should have been using &lt;code&gt;yyyy&lt;/code&gt; (some clumsily copied and pasted quick solution by myself ofcourse).&lt;/p&gt;

&lt;h1&gt;
  
  
  Example
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Declare formatters
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// y (Lowercase) &lt;/span&gt;
&lt;span class="nc"&gt;DateTimeFormatter&lt;/span&gt; &lt;span class="n"&gt;formatteryyyy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DateTimeFormatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofPattern&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"yyyy-MM-dd"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Y (Uppercase)&lt;/span&gt;
&lt;span class="nc"&gt;DateTimeFormatter&lt;/span&gt; &lt;span class="n"&gt;formatterYYYY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DateTimeFormatter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofPattern&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"YYYY-MM-dd"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When converting from Date to String
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Contains value from Database (December 31st 2019) &lt;/span&gt;
&lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="n"&gt;dateTime&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// String value will be 2019-12-31&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;yyyy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formatteryyyy&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// String value will be 2020-12-31&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;YYYY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formatterYYYY&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When convert from String to Date
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Actual date value will be 2020-12-31&lt;/span&gt;
&lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="n"&gt;parsedDateyyyy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2020-12-31"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;formatteryyyy&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="c1"&gt;// Actual date value will be 2019-12-31&lt;/span&gt;
&lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="n"&gt;parsedDateYYYY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2020-12-31"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;formatterYYYY&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In 99% of use cases, the following is true:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;yyyy good&lt;/li&gt;
&lt;li&gt;YYYY bad&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>json</category>
      <category>iso</category>
      <category>dates</category>
    </item>
    <item>
      <title>How to use different SSH Keys for different Bitbucket (git) Repositories</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Sun, 02 Aug 2020 13:20:26 +0000</pubDate>
      <link>https://dev.to/shane/how-to-use-different-ssh-keys-for-different-bitbucket-git-repositories-4of0</link>
      <guid>https://dev.to/shane/how-to-use-different-ssh-keys-for-different-bitbucket-git-repositories-4of0</guid>
      <description>&lt;p&gt;Bitbucket doesn't allow you to use the same SSH Key on more than one account. This means if you have more than 1 account but need to access the repositories on both (in my case a work account and a personal account) you will need to configure your SSH agent to allow you to choose which SSH Key to use when cloning over SSH.&lt;/p&gt;

&lt;p&gt;Navigate to your SSH Directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure SSH Agent is running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;ssh-agent&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create your SSH Keys&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run the following replacing EMAIL_ADDRESS with the email address associated with your bitbucket account&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"EMAIL_ADDRESS"&lt;/span&gt;

&lt;span class="c"&gt;# When prompted to enter a file name, enter a name to help you differentiate your two keys&lt;/span&gt;
Enter file &lt;span class="k"&gt;in &lt;/span&gt;which to save the key &lt;span class="o"&gt;(&lt;/span&gt;/c/Users/shane/.ssh/id_rsa&lt;span class="o"&gt;)&lt;/span&gt;: key-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(optional) Remove previous SSH Keys for your SSH Agent (this does not delete the actual key from your ~/.ssh directory)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add your newly generated SSH Keys to your SSH Agent&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add ~/.ssh/key-1
ssh-add ~/.ssh/key-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that your SSH Keys have been added&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add &lt;span class="nt"&gt;-l&lt;/span&gt;

&lt;span class="c"&gt;# Sample output&lt;/span&gt;
4096 SHA256:Mo+oiomJASfjlksc6Qj0KcQpUXRVpyvsEIHdXNYDL1c user@website1.com &lt;span class="o"&gt;(&lt;/span&gt;RSA&lt;span class="o"&gt;)&lt;/span&gt;
4096 SHA256:6Jt908009upoASFjjkljsflkj9iaGebl7pNr6vuezPI user@website2.com &lt;span class="o"&gt;(&lt;/span&gt;RSA&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create your SSH Config file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The format of our SSH Config&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Host bitbucket-key-1 &lt;span class="c"&gt;# Friendly name&lt;/span&gt;
  HostName bitbucket.org &lt;span class="c"&gt;# The server we opening the SSH connection with&lt;/span&gt;
  User git &lt;span class="c"&gt;# The SSH user (which for bitbucket is git eg. git@bitbucket.org)&lt;/span&gt;
  IdentityFile ~/.ssh/id_rsa &lt;span class="c"&gt;# The private key file&lt;/span&gt;
  IdentitiesOnly &lt;span class="nb"&gt;yes&lt;/span&gt; &lt;span class="c"&gt;# Tells SSH to only use keys provided by IdentityFile above&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create your different SSH Configs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Bitbucket - SSH Key 1&lt;/span&gt;
Host bitbucket-key-1
  HostName bitbucket.org  
  User git
  IdentityFile ~/.ssh/key-1-id_rsa
  IdentitiesOnly &lt;span class="nb"&gt;yes&lt;/span&gt;

&lt;span class="c"&gt;# Bitbucket - SSH Key 2&lt;/span&gt;
Host bitbucket-key-2
  HostName bitbucket.org
  User git
  IdentityFile ~/.ssh/key-2-id_rsa
  IdentitiesOnly &lt;span class="nb"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Important&lt;/em&gt; At this point, reload your terminal&lt;/p&gt;

&lt;p&gt;Now when cloning via SSH we replace the usual host name (bitbucket.org) with our new "friendly" name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Usual format&lt;/span&gt;
git clone USER@HOST:ACCOUNT_NAME/REPOSITORY_NAME.git
&lt;span class="c"&gt;# Example&lt;/span&gt;
git clone git@bitbucket.org:username/repository.git

&lt;span class="c"&gt;# Format using our new SSH Host config (replace bitbucket.org with the user friendly host name from our .config file)&lt;/span&gt;
git clone git@bitbucket-key-1:username/repository.git

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

&lt;/div&gt;



</description>
      <category>git</category>
      <category>bitbucket</category>
      <category>ssh</category>
      <category>github</category>
    </item>
    <item>
      <title>RxJS Unsubscribe patterns with Angular</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Fri, 03 Jul 2020 17:08:04 +0000</pubDate>
      <link>https://dev.to/shane/rxjs-unsubscribe-patterns-with-angular-5goh</link>
      <guid>https://dev.to/shane/rxjs-unsubscribe-patterns-with-angular-5goh</guid>
      <description>&lt;p&gt;RxJS Observables are classsss (if you know how to use them) but there are quite a few common issues people encounter. If you don't use them correctly you can end up with memory leaks. If you don't use them efficiently you can end up with a lot of unnecessarily verbose code.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to get memory leaks
&lt;/h1&gt;

&lt;p&gt;In RxJS, each time you &lt;code&gt;subscribe&lt;/code&gt; to an &lt;code&gt;Observable&lt;/code&gt; or &lt;code&gt;Subject&lt;/code&gt;, you then need to &lt;code&gt;unsubscribe&lt;/code&gt;. If you don't &lt;code&gt;unsubscribe&lt;/code&gt;, the &lt;code&gt;subscription&lt;/code&gt; will exist in memory and any time the subject emits a value, the logic in the subscription will run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MemoryLeakComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Our subject that we will subscribe to&lt;/span&gt;
  &lt;span class="nx"&gt;subjectA$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&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="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// Create your memory leaks&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&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;When you navigate away from this component and then navigate back, the subscriptions still exist and 4 more subscriptions will be added upon each return to this component. If you had, for example, subscribed to a &lt;code&gt;Subject&lt;/code&gt; from an injected service, the logic in your subscription would run in the background any time a value was emitted from the &lt;code&gt;Subject&lt;/code&gt;, even though the instance of the component it was relating to no longer exists. This can lead to memory leaks and performance issues.&lt;/p&gt;

&lt;p&gt;To avoid this, you need to &lt;code&gt;unsubscribe&lt;/code&gt; which comes with it's own caveats.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to end up with unnecessarily verbose code
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;VerboseSubscriptionComponent&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Our subject that we will subscribe to&lt;/span&gt;
  &lt;span class="nx"&gt;subjectA$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&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="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// The references we will use for our subscriptions;&lt;/span&gt;
  &lt;span class="nl"&gt;subscriptionA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;subscriptionB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;subscriptionC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;subscriptionD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// Create our verbose subscriptions&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;subscriptionA&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&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;subscriptionB&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&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;subscriptionC&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&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;subscriptionD&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ngOnDestroy&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// Manually unsubscribe from each subscription&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;subscriptionA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unsubscribe&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;subscriptionB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unsubscribe&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;subscriptionC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unsubscribe&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;subscriptionD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solves the memory leak issue but leaves room for error and is very verbose if we have a large amount of subscriptions. If at any point one of our &lt;code&gt;subscripton&lt;/code&gt; variables is unsubscribed from or if it is never actually assigned to, when &lt;code&gt;unsubscribe()&lt;/code&gt; is called in &lt;code&gt;ngOnDestroy()&lt;/code&gt; it will error and break our app.&lt;/p&gt;

&lt;p&gt;Below are some solutions that completely avoid this issue.&lt;/p&gt;

&lt;h1&gt;
  
  
  A solution involving (wo)man's best friend; LOOPS!
&lt;/h1&gt;

&lt;p&gt;We can create an &lt;code&gt;Array&amp;lt;Subscription&amp;gt;&lt;/code&gt; to store all our subscriptions. Then we itterate over the array in the &lt;code&gt;ngOnDestroy()&lt;/code&gt; method. With this solution, our code is much less verbose, we don't need to worry about keeping track of individual subscriptions and which one has or hasn't been unsubscribed from.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;LoopSubscriptionComponent&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Our subject that we will subscribe to&lt;/span&gt;
  &lt;span class="nx"&gt;subjectA$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&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="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// An array to hold our subscriptions&lt;/span&gt;
  &lt;span class="nl"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Subscription&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="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Subscription&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;constructor&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// Add our subscription to&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;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&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;subjectA$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&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;ngOnDestroy&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// We loop our subscriptions array and unsubscribe&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;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unsubcribe&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 is the solution I used to use when I thought I was really smart and cool. I have since been humbled and use the below, superior, solution.&lt;/p&gt;

&lt;h1&gt;
  
  
  A better solution involving the &lt;code&gt;takeUntil()&lt;/code&gt; pipeable operator
&lt;/h1&gt;

&lt;p&gt;Using the &lt;code&gt;takeUntil()&lt;/code&gt; pipeable operator, we no longer need to call &lt;code&gt;unsubscribe()&lt;/code&gt; on each individual subscription. This operator takes an observable as a paramater, and when a value is emitted from that observable, it will gracefully close the subscription is is applied to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TakeUntilComponent&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Our magical observable that will be passed to takeUntil()&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;ngUnsubscribe$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Our subject that we will subscribe to&lt;/span&gt;
  &lt;span class="nx"&gt;subjectA$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&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="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subjectA$&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;takeUntil&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;ngUnsubscribe$&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;// logic goes here ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ngOnDestroy&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// Emit a value so that takeUntil will handle the closing of our subscriptions;&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;ngUnsubscribe$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Unsubscribe from our unsubscriber to avoid creating a memory leak&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;ngUnsubscribe$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unsubscribe&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;h1&gt;
  
  
  Outro
&lt;/h1&gt;

&lt;p&gt;Hopefully you learned something new here! I am by no means an expert but I write this hoping you can skip the first 3 itterations of learning and jump straight into the best pattern to work with (best being my opinion ofcourse).&lt;/p&gt;

&lt;p&gt;If you know of a better pattern or solution, or if there are any issues with what I have written above, please let me know!&lt;/p&gt;

&lt;p&gt;And most importantly, have a nice day ♥&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Working with Enums in Angular components</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Tue, 28 Apr 2020 23:47:34 +0000</pubDate>
      <link>https://dev.to/shane/working-with-enums-in-angular-html-templates-2io9</link>
      <guid>https://dev.to/shane/working-with-enums-in-angular-html-templates-2io9</guid>
      <description>&lt;p&gt;This is a short guide on using Enums in an Angular application.&lt;br&gt;
Below you will see how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reference an Enum in your &lt;code&gt;component.html&lt;/code&gt; templates &lt;/li&gt;
&lt;li&gt;Itterate over an enum using &lt;code&gt;*ngFor&lt;/code&gt; and the &lt;code&gt;keyvalue&lt;/code&gt; pipe&lt;/li&gt;
&lt;li&gt;Conditionally show content using an Enum and &lt;code&gt;*ngIf&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Get all the values of an enum as an &lt;code&gt;Array&amp;lt;sting&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;You can skip the next block of text if you just want to get the actual details (I respect that)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I love using Enums in TypeScript as I am a terrible developer with a terrible memory and let my editor's auto complete do 80% of my job. Enums let you avoid using strings and having to remember what string values you used. They also allow you to lock down the values a property can be, so that a user can't just submit any value they want. So if you aren't using them, start using them, and if you are already using them, use them more, use them to a fault. Be the Enums you want to see in the world.&lt;/p&gt;
&lt;h1&gt;
  
  
  Example use of an enum for those unfamiliar
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is our PropertyType enum&lt;/span&gt;
&lt;span class="c1"&gt;// We give each value a string value otherwise PropertyType.House would return 0, Property.Apartment would return 1, and so on&lt;/span&gt;
&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;PropertyType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;House&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;House&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Apartment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Apartment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Flat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Studio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Studio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Our class which has a 'type' property.&lt;/span&gt;
&lt;span class="c1"&gt;// We want to lock type down to a set of predefined values&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Property&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;monthlyPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropertyType&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="c1"&gt;// Creates a property successfully&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PropertyType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Apartment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Will display an error from our linter and in the Angular CLI&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PropertyType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RANDOM_VALUE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;Enums can be used in your Angular templates. This is handy for situations like avoiding a hard coded set of values for a dropdown menu or displaying different content based on your component state. In my opinion, this pairs very nicely with reactive forms.&lt;br&gt;
To make an Enum accessible in your Angular template you need to first store it in a variable in our component.ts file. For this example, we will create a simple reactive form to create a &lt;code&gt;Property&lt;/code&gt;&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="c1"&gt;// Declaring our Enum. The Enum could also be imported from another file if needed &lt;/span&gt;
&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;PropertyType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;House&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;House&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Apartment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Apartment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Flat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Studio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Studio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-property-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./property.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;PropertyComponent&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Make a variable reference to our Enum&lt;/span&gt;
  &lt;span class="nx"&gt;ePropertyType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PropertyType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Build our form&lt;/span&gt;
  &lt;span class="nl"&gt;form&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This is only here to make the form look more l3g1t&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;formBuilder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormBuilder&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;form&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;formBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
      &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&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;type&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;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;FormControl&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;price&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;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;FormControl&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;Then in our &lt;code&gt;property.html&lt;/code&gt; template, we can utilize our Enum as follows. We will use the &lt;code&gt;keyvalue&lt;/code&gt; pipe. This takes our &lt;code&gt;PropertyType&lt;/code&gt; enum (referenced as &lt;code&gt;ePropertyType&lt;/code&gt;) and turns it into a &lt;code&gt;KeyValue&lt;/code&gt; array, which we can iterate over with &lt;code&gt;*ngFor&lt;/code&gt;. As we declared our &lt;code&gt;PropertyType&lt;/code&gt; with a string value (ie. &lt;code&gt;Apartment = 'Apartment'&lt;/code&gt;) the &lt;code&gt;KeyValue.key&lt;/code&gt; and &lt;code&gt;KeyValue.value&lt;/code&gt; will both contain the string value of the enum so we can use either.&lt;/p&gt;

&lt;p&gt;We then can use our Enum as part of an &lt;code&gt;*ngIf&lt;/code&gt; to conditionally display a message.&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;form&lt;/span&gt; &lt;span class="na"&gt;[formGroup]=&lt;/span&gt;&lt;span class="s"&gt;"form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Property type form control --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"propertyType"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Property Type&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"propertyType"&lt;/span&gt; &lt;span class="na"&gt;[formControl]=&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;[ngValue]=&lt;/span&gt;&lt;span class="s"&gt;"null"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Select one...&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let type of ePropertyType | keyvalue"&lt;/span&gt; &lt;span class="na"&gt;[ngValue]=&lt;/span&gt;&lt;span class="s"&gt;"type.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{type.value}}&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- Property price form control --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"propertyPrice"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Property Price&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"propertyPrice"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;[formControl]=&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Street..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Conditionally display a message if a certain PropertyType is selected (or not selected) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ng-container&lt;/span&gt; &lt;span class="na"&gt;*ngIf=&lt;/span&gt;&lt;span class="s"&gt;"type.value !== ePropertyType.House"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
Wouldn't you prefer a nice garden?
&lt;span class="nt"&gt;&amp;lt;/ng-container&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  How to get an array of strings from an Enum
&lt;/h1&gt;

&lt;p&gt;A nice little trick to get an array of strings &lt;em&gt;(&lt;code&gt;string[]&lt;/code&gt;, or &lt;code&gt;Array&amp;lt;string&amp;gt;&lt;/code&gt; if you're a cool boi like myself)&lt;/em&gt; from an Enum is to use use &lt;code&gt;Object.keys&lt;/code&gt; and &lt;code&gt;Array.filter&lt;/code&gt;&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="c1"&gt;// Declare your enum&lt;/span&gt;
&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;PropertyType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;House&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;House&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Apartment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Apartment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Flat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Studio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Studio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Get an array of keys, filtering out number values
*  as the enum object itself is as follows
*  { 0: 'House', 1: 'Apartment' ...}
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;propertyType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PropertyType&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Enums are lit, use them more often. &lt;/p&gt;

</description>
      <category>angular</category>
      <category>enums</category>
      <category>typescript</category>
      <category>angular9</category>
    </item>
    <item>
      <title>Angular - How to pass arrays via Query Parameters</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Mon, 13 Apr 2020 15:36:52 +0000</pubDate>
      <link>https://dev.to/shane/angular-9-how-to-pass-arrays-via-query-parameters-23ai</link>
      <guid>https://dev.to/shane/angular-9-how-to-pass-arrays-via-query-parameters-23ai</guid>
      <description>&lt;p&gt;This is a quick guide on how to pass an array of values via query string in Angular. This is working in Angular 9+ as of 13/04/2020 but will most likely work just fine for any version from Angular 2+.&lt;/p&gt;

&lt;p&gt;In the example below we will create an array of values in &lt;code&gt;ComponentA&lt;/code&gt; and pass them to &lt;code&gt;ComponentB&lt;/code&gt; via navigation. This method will work for a direct navigation to &lt;code&gt;ComponentB&lt;/code&gt; via a link and also via programmatic navigation with the Angular router.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The short version is: &lt;code&gt;JSON.stringify&lt;/code&gt; your array and pass it as query param, thend &lt;code&gt;JSON.parse&lt;/code&gt; it back into an array after navigation&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Component A - Passing the array
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ComponentA&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// We need access to the Angular router object to navigate programatically&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;){}&lt;/span&gt;

  &lt;span class="nx"&gt;navigateWithArray&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create our query parameters object&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="c1"&gt;// Create our array of values we want to pass as a query parameter&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arrayOfValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Add the array of values to the query parameter as a JSON string&lt;/span&gt;
    &lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayOfVAlues&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create our 'NaviationExtras' object which is expected by the Angular Router&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;navigationExtras&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NavigationExtras&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;queryParams&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Navigate to component B&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;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/componentB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;navigationExtras&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;h4&gt;
  
  
  Component B - parsing the array
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ComponentB&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Where we will be storing the values we get from the query string&lt;/span&gt;
  &lt;span class="nl"&gt;arrayOfValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&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;// We need use the ActivatedRoute object to get access &lt;/span&gt;
  &lt;span class="c1"&gt;// to information about the current route&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;activatedRoute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActivatedRoute&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the query string value from our route&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myArray&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;activatedRoute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryParamMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myArray&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// If the value is null, create a new array and store it&lt;/span&gt;
    &lt;span class="c1"&gt;// Else parse the JSON string we sent into an array&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;myArray&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="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;arrayOfValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arrayOfValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myArray&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;h4&gt;
  
  
  Enjoy
&lt;/h4&gt;

</description>
      <category>angular</category>
      <category>angular11</category>
      <category>queryparam</category>
      <category>queryparameters</category>
    </item>
    <item>
      <title>Using Postman with Java Spring and CSRF Tokens</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Tue, 07 Apr 2020 16:40:42 +0000</pubDate>
      <link>https://dev.to/shane/using-postman-with-java-spring-and-csrf-tokens-di0</link>
      <guid>https://dev.to/shane/using-postman-with-java-spring-and-csrf-tokens-di0</guid>
      <description>&lt;p&gt;Java Spring will return a &lt;code&gt;403 Forbidden&lt;/code&gt; if any request besides a &lt;code&gt;GET&lt;/code&gt; request is missing a Cross Site Request Forgery Token (CSRF Token) in the &lt;code&gt;X-XSRF-TOKEN&lt;/code&gt; Header. Here is how to fix that issue when using Postman. I have seen people online suggest that you disable CSRF Tokens but please don't do that. That is silly. Those people are sily. &lt;/p&gt;

&lt;h1&gt;
  
  
  Creating an environment
&lt;/h1&gt;

&lt;p&gt;We need to create an environment in which to store our &lt;code&gt;CSRF Token&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the top right of Postman, click the cog.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dRAfmQTy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/frzzfll8gvrz960inwuk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dRAfmQTy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/frzzfll8gvrz960inwuk.png" alt="Alt Text" width="361" height="106"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Pop Up window, Click &lt;code&gt;Add&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JZuPzZew--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/3uj3nmamli2hl9d9w7me.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JZuPzZew--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/3uj3nmamli2hl9d9w7me.png" alt="Alt Text" width="728" height="727"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter an appropriate &lt;code&gt;Environment Name&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter &lt;code&gt;xsrf-token&lt;/code&gt; in the first column.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;code&gt;Add&lt;/code&gt; in the bottom right corner&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--14xoRSHY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/57yyelhwtqqsk4pmhi9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--14xoRSHY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/57yyelhwtqqsk4pmhi9c.png" alt="Alt Text" width="730" height="730"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure your environment is selected in the drop-down in the top right.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Getting the CSRF Token
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;GET&lt;/code&gt; requests do not require a CSRF Token to be allowed through our &lt;code&gt;SpringSecurityConfig&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a &lt;code&gt;GET&lt;/code&gt; request&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;code&gt;Tests&lt;/code&gt; tab&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;pm.environment.set("xsrf-token", decodeURIComponent(pm.cookies.get("XSRF-TOKEN")));&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ANi-Dyiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/zhxk5toyzly5o8pp3jsn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ANi-Dyiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/zhxk5toyzly5o8pp3jsn.png" alt="Alt Text" width="649" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now when you call this endpoint in Postman, your CSRF Token will be stored in your environment variables.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using the CSRF Token
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Go to your request that requires the CSRF Token&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;code&gt;Headers&lt;/code&gt; tab&lt;/li&gt;
&lt;li&gt;Enter a key of &lt;code&gt;X-XSRF-TOKEN&lt;/code&gt; and a value of &lt;code&gt;{{xsrf-token}}&lt;/code&gt;, the &lt;code&gt;{{xsrf-token}}&lt;/code&gt; value will be populated from our Environment we created earlier. 
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cVVrCc4o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/tsyur8aa0q0sek13xepi.png" alt="Alt Text" width="613" height="241"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your request should now be from from CSRF errors&lt;/p&gt;

&lt;h1&gt;
  
  
  Things to watch out for
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Be sure you have actually selected an Environment. I have forgotten to do this several times.&lt;/li&gt;
&lt;li&gt;Be sure to call the &lt;code&gt;GET&lt;/code&gt; request again to populate the value in case it has become invalid or has expired.&lt;/li&gt;
&lt;li&gt;Have a nice day&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>springboot</category>
      <category>postman</category>
      <category>csrf</category>
      <category>xsrf</category>
    </item>
    <item>
      <title>How to create an AWS S3 hosted Angular App with a Custom Domain, HTTPS and Continuous Deployment</title>
      <dc:creator>Shane McGowan</dc:creator>
      <pubDate>Mon, 16 Dec 2019 01:54:49 +0000</pubDate>
      <link>https://dev.to/shane/how-to-create-an-aws-s3-hosted-angular-app-with-a-custom-domain-https-and-continuous-deployment-2i3i</link>
      <guid>https://dev.to/shane/how-to-create-an-aws-s3-hosted-angular-app-with-a-custom-domain-https-and-continuous-deployment-2i3i</guid>
      <description>&lt;p&gt;A guide on how to host an Angular app in AWS S3 with a custom domain, HTTPS and continuous deployment from a GitHub repo. (accurate as of 16th of December 2019 &lt;em&gt;common era&lt;/em&gt;)&lt;/p&gt;

&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub Account&lt;/li&gt;
&lt;li&gt;A GitHub Repo containing an Angular App created in the root directory&lt;/li&gt;
&lt;li&gt;An AWS Account&lt;/li&gt;
&lt;li&gt;A domain name with the ability to update it's DNS settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Basic Static Site Setup
&lt;/h1&gt;

&lt;h4&gt;
  
  
  S3
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a bucket with site name (example.com)&lt;/li&gt;
&lt;li&gt;Go to the &lt;code&gt;'Properties'&lt;/code&gt; tab&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;'Static Website'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;'Use this bucket to host a website'&lt;/code&gt; and enter index.html for both Index document and Error document (for single page app)&lt;/li&gt;
&lt;li&gt;Manually add an index.html file to the bucket for testing purposes&lt;/li&gt;
&lt;li&gt;Make note of the Endpoint, we will be needing this later when setting up our CDN.&lt;/li&gt;
&lt;li&gt;Go to the &lt;code&gt;'Permissions'&lt;/code&gt; tab&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;'Bucket Policy'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy the following json replacing &lt;code&gt;BUCKET_NAME&lt;/code&gt; with the name of the bucket (example.com).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Statement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AllowPublicRead&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Effect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Principal&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AWS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Action&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s3:GetObject&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Resource&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arn:aws:s3:::BUCKET_NAME/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: The policy found in bucket-policy.json will cause all objects in this bucket to be &lt;strong&gt;publicly available by default&lt;/strong&gt;, this is required later by our deployment script as normally objects are made private by default. If you do not do this, your site will not be accessible.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create bucket with site name and subdomain (&lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Go to &lt;code&gt;'Properties'&lt;/code&gt; tab&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;'Static Website'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;'Redirect requests'&lt;/code&gt; and choose &lt;code&gt;'http'&lt;/code&gt; for the protocol&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Custom Domain and HTTPS
&lt;/h1&gt;

&lt;h4&gt;
  
  
  Route 53 and DNS
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;code&gt;'Create Hosted Zone'&lt;/code&gt; and enter your domain example.com with type &lt;code&gt;'Public Hosted Zone'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Go to the Domain Registrar where you got your domain (eg hover.com)&lt;/li&gt;
&lt;li&gt;Copy the &lt;code&gt;ns&lt;/code&gt; values from your newly created hosted zone to nameserver settings for your domain  
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  AWS Certificate Manager (SSL Certs)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the &lt;code&gt;us-east-1&lt;/code&gt; region is selected as Cloud Front needs this (top right of dashboard). More info on this here &lt;a href="https://aws.amazon.com/certificate-manager/faqs/"&gt;https://aws.amazon.com/certificate-manager/faqs/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add your domain example.com and your domain with the &lt;code&gt;'www'&lt;/code&gt; subdomain &lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt; then click &lt;code&gt;'Next'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;'DNS Validation'&lt;/code&gt; then click &lt;code&gt;'Next'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;'Review'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;'Confirm and Request'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expand the area for each domain and click &lt;code&gt;'Create record in route53'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;'Continue'&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  AWS Cloud Front (CDN)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;code&gt;'Create Distribution'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;'Web'&lt;/code&gt; click &lt;code&gt;'Get Started'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;'Origin Domain Name'&lt;/code&gt; enter the S3 Site Endpoint you made a note of earlier. It should be in the format &lt;strong&gt;bucket.name&lt;/strong&gt;.s3-website-&lt;strong&gt;aws-region&lt;/strong&gt;.amazonaws.com&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;'Viewer Protocol Policy'&lt;/code&gt;, select &lt;code&gt;'redirect http to https'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;'Price class'&lt;/code&gt; select &lt;code&gt;'use only US, Canada and Europe'&lt;/code&gt;. Users outside these regions will experience more latency but this is cheaper&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;'Alternate Domain Names (CNAMEs)'&lt;/code&gt; enter your apex domain (example.com) and then on a new line enter your domain with the &lt;code&gt;'www'&lt;/code&gt; subdomain (&lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;'SSL Certificate'&lt;/code&gt; select &lt;code&gt;'Custom SSL Certificate'&lt;/code&gt; and choose the Certificate we just created in AWS Certificate Manager&lt;/li&gt;
&lt;li&gt;Under &lt;code&gt;'Default Root Object'&lt;/code&gt; enter &lt;code&gt;'index.html'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;'Create Distribuion'&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: It will take 15 to 20 minutes to create your distribution, be patient and wait before moving on to the next step.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: Your first 1,000 invalidation path requests each month are free, but invalidations after this will cost $0.005 per additonal path invalidated.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: You can have a max of 3,000 path invalidation requests in progress at once. A wildcard '*' request can invalidate a max of 15 paths at once so if your app contains more than 15 files, you will need to remove each path manually in your deployment script, not using the wild card path.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Back to Route 53
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;code&gt;'Hosted Zones'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click your domain example.com&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;'Create Record Set'&lt;/code&gt; and leave name blank
Set &lt;code&gt;'Alias'&lt;/code&gt; to &lt;code&gt;'Yes'&lt;/code&gt;
Select &lt;code&gt;'Alias Target'&lt;/code&gt; and select the Cloud Front deployment that we created earlier from the dropdown
Click Create&lt;/li&gt;
&lt;li&gt;Repeat as above but enter &lt;code&gt;'www'&lt;/code&gt; as the name this time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: This may take several minutes to propogate, I have experienced site without www subdomain working before site with www subdomain. Eventually the www subdomain will work also so be patient.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your site should now be live under &lt;a href="https://example.com"&gt;https://example.com&lt;/a&gt; and &lt;a href="https://www.example.com"&gt;https://www.example.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Continuous Delivery
&lt;/h1&gt;

&lt;h4&gt;
  
  
  AWS Code Pipeline
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to AWS Code Pipeline&lt;/li&gt;
&lt;li&gt;Enter a name for your pipeline&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;'New service role'&lt;/code&gt;, the default name is fine&lt;/li&gt;
&lt;li&gt;Ensure &lt;code&gt;'Allow AWS CodePipeline to create a service role so it can be used with this new pipeline'&lt;/code&gt; is checked&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;code&gt;'Next'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;'Source provider'&lt;/code&gt; dropdown, select &lt;code&gt;'GitHub'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;code&gt;'Connect To GitHub'&lt;/code&gt; and allow AWS access to your GitHub account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;'Repository'&lt;/code&gt; dropdown, select your repo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;'Branch'&lt;/code&gt; dropdown, select your desired branch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Change detection options'&lt;/code&gt; ensure &lt;code&gt;'GitHub webhooks'&lt;/code&gt; is selected&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;code&gt;'Next'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;'Build provider'&lt;/code&gt; dropdown, select &lt;code&gt;'AWS CodeBuild'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the &lt;code&gt;'Region'&lt;/code&gt; dropdown, select your desired AWS region&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Project name'&lt;/code&gt;, click &lt;code&gt;'Create project'&lt;/code&gt;. This will bring you to a popup window.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Popup Window, under &lt;code&gt;'Project Name'&lt;/code&gt; enter a desired name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Environment image'&lt;/code&gt; select &lt;code&gt;'Managed image'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Operating System'&lt;/code&gt; select &lt;code&gt;'Ubuntu'&lt;/code&gt;. This includes the language runtimes we need for building our Angular App&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Runtimes'&lt;/code&gt; select &lt;code&gt;'Standard'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Image'&lt;/code&gt; select &lt;code&gt;'aws/codebuild/standard:3.0'&lt;/code&gt;. This contains NodeJS version 12 which we want.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Image version'&lt;/code&gt; select &lt;code&gt;'Always use the latest image for this runtime version'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Environment Type'&lt;/code&gt; select &lt;code&gt;'Linux'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Service role'&lt;/code&gt; select &lt;code&gt;'New Service Role'&lt;/code&gt; and enter an appropriate name (for example 'codebuild-service-role-s3-angular')&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;code&gt;'Build specifications'&lt;/code&gt; select &lt;code&gt;'User a buildspec file'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;code&gt;'Continue to CodePipeline'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should be brought back to CodePipeline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;code&gt;'Next'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;code&gt;'Skip deploy stage'&lt;/code&gt; as we covered this in our build pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;code&gt;'Create pipeline'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  AWS CodeBuild
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a &lt;code&gt;buildspec.yaml&lt;/code&gt; file in the root of your repo. This will be used during the CodeBuild part of our CD pipeline to build your angular app and copy it to the root of the S3 bucket.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Copy the following to the &lt;code&gt;buildspec.yaml&lt;/code&gt; file.&lt;br&gt;
Replace &lt;code&gt;@SITE_NAME&lt;/code&gt; with your site name (example.com).&lt;br&gt;
Replace &lt;code&gt;@ANGULAR_APP_NAME&lt;/code&gt; with the name of the folder which contains your angular app after running ng build which can be found inside the &lt;code&gt;dist&lt;/code&gt; folder for default angular apps&lt;br&gt;
Replace &lt;code&gt;@ANGULAR_APP_ENVIRONMENT&lt;/code&gt; with the build environment for your angular app, &lt;code&gt;prod&lt;/code&gt; being the default value&lt;br&gt;
Replace &lt;code&gt;@CLOUDFRONT_DISTRIBUTION_ID&lt;/code&gt; with the ID of the cloudfront distrubtion you created earlier. This can be found in your Cloudfront Dashboard.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;S3_BUCKET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@SITE_NAME"&lt;/span&gt;
    &lt;span class="na"&gt;APP_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@ANGULAR_APP_NAME"&lt;/span&gt;
    &lt;span class="na"&gt;BUILD_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@ANGULAR_APP_ENVIRONMENT"&lt;/span&gt;
    &lt;span class="na"&gt;CDN_DISTRIBUTION_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@CLOUDFRONT_DISTRIBUTION_ID"&lt;/span&gt;

&lt;span class="na"&gt;phases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runtime-versions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# NodeJS included in the docker image&lt;/span&gt;
      &lt;span class="na"&gt;nodejs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Install node dependancies.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Builds Angular application.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node ./node_modules/@angular/cli/bin/ng build --$BUILD_ENV&lt;/span&gt;

  &lt;span class="na"&gt;post_build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Clear S3 bucket.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;aws s3 rm s3://$S3_BUCKET --recursive&lt;/span&gt;
      &lt;span class="c1"&gt;# Copy files from dist to S3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd dist&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;aws s3 cp $APP_NAME s3://$S3_BUCKET --recursive&lt;/span&gt;
      &lt;span class="c1"&gt;# Begin cloudfront invalidation&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;aws cloudfront create-invalidation --distribution-id $CDN_DISTRIBUTION_ID --paths "/*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  CodePipeline IAM Role Permissions
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;An IAM Role will have been created for both Code Pipeline and CodeBuild. You need to give the CodeBuild role the permission to access S3 and Cloudfront&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the IAM Dashboard&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;'Roles'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In the table, click on the role that was created during the CodeBuild in the previous step.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;'Attach Policy'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;'S3'&lt;/code&gt; into the search bar and click the checkbox beside &lt;code&gt;'AmazonS3FullAccess'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;'CloudFront'&lt;/code&gt; into the search bar and click the checkbox beside &lt;code&gt;'CloudFrontFullAccess'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;'Attach Policy'&lt;/code&gt; to add the policy to this role.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The End
&lt;/h1&gt;

&lt;p&gt;You did it, good work friend ❤️&lt;/p&gt;

</description>
      <category>aws</category>
      <category>angular</category>
      <category>github</category>
      <category>https</category>
    </item>
  </channel>
</rss>
