<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Coding Latte</title><link>https://codinglatte.com/</link><description>Latest Lessons at Coding Latte</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Mon, 20 Jan 2020 12:33:24 +0300</lastBuildDate><atom:link href="https://codinglatte.com/index.xml" rel="self" type="application/rss+xml"/><item><title>How to Integrate Smart Tables With Angular</title><link>https://codinglatte.com/posts/angular/how-to-integrate-smart-tables-with-angular/</link><pubDate>Mon, 20 Jan 2020 12:33:24 +0300</pubDate><author>Shira Gray</author><guid>https://codinglatte.com/posts/angular/how-to-integrate-smart-tables-with-angular/</guid><description>&lt;p>&lt;em>The following post surely catches a bit surface of the major revamp which has been promised by AngularJS since its inception. With such technologies growing, the best is always yet to come! A lot seems to have changed under the hood in regards to tooling. For example, it offers seamless upgrading and adding new libraries to your developed apps.&lt;/em>&lt;/p>
&lt;p>Without wasting further time I would straight jump to the crux of the post; i.e. how to integrate and use ng2-smart-tables with Angular . But before that do you know what is ng2-smart-table? Of course, it’s a library featuring npm package and pre-defined components and directives mainly used for sorting, searching, filtering and displaying things exactly in the form of a table. So to begin with,&lt;/p>
&lt;h3 id="prerequisites">Prerequisites&lt;/h3>
&lt;ul>
&lt;li>Install and Setup Angular on your Workspace - &lt;a href="https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/">Link&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Time to generate new project!&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng new smart-table-example
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Before coming to any conclusion it is advisable to check whether everything is in sync or not. Run ng serve –open or you can also visit the URL &lt;a href="http://localhost:4200/">localhost:4200&lt;/a>.&lt;/p>
&lt;h3 id="smart-tables-with-angular">Smart tables with Angular&lt;/h3>
&lt;h4 id="install-rxjs--compat">Install rxjs- compat&lt;/h4>
&lt;p>One of the major cons faced when dealing with the Angular ecosystem is the compatibility issue. Many third party libraries are found incompatible whenever a new Angular version is released. And the same goes for Angular moreover depending on TypeScript 2.7 and RxJS version . Another reason for third party libraries not being compatible is they haven’t been updated. So in order to make things work with the latest version, it is advisable to use another third-party library in our app, called rxjs-compat.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm i rxjs-compat --save
&lt;/code>&lt;/pre>&lt;/div>&lt;p>One additional Tip for you: In future you might find third party libraries which might or might not be compatible. For that rxjs-compat. is certainly not required. Being an AngularJS developer, you should check the documentation of the third-party library before integrating it with Angular.&lt;/p>
&lt;h3 id="installing-the-ng2-smart-table-library">Installing the ng2-smart-table library&lt;/h3>
&lt;p>Install it as a local dependency on the Angular project.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install –save
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the dictionary of Angular Application development, you will certainly find a global space to register a module called &lt;code>app.module.ts&lt;/code>. All you require doing is open it and add the following:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">BrowserModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/platform-browser&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Ng2SmartTableModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;ng2-smart-table&amp;#39;&lt;/span>; &lt;span style="color:#75715e">// add
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AppComponent&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app.component&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">Ng2SmartTableModule&lt;/span> &lt;span style="color:#75715e">// add
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If no errors found here at this step; it surely means the Webpack has been succeeded in compiling with the app. Which also means it’s time to move forward.&lt;/p>
&lt;h3 id="table-creation">Table Creation&lt;/h3>
&lt;p>Time to generate a component and name it table as it is created using the ng g c table code. The ng command won’t just create a default component but also updates &lt;code>app.module.ts&lt;/code> at regular intervals. The new generated component will be found on inside src/app/. Check the code below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Component&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">// add the following
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">TableComponent&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./table/table.component&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@Component&lt;/span>({
&lt;span style="color:#a6e22e">selector&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;app-root&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">templateUrl&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app.component.html&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">styleUrls&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;./app.component.css&amp;#39;&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppComponent&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;smart-table-example&amp;#39;&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="back-to-the-backend">Back to the Backend&lt;/h3>
&lt;p>Here we are going to create a mock backend server, where installing json-server becomes easy from npm. This will also serve data as an API to the developed AngularJs Application.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install -g json-server
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Also, create a directory called data and a new file named db.json. Try adding some mock data in JSON format. It will be easier to render.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">{ &lt;span style="color:#e6db74">&amp;#34;employees&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [{
&lt;span style="color:#e6db74">&amp;#34;id&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Jason Bourne&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;employeeId&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;us2323&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;city&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;New York&amp;#34;&lt;/span>
},
{
&lt;span style="color:#e6db74">&amp;#34;id&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Mary&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;employeeId&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;us6432&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;city&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;San Jose&amp;#34;&lt;/span>
},
{
&lt;span style="color:#e6db74">&amp;#34;id&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Sameer&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;employeeId&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;in2134&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;city&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Mumbai&amp;#34;&lt;/span>
},
{
&lt;span style="color:#e6db74">&amp;#34;id&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Sam Hiddlestone&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;employeeId&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;au9090&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;city&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Melbourne&amp;#34;&lt;/span>
}]
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As soon as you are done! A successful message will be prompted.&lt;/p>
&lt;h3 id="instead-of-creating-make-the-table-smart">Instead of creating make the Table Smart&lt;/h3>
&lt;p>Now we have reached the point where the table is rendering as a static. In simple words, it cannot do any kind of sorting or searching as it does not have any feature or functionality. Making things more dynamic is what we aim here. We need to add some configuration.&lt;/p>
&lt;p>Create an object inside &lt;code>table.component.ts&lt;/code> and call it settings. This object contains columns that are displayed on the table.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Component&lt;/span>, &lt;span style="color:#a6e22e">OnInit&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">TableService&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./table.service&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Table&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./Table&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@Component&lt;/span>({
&lt;span style="color:#a6e22e">selector&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;app-table&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">templateUrl&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./table.component.html&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">styles&lt;/span>&lt;span style="color:#f92672">:&lt;/span> []
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">TableComponent&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">OnInit&lt;/span> {
&lt;span style="color:#a6e22e">employees&lt;/span>: &lt;span style="color:#66d9ef">Table&lt;/span>[];
&lt;span style="color:#75715e">// add this config
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">settings&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">columns&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">id&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;ID&amp;#39;&lt;/span>
},
&lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Name&amp;#39;&lt;/span>
},
&lt;span style="color:#a6e22e">city&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;City&amp;#39;&lt;/span>
},
&lt;span style="color:#a6e22e">employeeId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Employee No.&amp;#39;&lt;/span>
}
}
};
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">tservice&lt;/span>: &lt;span style="color:#66d9ef">TableService&lt;/span>) {}
&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">tservice&lt;/span>.&lt;span style="color:#a6e22e">getData&lt;/span>().&lt;span style="color:#a6e22e">subscribe&lt;/span>((&lt;span style="color:#a6e22e">data&lt;/span>: &lt;span style="color:#66d9ef">Table&lt;/span>[]) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">employees&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>;
});
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Featuring all the fields coming from our service, it is certainly not necessary to have the column name identical with the original key. One can add or modify the name for a column using the title. In addition to this, what else do we require is source which gives reference to the actual data from our service to the ng2-smart-table directive. Finally, we have reached the last piece of puzzle by which we can create a dynamic table.&lt;/p>
&lt;p>&lt;strong>Lastly,&lt;/strong>&lt;/p>
&lt;p>As an AngularJS developer, I would suggest you to try and play with it and explore as much functionalities as you can. Try noticing how it automatically add by default various functionalities to edit and update or delete a field as well add a search bar over every column.&lt;/p>
&lt;h3 id="author-bio">Author Bio&lt;/h3>
&lt;p>Shira Gray is working as a Business Development Executive at Angular Development
Company – eTatvaSoft.com,to &lt;a href="https://www.etatvasoft.com/">know more&lt;/a> information
about the company. She writes about emerging technologies. Being a tech geek,
she keeps a close watch over the industry focusing on the latest technology news
and gadgets.&lt;/p></description></item><item><title>How to build a reusable Modal Overlay/Dialog Using Angular CDK</title><link>https://codinglatte.com/posts/angular/reusable-modal-overlay-using-angular-cdk-overlay/</link><pubDate>Wed, 20 Nov 2019 02:49:14 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/reusable-modal-overlay-using-angular-cdk-overlay/</guid><description>&lt;p>Today, I am going to show you how to create a reusable modal overlay/dialog
using Angular CDK Overlay that can be reused inside our Angular project
multiple times with ease. We are going to try and match the behavior and
the functionality of Angular Material Dialog component, but using the UI Framework
of our choice.&lt;/p>
&lt;div class="column has-text-centered">
&lt;video width="100%" controls>
&lt;source src="https://codinglatte.com/posts/angular/reusable-modal-overlay-using-angular-cdk-overlay/resources/demo.webm" type="video/webm" />
&lt;source src="https://codinglatte.com/posts/angular/reusable-modal-overlay-using-angular-cdk-overlay/resources/demo.mp4" type="video/mp4" />
&lt;p>Your browser doesn't support HTML5 video. Here is
a &lt;a target="_blank" href="https://codinglatte.com/posts/angular/reusable-modal-overlay-using-angular-cdk-overlay/resources/demo.mp4">link to the video&lt;/a> instead.&lt;/p>
&lt;/video>
&lt;/div>
&lt;p>This is going to be the first of a few articles, focusing on ways you can
utilize Angular CDK to implement common interaction patterns within your
application.&lt;/p>
&lt;h3 id="demo-and-source-code">Demo and Source Code&lt;/h3>
&lt;p>You can find the link to the demo &lt;a href="https://mainawycliffe.github.io/ng-cdk-overlay-demo/">here&lt;/a> and the GitHub repo for this post &lt;a href="https://github.com/mainawycliffe/ng-cdk-overlay-demo">here&lt;/a>.&lt;/p>
&lt;h3 id="prerequisites">Prerequisites&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Install Angular CLI and create a new Angular project – &lt;a href="https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/">link&lt;/a>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Setup Bulma inside your Angular Project.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Install Angular CDK – &lt;code>npm i @angular/cdk&lt;/code> or &lt;code>yarn add @angular/cdk&lt;/code>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>The article is divided into two sections:&lt;/p>
&lt;ul>
&lt;li>The Basics - a Quick look at how to use Angular CDK Overlay&lt;/li>
&lt;li>Building a Reusable Modal Overlay - A detailed guide into building a reusable
modal overlay.&lt;/li>
&lt;/ul>
&lt;h3 id="the-basics">The Basics&lt;/h3>
&lt;p>Let us get the basics out of the way first. Assuming you have installed Angular CDK you will need to import &lt;code>OverlayModule&lt;/code> into your app module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">import&lt;/span> {&lt;span style="color:#a6e22e">OverlayModule&lt;/span>} &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/cdk/overlay&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, inject the &lt;code>Overlay&lt;/code> service and &lt;a href="https://angular.io/api/core/ViewContainerRef#description">ViewContainerRef&lt;/a> into your component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">overlay&lt;/span>: &lt;span style="color:#66d9ef">Overlay&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">viewContainerRef&lt;/span>: &lt;span style="color:#66d9ef">ViewContainerRef&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To show a modal overlay, you need either a &lt;a href="https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/">Template&lt;/a> or an Angular &lt;a href="https://angular.io/api/core/Component">Component&lt;/a> holding the content you would like to show. Let’s look at how you can use both below:&lt;/p>
&lt;h4 id="using-a-template">Using a Template&lt;/h4>
&lt;p>Inside the template of our component, let’s define a new template and add our overlay content:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-template&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">tpl&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-card&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">header&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-card-head&amp;#34;&lt;/span>&amp;gt;
…
&amp;lt;/&lt;span style="color:#f92672">header&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">section&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-card-body&amp;#34;&lt;/span>&amp;gt;
…
&amp;lt;/&lt;span style="color:#f92672">section&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">footer&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-card-foot&amp;#34;&lt;/span>&amp;gt;
…
&amp;lt;/&lt;span style="color:#f92672">footer&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-template&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, add a method to show the overlay and it accepts an &lt;code>ng-template&lt;/code> reference as the parameter.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">openWithTemplate&lt;/span>(&lt;span style="color:#a6e22e">tpl&lt;/span>: &lt;span style="color:#66d9ef">TemplateRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, Inside the above method, we are going to create an overlay. We will start by defining the configs of the overlay – &lt;code>OverlayConfig&lt;/code>. In our case, we will just set the &lt;code>hasBackdrop&lt;/code> and &lt;code>backdropClass&lt;/code> properties. For &lt;code>backdropClass&lt;/code> we are using &lt;code>modal-background&lt;/code> a Bulma CSS Framework class. You can find all the Overlay Configurations you can add &lt;a href="https://material.angular.io/cdk/overlay/api#OverlayConfig">here&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">configs&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">OverlayConfig&lt;/span>({
&lt;span style="color:#a6e22e">hasBackdrop&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#a6e22e">panelClass&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;modal&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;is-active&amp;#39;&lt;/span>],
&lt;span style="color:#a6e22e">backdropClass&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;modal-background&amp;#39;&lt;/span>
});
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: For &lt;code>backdrop&lt;/code> click to dismiss the modal overlay to work, you might need
to disable &lt;code>pointer-events&lt;/code> for your modal, for some CSS Frameworks like
Bulma. This is because CDK Overlay doesn&amp;rsquo;t add them to DOM in the nested order
of &lt;code>modal ➡ modal-background ➡ modal-content&lt;/code>, but rather &lt;code>modal ➡ modal-content&lt;/code>, while the backdrop is a separate div tag not nested under
&lt;code>modal&lt;/code>, but on a level above &lt;code>modal&lt;/code> class div tag.&lt;/p>
&lt;/blockquote>
&lt;div class="column">
&lt;amp-img sizes="(min-width: 35em) 1200px, 100vw" srcset='
https://codinglatte.com/posts/angular/reusable-modal-overlay-using-angular-cdk-overlay/resources/code_snippet_hu83e21899ce623e0ba8a6c594718f4b9c_58588_500x0_resize_box_2.png 500w
, https://codinglatte.com/posts/angular/reusable-modal-overlay-using-angular-cdk-overlay/resources/code_snippet_hu83e21899ce623e0ba8a6c594718f4b9c_58588_800x0_resize_box_2.png 800w
, /posts/angular/reusable-modal-overlay-using-angular-cdk-overlay/resources/code_snippet_hu83e21899ce623e0ba8a6c594718f4b9c_58588_1200x0_resize_box_2.png 1200w
' alt="Adaptive Layout Design - Angular Flex Layout" class="contain" layout="fill">
&lt;/div>
&lt;blockquote>
&lt;p>For Bulma CSS framework case, you can override the default behavior like this:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-css" data-lang="css">.&lt;span style="color:#a6e22e">modal&lt;/span> {
pointer-events: &lt;span style="color:#66d9ef">none&lt;/span> &lt;span style="color:#75715e">!important&lt;/span>;
}
.&lt;span style="color:#a6e22e">modal-content&lt;/span> {
pointer-events: &lt;span style="color:#66d9ef">all&lt;/span> &lt;span style="color:#75715e">!important&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, let’s create an &lt;code>OverlayRef&lt;/code>, by using the &lt;code>create&lt;/code> method of the Overlay service and pass the configs we just created above:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">overlayRef&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">overlay&lt;/span>.&lt;span style="color:#a6e22e">create&lt;/span>(&lt;span style="color:#a6e22e">configs&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then we can attach our template, using &lt;a href="https://material.angular.io/cdk/portal/api#TemplatePortal">TemplatePortal&lt;/a>, passing our template and &lt;code>ViewContainerRef&lt;/code> which we injected into our component:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">overlayRef&lt;/span>.&lt;span style="color:#a6e22e">attach&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">TemplatePortal&lt;/span>(&lt;span style="color:#a6e22e">tpl&lt;/span>, &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">viewContainerRef&lt;/span>));
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, we can trigger the method with a click of a button:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">openWithTemplate&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">tpl&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span> &amp;gt;
Show
&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="using-a-component">Using a Component&lt;/h4>
&lt;p>The difference between the two is that we will be using &lt;code>ComponentPortal&lt;/code> instead of &lt;code>TemplatePortal&lt;/code> to attach the component to the &lt;code>OverlayRef&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">overlayRef&lt;/span>.&lt;span style="color:#a6e22e">attach&lt;/span>(
&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ComponentPortal&lt;/span>(&lt;span style="color:#a6e22e">OverlayComponent&lt;/span>, &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">viewContainerRef&lt;/span>)
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> The component must be added to the list of &lt;code>entryComponents&lt;/code> in your App Module.&lt;/p>
&lt;h5 id="closing-modal-overlay-on-backdrop-clip">Closing Modal Overlay on Backdrop Clip&lt;/h5>
&lt;p>You can close the overlay when the backdrop is clicked by subscribing to the &lt;code>backdropClick()&lt;/code> and then calling the &lt;code>dispose&lt;/code> method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">overlayRef&lt;/span>.&lt;span style="color:#a6e22e">backdropClick&lt;/span>().&lt;span style="color:#a6e22e">subscribe&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">overlayRef&lt;/span>.&lt;span style="color:#a6e22e">dispose&lt;/span>());
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="making-a-re-usable-modal-overlay">Making a Re-usable Modal Overlay&lt;/h3>
&lt;p>Building modal overlays as shown above works very well if you are building one or two of them, however, it does not really scale very well. Wouldn’t it be nice if you could build a re-usable modal overlay that you can then use across your Angular project or projects? Wouldn’t it also be nice if we could be able to pass data to and receive data from the modal?&lt;/p>
&lt;h4 id="objective">Objective&lt;/h4>
&lt;ul>
&lt;li>
&lt;p>A service to open the modal, than can be injected into any component&lt;/p>
&lt;/li>
&lt;li>
&lt;p>A way to subscribe to when the modal is closed and access the response.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Pass data to the modal&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Pass data as a String, Template or Component.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h4 id="overlay-ref-class">Overlay Ref Class&lt;/h4>
&lt;p>We are going to start by extending the &lt;code>OverlayRef&lt;/code>. We will create a custom &lt;code>OverlayRef&lt;/code>, creatively named &lt;code>MyOverlayRef&lt;/code>, which is going to accept the &lt;code>OverlayRef&lt;/code>, &lt;code>content&lt;/code> and the data to pass to our modal overlay. The content can be of type &lt;code>string&lt;/code>, &lt;code>TemplateRef&lt;/code> or &lt;code>Component&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#75715e">// R = Response Data Type, T = Data passed to Modal Type
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">MyOverlayRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">R&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span>, &lt;span style="color:#a6e22e">T&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#960050;background-color:#1e0010">…&lt;/span>
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">overlay&lt;/span>: &lt;span style="color:#66d9ef">OverlayRef&lt;/span>, &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">content&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">TemplateRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">Type&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>, &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>: &lt;span style="color:#66d9ef">T&lt;/span> ) {
&lt;span style="color:#960050;background-color:#1e0010">…&lt;/span>
}
&lt;span style="color:#960050;background-color:#1e0010">…&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, Inside the &lt;code>MyOverlayRef&lt;/code> class, we are going to add a &lt;code>BehaviorSubject&lt;/code> property named &lt;code>afterClosed$&lt;/code> which we can subscribe to get data once the overlay is closed.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">afterClosed$&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Subject&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">OverlayCloseEvent&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">R&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The behavior subject is going to pass back an &lt;code>OverlayCloseEvent&lt;/code>, which contains the data from modal and how the modal was closed. Feel free to modify this to cover your needs.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span> &lt;span style="color:#a6e22e">OverlayCloseEvent&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">R&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;backdropClick&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;close&amp;#39;&lt;/span>;
&lt;span style="color:#a6e22e">data&lt;/span>: &lt;span style="color:#66d9ef">R&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to add a private method to close the overlay. The method will dispose off the overlay, pass the &lt;code>OverlayCloseEvent&lt;/code> back to the subscriber and complete the &lt;code>afterClosed$&lt;/code> Observable.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">_close&lt;/span>(&lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;backdropClick&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;close&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">data&lt;/span>: &lt;span style="color:#66d9ef">R&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">overlay&lt;/span>.&lt;span style="color:#a6e22e">dispose&lt;/span>();
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">afterClosed$&lt;/span>.&lt;span style="color:#a6e22e">next&lt;/span>({
&lt;span style="color:#a6e22e">type&lt;/span>,
&lt;span style="color:#a6e22e">data&lt;/span>
});
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">afterClosed$&lt;/span>.&lt;span style="color:#a6e22e">complete&lt;/span>();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, we are going to add a second public close method. It will only accept &lt;code>data&lt;/code> as a parameter and will call the private &lt;code>_close&lt;/code> method, to close the modal.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">close&lt;/span>(&lt;span style="color:#a6e22e">data?&lt;/span>: &lt;span style="color:#66d9ef">R&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_close&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;close&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">data&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, we are going to subscribe to &lt;code>backdropClick&lt;/code> and close the modal when clicked. We are adding this subscriber to the &lt;code>MyOverlayRef&lt;/code> constructor.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">overlay&lt;/span>.&lt;span style="color:#a6e22e">backdropClick&lt;/span>().&lt;span style="color:#a6e22e">subscribe&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_close&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;backdropClick&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">null&lt;/span>));
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="overlay-component">Overlay Component&lt;/h4>
&lt;p>Next, we are going to add a special component that we will use to show our modal content. If it is a simple string, we will bind it to a div, while we can use either &lt;code>ngTemplateOutlet&lt;/code> and &lt;code>ngComponentOutlet&lt;/code> to load the &lt;code>template&lt;/code> and &lt;code>component&lt;/code> respectively.&lt;/p>
&lt;h5 id="component-class">Component Class&lt;/h5>
&lt;p>We are going to start by injecting an instance of our &lt;code>MyOverlayRef&lt;/code> into the component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">ref&lt;/span>: &lt;span style="color:#66d9ef">MyOverlayRef&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, let’s define 3 more properties inside our component class:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">contentType&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;template&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;string&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;component&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;component&amp;#39;&lt;/span>;
&lt;span style="color:#a6e22e">content&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">TemplateRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">Type&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>;
&lt;span style="color:#a6e22e">context&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, &lt;code>OnInit&lt;/code>, we need to determine the content type and set the above properties appropriately.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">typeof&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">content&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#e6db74">&amp;#39;string&amp;#39;&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contentType&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;string&amp;#39;&lt;/span>;
} &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">content&lt;/span> &lt;span style="color:#66d9ef">instanceof&lt;/span> &lt;span style="color:#a6e22e">TemplateRef&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contentType&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;template&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">context&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">close&lt;/span>: &lt;span style="color:#66d9ef">this.ref.close.bind&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">ref&lt;/span>)
};
} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contentType&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;component&amp;#39;&lt;/span>;
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, we are going to be adding a global close button, so let’s add a &lt;code>close&lt;/code> method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">close() {&lt;/span>
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">ref&lt;/span>.&lt;span style="color:#a6e22e">close&lt;/span>(&lt;span style="color:#66d9ef">null&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, remember to add the Overlay component as an &lt;code>entryComponent&lt;/code> in your app module.&lt;/p>
&lt;h5 id="component-template">Component Template&lt;/h5>
&lt;p>In the template, we are going to use &lt;code>ngSwitch&lt;/code> to switch between content type and add a global close button for our modal.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-content&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngSwitch&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">contentType&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchCase&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#39;string&amp;#39;&amp;#34;&lt;/span>&amp;gt;
      &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;box&amp;#34;&lt;/span>&amp;gt;
        &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">innerHTML&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">content&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchCase&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#39;template&amp;#39;&amp;#34;&lt;/span>&amp;gt;
…
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchCase&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#39;component&amp;#39;&amp;#34;&lt;/span>&amp;gt;
…
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- You can also add a global close button --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">close&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-close is-large&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">aria-label&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;close&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For template content type, we will use &lt;code>ngTemplateOutlet&lt;/code>, passing the template, which is the &lt;code>content&lt;/code> and then pass the &lt;code>context&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngTemplateOutlet&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;content; context: context&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And while for component content type, we will use &lt;code>ngComponentOutlet&lt;/code>, passing the Component, which is the content:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngComponentOutlet&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;content&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="the-overlay-service">The Overlay Service&lt;/h4>
&lt;p>Next, we are going to create an Overlay service, which we can inject into any component we want to use our modal overlay. Where we are going to inject &lt;code>Overlay&lt;/code> Service and the &lt;code>Injector&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">OverlayService&lt;/span> {
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">overlay&lt;/span>: &lt;span style="color:#66d9ef">Overlay&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">injector&lt;/span>: &lt;span style="color:#66d9ef">Injector&lt;/span>) {}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, add an &lt;code>open&lt;/code> method, which will accept content and data. The &lt;code>data&lt;/code> param, in this case, is the data you would like to pass to your modal.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">open&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">R&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span>, &lt;span style="color:#a6e22e">T&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(
&lt;span style="color:#a6e22e">content&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">TemplateRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">Type&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>,&lt;span style="color:#a6e22e">data&lt;/span>: &lt;span style="color:#66d9ef">T&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">MyOverlayRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">R&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#960050;background-color:#1e0010">…&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Inside the method, first, we need to create an &lt;code>OverlayRef&lt;/code> object by using the &lt;code>Overlay&lt;/code> &lt;code>create&lt;/code> method. Feel free to customize the configs to suit your needs.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">configs&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">OverlayConfig&lt;/span>({
&lt;span style="color:#a6e22e">hasBackdrop&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#a6e22e">panelClass&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;modal&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;is-active&amp;#39;&lt;/span>],
&lt;span style="color:#a6e22e">backdropClass&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;modal-background&amp;#39;&lt;/span>
});
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">overlayRef&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">overlay&lt;/span>.&lt;span style="color:#a6e22e">create&lt;/span>(&lt;span style="color:#a6e22e">configs&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, let’s instantiate our &lt;code>MyOverlayRef&lt;/code> Class passing the &lt;code>OverlayRef&lt;/code> object we created above, then content and the data, both from the method parameters.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">myOverlayRef&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">MyOverlayRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">R&lt;/span>, &lt;span style="color:#a6e22e">T&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#a6e22e">overlayRef&lt;/span>, &lt;span style="color:#a6e22e">content&lt;/span>, &lt;span style="color:#a6e22e">data&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Create an injector using &lt;code>PortalInjector&lt;/code>, so that we can inject our custom &lt;code>MyOverlayRef&lt;/code> object to the overlay component, we created above.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">injector&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">createInjector&lt;/span>(&lt;span style="color:#a6e22e">myOverlayRef&lt;/span>, &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">injector&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally use &lt;code>ComponentPortal&lt;/code>, to attach the &lt;code>OverlayComponent&lt;/code> we created above and the newly created injector and return a &lt;code>MyOverlayRef&lt;/code> object.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">overlayRef&lt;/span>.&lt;span style="color:#a6e22e">attach&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ComponentPortal&lt;/span>(&lt;span style="color:#a6e22e">OverlayComponent&lt;/span>, &lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">injector&lt;/span>));
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">myOverlayRef&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And here is the method for creating a custom injector using &lt;code>PortalInjector&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">createInjector&lt;/span>(&lt;span style="color:#a6e22e">ref&lt;/span>: &lt;span style="color:#66d9ef">MyOverlayRef&lt;/span>, &lt;span style="color:#a6e22e">inj&lt;/span>: &lt;span style="color:#66d9ef">Injector&lt;/span>) {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">injectorTokens&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">WeakMap&lt;/span>([[&lt;span style="color:#a6e22e">MyOverlayRef&lt;/span>, &lt;span style="color:#a6e22e">ref&lt;/span>]]);
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">PortalInjector&lt;/span>(&lt;span style="color:#a6e22e">inj&lt;/span>, &lt;span style="color:#a6e22e">injectorTokens&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it, we now have a re-usable modal overlay, that we can use anywhere inside our application.&lt;/p>
&lt;h3 id="usage">Usage&lt;/h3>
&lt;p>First, inject the Overlay Service in the component where you would like to open a new modal overlay.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">overlayService&lt;/span>: &lt;span style="color:#66d9ef">OverlayService&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, inside the method you would want to trigger the modal overlay, you just
use the open method and pass the content and any data you want to pass to the
modal overlay.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">ref&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">overlayService&lt;/span>.&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#a6e22e">content&lt;/span>, &lt;span style="color:#66d9ef">null&lt;/span>);
&lt;span style="color:#a6e22e">ref&lt;/span>.&lt;span style="color:#a6e22e">afterClosed$&lt;/span>.&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span>);
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The content can be a simple string or a &lt;code>Template&lt;/code> or a &lt;code>Component&lt;/code>.&lt;/p>
&lt;h4 id="string">String&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">ref&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">overlayService&lt;/span>.&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">null&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="template">Template&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-template&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">tpl&lt;/span> &lt;span style="color:#a6e22e">let-close&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;close&amp;#34;&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-card&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">section&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-card-body&amp;#34;&lt;/span>&amp;gt;
A yes no dialog, using template
&amp;lt;/&lt;span style="color:#f92672">section&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">footer&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;modal-card-foot&amp;#34;&lt;/span>&amp;gt;
   &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;buttons&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">close&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">yes&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;button&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;button is-success&amp;#34;&lt;/span>&amp;gt;Yes&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">close&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">no&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;button&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;button is-danger&amp;#34;&lt;/span>&amp;gt;No&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">footer&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-template&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And a button to open the modal:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">open&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">tpl&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;button is-small is-primary&amp;#34;&lt;/span>&amp;gt;
Show
&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then open the overlay with an &lt;code>open&lt;/code> method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#a6e22e">content&lt;/span>: &lt;span style="color:#66d9ef">TemplateRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>) {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">ref&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">overlayService&lt;/span>.&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#a6e22e">content&lt;/span>, &lt;span style="color:#66d9ef">null&lt;/span>);
&lt;span style="color:#a6e22e">ref&lt;/span>.&lt;span style="color:#a6e22e">afterClosed$&lt;/span>.&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span>);
});
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="component">Component&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">open() {&lt;/span>
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">ref&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">overlayService&lt;/span>.&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#a6e22e">YesNoDialogComponent&lt;/span>, &lt;span style="color:#66d9ef">null&lt;/span>);
&lt;span style="color:#a6e22e">ref&lt;/span>.&lt;span style="color:#a6e22e">afterClosed$&lt;/span>.&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span>);
});
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can also inject the &lt;code>MyOverlayRef&lt;/code> inside the component to access data and the close method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">ref&lt;/span>: &lt;span style="color:#66d9ef">MyOverlayRef&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This allows you to pass data to the component and trigger the closing of the modal from within the component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">close&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">ref&lt;/span>.&lt;span style="color:#a6e22e">close&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> Please remember to add the component as an &lt;code>entryComponent&lt;/code> inside your App Module.&lt;/p>
&lt;p>You can find all of the above code &lt;a href="https://github.com/mainawycliffe/ng-cdk-overlay-demo">here&lt;/a> and the demo &lt;a href="https://mainawycliffe.github.io/ng-cdk-overlay-demo/">here&lt;/a>.&lt;/p>
&lt;h3 id="additional-resources">Additional Resources&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://material.angular.io/cdk/categories">Angular Component Development Kit (CDK)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://netbasal.com/creating-powerful-components-with-angular-cdk-2cef53d81cea">Creating Powerful Components with Angular CDK
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://material.angular.io/cdk/overlay/api">API reference for Angular CDK overlay&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/">Angular ng-template, ng-container and ngTemplateOutlet - The Complete Guide To Angular Templates&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Angular Newsletter Issue No #3 7th November 2019</title><link>https://codinglatte.com/newsletters/angular-newsletter-issue-no-3-7th-november-2019/</link><pubDate>Thu, 07 Nov 2019 00:19:54 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/newsletters/angular-newsletter-issue-no-3-7th-november-2019/</guid><description>&lt;p>This is my weekly newsletter for Angular and related news. Every week, I go through the web and find and curate the articles I find most interesting to share with you.&lt;/p>
&lt;h3 id="1-translocos-new-dev-tools-make-i18n-in-angular-easy-as-pie">1. Transloco’s New Dev Tools Make i18n in Angular Easy as Pie&lt;/h3>
&lt;p>…&lt;/p>
&lt;p>Translation is a tiresome and repetitive task. Each time we add new text, we need to create a new entry in the translation file, find the correct placement for it, etc. Moreover, when we delete existing keys, we need to remember to remove them from each translation file.&lt;/p>
&lt;p>To make the process less burdensome, we’ve created two tools for the Transloco library, which will do the monotonous work for you. Let’s examine each one:&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Netanel Basal&lt;/em> | &lt;strong>&lt;a href="https://netbasal.com/translocos-new-dev-tools-make-i18n-in-angular-easy-as-pie-889b3ddd6a69">Read Article&lt;/a>&lt;/strong>&lt;/p>
&lt;h3 id="2-use-the-new-angular-clipboard-cdk-to-interact-with-the-clipboard">2. Use the new Angular Clipboard CDK to interact with the clipboard&lt;/h3>
&lt;p>The &lt;a href="https://github.com/angular/components/releases/tag/9.0.0-next.1">helium-barbell (v9.0.0-next.1)&lt;/a> release brings us a new CDK clipboard module to interact with the clipboard. In this post, we&amp;rsquo;ll explore how to use the new CDK with some examples.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Tim Deschryver&lt;/em> | &lt;strong>&lt;a href="https://timdeschryver.dev/posts/use-the-new-angular-clipboard-cdk-to-interact-with-the-clipboard">Read Article&lt;/a>&lt;/strong>&lt;/p>
&lt;h3 id="3-the-new-angular-youtube-player-component">3. The new Angular YouTube Player component!&lt;/h3>
&lt;p>There’s a cool new component in the Angular world 🌎! It makes it easier than ever before to add YouTube videos to your Angular applications. Install it today and try it out:&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By Craig | &lt;strong>&lt;a href="https://dev.to/phenomnominal/the-new-angular-youtube-player-component-2cn6">Read Article&lt;/a>&lt;/strong>&lt;/p>
&lt;h3 id="4-upgrading-with-angular-elements-top-lessons-learned">4. Upgrading with Angular Elements: Top Lessons Learned&lt;/h3>
&lt;p>In my last blog, &lt;a href="https://medium.com/capital-one-tech/capital-one-is-using-angular-elements-to-upgrade-from-angularjs-to-angular-42f38ef7f5fd">How Capital One is Using Angular Elements to Upgrade from AngularJS to Angular&lt;/a>, I gave a deep dive into Capital One’s massive Angular transformation of our customer servicing platform. Today, I want to build on that by sharing with you the top lessons we have learned and embraced during our migration journey. Some of these lessons are human focused, and others are centered around technical challenges we have faced.&lt;/p>
&lt;p>If you haven’t already, check out our &lt;a href="https://www.youtube.com/watch?v=WFzph5uTdmw">Ng-Conf 2019 talk&lt;/a> on how we are using Angular elements!&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>TJ Seaman&lt;/em> | &lt;strong>&lt;a href="https://medium.com/capital-one-tech/upgrading-with-angular-elements-eb3185e26382">Read
Article&lt;/a>&lt;/strong>&lt;/p>
&lt;h3 id="5-google-maps-is-now-an-angular-component">5. Google Maps is now an Angular component&lt;/h3>
&lt;p>The new Angular Component &lt;a href="https://github.com/angular/components/releases/tag/9.0.0-rc.0">pearl-lullaby (v9.0.0-rc.0)&lt;/a> introduces the second official @angular/component component, a Google Maps component. In this post, we take a look at getting started with the Google Maps component.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Tim Deschryver&lt;/em> | &lt;a href="https://timdeschryver.dev/posts/google-maps-as-an-angular-component">&lt;strong>Read Article&lt;/strong>&lt;/a>&lt;/p>
&lt;h3 id="6-debugging-memory-leaks-in-angular">6. Debugging Memory Leaks in Angular&lt;/h3>
&lt;p>Building large applications entails writing lots of code, complex pages, long lists, and hundreds (if not more) of components. If you’ve worked at least once in a non-trivial web application, you may have found yourself battling a memory leak for hours and hours.&lt;/p>
&lt;p>In this article, I want to introduce you to a number of situations where memory leaks are most likely to happen, and how you can deal with them thanks to the powerful Chrome DevTools.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Giancarlo Buomprisco&lt;/em> | &lt;strong>&lt;a href="https://dev.to/gc_psk/debugging-memory-leaks-in-angular-4m2o">Read Article&lt;/a>&lt;/strong>&lt;/p>
&lt;h3 id="7-exciting-times-ahead--be-ready-for-angular-9">7. Exciting Times Ahead — Be Ready For Angular 9&lt;/h3>
&lt;p>The Angular 9 RC is out, what an exciting time to be Angular developer, no I am not saying this because of Angular 9 RC release. It&amp;rsquo;s because Ivy is here, Ivy is now the default rendering engine in Angular.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Santosh Yadav&lt;/em> | &lt;a href="https://blog.angularindepth.com/exciting-time-ahead-be-ready-for-angular-9-b3dbb4078c47">&lt;strong>Read Article&lt;/strong>&lt;/a>&lt;/p>
&lt;h3 id="8-why-do-we-have-dependency-injection-in-web-development">8. Why do we have Dependency Injection in web development&lt;/h3>
&lt;p>Dependency Injection (DI) software design pattern has long been part of native client and server-side applications that use OOP languages. In essence it’s a technique for achieving Inversion of Control (IoC) between classes and their dependencies. With the rise of enterprise focused front-end frameworks like Angular and Ember, many web developers have become familiar with the pattern and mechanism of DI container.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Max Koretskyi&lt;/em> | &lt;a href="https://blog.angularindepth.com/why-do-we-have-dependency-injection-in-web-development-f8815e593b38">&lt;strong>Read Article&lt;/strong>&lt;/a>&lt;/p>
&lt;h3 id="9-announcing-typescript-37">9. Announcing TypeScript 3.7&lt;/h3>
&lt;p>We’re thrilled to announce the release of TypeScript 3.7, a release packed with awesome new language, compiler, and tooling features.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Daniel&lt;/em> | &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/">&lt;strong>Read Article&lt;/strong>&lt;/a>&lt;/p>
&lt;h3 id="10-3-easy-ways-to-boost-your-web-application-performance">10. 3 easy ways to boost your web application performance&lt;/h3>
&lt;p>When building a web application, there’s something you absolutely need to take account: performance. Your app may be greatly designed or have some killer features, nobody will use it if it’s not performant. Users are not patient. But how can one make an app more performant? Well, the less your browser has stuff to do, the faster it will be, right? Then, a great strategy to boost your app performance is to give the browser less work, that is to say, reduce the amount of stuff to load. There are easy ways to do so and we’ll take a look at three of them today.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Thomas Lombart&lt;/em> | &lt;strong>&lt;a href="https://thomlom.dev/3-ways-boost-web-app-performance/">Read Article&lt;/a>&lt;/strong>&lt;/p>
&lt;h3 id="11--restricting-notification-permission-prompts-in-firefox">11. Restricting Notification Permission Prompts in Firefox&lt;/h3>
&lt;p>In April we announced our intent to reduce the amount of annoying permission prompts for receiving desktop notifications that our users are seeing on a daily basis. To that effect, we ran a series of studies and experiments around restricting these prompts.&lt;/p>
&lt;p>Based on these studies, we will require user interaction on all notification permission prompts, starting in Firefox 72. That is, before a site can ask for notification permission, the user will have to perform a tap, click, or press a key.&lt;/p>
&lt;p>In this blog post I will give a detailed overview of the study results and further outline our plans for the future.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Mozilla&lt;/em> | &lt;a href="https://blog.mozilla.org/futurereleases/2019/11/04/restricting-notification-permission-prompts-in-firefox/">&lt;strong>Read Article&lt;/strong>&lt;/a>&lt;/p>
&lt;h3 id="12-getting-your-sites-ready-for-the-new-microsoft-edge">12. Getting your sites ready for the new Microsoft Edge&lt;/h3>
&lt;p>This morning, we released Microsoft Edge Beta version 79, which is the final Beta before the new Microsoft Edge is generally available, also known as the “Release Candidate.” On January 15th, we expect to release the “Stable” channel, at which point Microsoft Edge will be generally available to download on Windows and macOS.&lt;/p>
&lt;p>The new Microsoft Edge is built on the Chromium engine, providing best in class compatibility with extensions and web sites, with great support for the latest rendering capabilities, modern web applications, and powerful developer tools across all supported platforms.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>By &lt;em>Kyle Pflug&lt;/em> and &lt;em>John Jansen&lt;/em> | &lt;a href="https://blogs.windows.com/msedgedev/2019/11/04/edge-chromium-release-candidate-get-ready/">&lt;strong>Read
Article&lt;/strong>&lt;/a>&lt;/p></description></item><item><title>Weekly Angular Newsletter 13th 21st October 2019</title><link>https://codinglatte.com/newsletters/weekly-angular-newsletter-13th-21st-october-2019/</link><pubDate>Mon, 21 Oct 2019 19:16:56 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/newsletters/weekly-angular-newsletter-13th-21st-october-2019/</guid><description>&lt;p>First, I would like to apologize for being late in this week’s newsletter, I was in &lt;a href="https://devfest.gdgnairobi.com/">GDG Devfest Nairobi 2019&lt;/a> over the weekend, and arrived back at home yesterday at Night. I hope to write more about that later. This is my second weekly newsletter on Angular, which starts from the 13th to 21st (today) of October 2019.&lt;/p>
&lt;p>Here are some of the most interesting articles I came across over the course of the week.&lt;/p>
&lt;h3 id="1-the-angular-team--angularconnect-2019-by-stephen-fluin">1. The Angular Team @ AngularConnect 2019 by Stephen Fluin&lt;/h3>
&lt;p>It was our pleasure to attend AngularConnect again this year and to talk to hundreds of amazing engineers.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/newsletters/weekly-angular-newsletter-13th-21st-october-2019/angularconnect.jpg" alt="The Angular Team @ AngularConnect 2019 by Stephen Fluin" width="600" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>This year the team focused on sharing insights and opening the curtain into some of the internals of how Angular works and the challenges we are taking on as a team.&lt;/p>
&lt;h3 id="2-hack-for-good-by-sebastian-witalec">2. Hack for Good By Sebastian Witalec&lt;/h3>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/newsletters/weekly-angular-newsletter-13th-21st-october-2019/hackathon.png" alt=" Hack for Good By Sebastian Witalec" width="600" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>The Angular and NativeScript teams teamed up last month to organise the first ng-ns Hack For Good — an online hackathon with prizes, where all participants were asked to build mobile apps with NativeScript Angular for NGOs and good causes.&lt;/p>
&lt;p>The rules were quite simple: starting from Thursday the 12th of September, participants — working alone or in teams of up to 4 people — had 96 hours to build a Native Mobile App — using NativeScript and Angular.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://blog.angular.io/hack-for-good-6b500f1946a3">Read Article&lt;/a>.&lt;/p>
&lt;h3 id="3-testing-asynchronous-code-in-angular-using-fakeasync-by-netanel-basal">3. Testing Asynchronous Code in Angular Using FakeAsync by Netanel Basal&lt;/h3>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/newsletters/weekly-angular-newsletter-13th-21st-october-2019/testing-asynchronous-code-in-angular-using-fakeasync.jpeg" alt="Testing Asynchronous Code in Angular Using FakeAsync by Netanel Basal" width="400" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>…&lt;/p>
&lt;p>fakeAsync is a special zone that lets us test asynchronous code in a synchronous way. Unlike the original zone that performs some work and delegates the task to the browser or Node.js, fakeAsync buffers each task internally, exposes an API that lets us decide when the task should be executed.&lt;/p>
&lt;p>In this article, we’ll learn how we can use it to make async tests predictable, and how it works under the hood. To make the code cleaner and easier to read, in the following examples, I’ll use Spectator. It’ll work in the same way as when using the native testing API directly.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://netbasal.com/testing-asynchronous-code-in-angular-using-fakeasync-fc777f86ed13">Read Article&lt;/a>.&lt;/p>
&lt;h3 id="4-angular--css-grid-dynamic-grid-properties-by-erxk-verduin">4. Angular &amp;amp; CSS Grid: Dynamic Grid Properties by Erxk Verduin&lt;/h3>
&lt;p>Article Goal: Investigate one way to dynamically modify CSS Grid Properties using Angular’s @HostBinding Decorator.&lt;/p>
&lt;p>Article Topics:&lt;/p>
&lt;ul>
&lt;li>Use CSS-Grid with Angular Components by leveraging the :host selector&lt;/li>
&lt;li>How to adjust CSS Grid Properties such as column-template-rows and gap with TypeScript dynamically.&lt;/li>
&lt;li>Angular’s DOM Sanitizer, why we have to bypass security and some guidelines we should follow when doing so.&lt;/li>
&lt;/ul>
&lt;p>&lt;a href="https://itnext.io/angular-css-grid-dynamic-grid-properties-1a03634607a1">Read Article&lt;/a>.&lt;/p>
&lt;h3 id="5-from-angularjs-to-angular--a-25-years-migration-journey-by-aurélia-rochat">5. From AngularJS to Angular : a 2.5 years migration journey by Aurélia Rochat&lt;/h3>
&lt;p>When I realized I spent 2.5 years migrating an AngularJS application to Angular (among other things), I thought it would be worth telling the story.&lt;/p>
&lt;p>The aim of this text is not to present in detail the technical challenges we met nor the solutions we chose, but to explain the journey we undertook while replacing every single line of code in our application codebase.&lt;/p>
&lt;p>My idea is to share the mistakes we made, the pitfalls we fell into, and the advice I can give to anyone who is about to begin such endeavor.&lt;/p>
&lt;p>To give you an idea of the application size, our github repo counted&lt;/p>
&lt;p>118'030 lines of code&lt;/p>
&lt;p>1'706 files&lt;/p>
&lt;p>in the application src/app folder (typescript, html and scss files included) rightafter the migration was completed.&lt;/p>
&lt;p>&amp;hellip;&lt;/p>
&lt;p>&lt;a href="https://medium.com/@rochat.aurelia/from-angularjs-to-angular-a-2-years-journey-5afcebe050a8">Read Article&lt;/a>.&lt;/p>
&lt;h3 id="6-wrapping-commonjs-library-in-angular-8-directive-on-the-example-of-markjs-by-alexander-poshtaruk">6. Wrapping CommonJS library in Angular 8 directive on the example of mark.js by Alexander Poshtaruk&lt;/h3>
&lt;p>…&lt;/p>
&lt;p>Time to time on my daily tasks I have to implement some functionality that was already implemented by someone previously in a neat vanillaJS library, but… no Angular version or even ES6 module of it is available to be able to easily grab it into your Angular 8 application.&lt;/p>
&lt;p>Yes, you can attach this lib in index.html with script tag but from my point of view, it hardens maintainability. Also, you should do the same for another Angular project where you might use it.&lt;/p>
&lt;p>Much better for is create Angular wrapper directive (or component) and publish it as npm package so everyone (and you of course:) can easily re-use it in another project.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://blog.angularindepth.com/wrapping-commonjs-library-in-angular-8-directive-on-the-example-of-mark-js-976cbcd5d10a">Read Article&lt;/a>.&lt;/p>
&lt;h3 id="7-rxjs-subjects-in-depth-by-giancarlo-buomprisco">7. RxJS Subjects in Depth by Giancarlo Buomprisco&lt;/h3>
&lt;p>In this article, I want to explore the topic of RxJS’s implementation of Subjects, a utility that is increasingly getting awareness and love from the community.&lt;/p>
&lt;p>In the past, I have used Subjects in a variety of ways, but sometimes not fully understanding what they are internally and what are the main differences with Observables.&lt;/p>
&lt;p>&lt;a href="https://blog.bitsrc.io/rxjs-subjects-in-depth-56dcfc1dc858">Read Article&lt;/a>.&lt;/p>
&lt;h3 id="8-multiple-http-requests-in-angular-by-kevin">8. Multiple HTTP Requests in Angular by Kevin&lt;/h3>
&lt;p>RxJS can get confusing sometimes and it may not be obvious at first how to do certain things. One of these things may be how to do multiple HTTP requests the right way - but gladly it&amp;rsquo;s not too complicated.&lt;/p>
&lt;p>There might be two different cases for executing multiple requests; either one by another (sequentially) or simultaneously (parallel).&lt;/p>
&lt;p>&lt;a href="https://nehalist.io/multiple-http-requests-in-angular/">Read Article&lt;/a>.&lt;/p>
&lt;h3 id="9-exploring-web-apis-observers--real-life-examples-explained-by-liron-hazan">9. Exploring web APIs Observers — real life examples explained! By Liron Hazan&lt;/h3>
&lt;p>If you enjoys diving into mdn there’s a chance you recognized few web APIs which ends with the “Observer” suffix.&lt;/p>
&lt;p>Those observers are relatively new web APIs (besides the mutationObserver), some of them aren’t supported by all browsers, generally used in observing a certain state of a target element/s and act when detecting that state (by running callback), some came to resolve web traditional ways of knowing when a change occurred (e.g. change of an element/tree, visibility of an element in the viewport etc..) which could be expensive due to calculations who effect performance ( e.g. by triggering reflow/repaint).&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://itnext.io/exploring-web-apis-observers-real-life-examples-explained-ed194477314">Read Article&lt;/a>.&lt;/p></description></item><item><title>Angular Weekly Newsletter 1st to 12th October 2019</title><link>https://codinglatte.com/newsletters/angular-weekly-newsletter-1st-12th-october-2019/</link><pubDate>Sat, 12 Oct 2019 20:58:42 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/newsletters/angular-weekly-newsletter-1st-12th-october-2019/</guid><description>&lt;p>I am excited to announce my new Weekly Newsletter on Angular (and Related News of course). I am going to be sharing interesting articles that I come across every week. This being the first one, I thought I give myself some latitude and start at the beginning of this month.&lt;/p>
&lt;iframe src="https://giphy.com/embed/X8ynfaP1ZwTvTbxH1b" width="800" height="800" frameBorder="0"
class="giphy-embed" allowFullScreen>&lt;/iframe>
&lt;h3 id="1-understanding-rxjs-multicast-operators-by-netanel-basal">1. Understanding RxJS Multicast Operators by &lt;strong>Netanel Basal&lt;/strong>&lt;/h3>
&lt;p>RxJS multicast operators, better known as sharing operators, are probably the most complicated topic to understand in the jungle that is RxJS. In this article, I’ll try to clarify the subject by looking at it in a different way.&lt;/p>
&lt;p>The key to really comprehend them is to understand the mechanism behind them, and the problem which they solve.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://netbasal.com/understanding-rxjs-multicast-operators-77b3f60af0a2">Read Article&lt;/a>&lt;/p>
&lt;h3 id="2-10-things-every-angular-developer-should-know-about-zonejs-by-matthias-junker">2. 10 Things Every Angular Developer Should Know About Zone.js By &lt;strong>Matthias Junker&lt;/strong>&lt;/h3>
&lt;p>Every developer should know the basics about Zone.js&lt;/p>
&lt;p>&lt;a href="https://medium.com/better-programming/zone-js-for-angular-devs-573d89bbb890">Read Article&lt;/a>&lt;/p>
&lt;h3 id="3-using-angular-cli-schematics-by-chris-engelsma">3. Using Angular CLI Schematics by &lt;strong>Chris Engelsma&lt;/strong>&lt;/h3>
&lt;p>…&lt;/p>
&lt;p>Angular Schematics were introduced by the Angular team in 2018, and it provides an API to generate and manage files in your Angular project, as well as providing any required dependencies. Think of it like a templating tool.&lt;/p>
&lt;p>In this article, I will show you how you can leverage the built-in schematics to streamline your Angular development.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://alligator.io/angular/angular-cli-schematics/">Read Article&lt;/a>&lt;/p>
&lt;h3 id="4-speed-up-your-app-with-web-workers-by-kent-c-dodds">4. Speed up your App with Web Workers by &lt;strong>Kent C. Dodds&lt;/strong>&lt;/h3>
&lt;p>…&lt;/p>
&lt;p>You know how you can have multiple tabs open in your browser? Each one of those tabs is running the JavaScript for that page in its own thread. So just because JavaScript is single-threaded, doesn&amp;rsquo;t mean the browser can&amp;rsquo;t spin up multiple threads to run different JavaScript files.&lt;/p>
&lt;p>Web Workers are a browser standard that enables you to do just that! And you can even communicate between those different threads (with some limitations, which we won&amp;rsquo;t get into in this post).&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://kentcdodds.com/blog/speed-up-your-app-with-web-workers">Read Article&lt;/a>&lt;/p>
&lt;h3 id="5-angular-cross-component-communication-by-mehmet-cüneyt-dalan">5. Angular Cross Component Communication by &lt;strong>Mehmet Cüneyt Dalan&lt;/strong>&lt;/h3>
&lt;p>It is very common need to interact with the other component while developing any kind of frameworks or libraries. In angular there are ways to do it.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://medium.com/5bayt/angular-cross-component-communication-df24ae463399">Read Article&lt;/a>&lt;/p>
&lt;h3 id="6-angular-forms-several-ways-reactive-nested-across-routes-by-jennifer-wadella">6. Angular Forms Several Ways: Reactive, Nested, Across Routes by &lt;strong>Jennifer Wadella&lt;/strong>&lt;/h3>
&lt;p>Dealing with forms is rarely simple anymore. Many SaaS products offer highly customizable setups managed by complex and dynamic forms. Knowing how to use Angulars ControlContainer will give you more control, heh, over managing your forms.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://dev.to/bitovi/angular-forms-several-ways-reactive-nested-across-routes-42g3">Read Article&lt;/a>&lt;/p>
&lt;h3 id="7-focus-first-invalid-input-with-angular-forms-by-cory-rylan">7. Focus First Invalid Input with Angular Forms by &lt;strong>Cory Rylan&lt;/strong>&lt;/h3>
&lt;p>When dealing with required inputs on a form sometimes the user can miss&lt;/p>
&lt;p>a required field. When this happens, it can be confusing for users what needs to be resolved to continue in the form. With Angular Forms, we can help the user by focusing the first invalid input when they submit the form.&lt;/p>
&lt;p>…&lt;/p>
&lt;p>&lt;a href="https://dev.to/coryrylan/focus-first-invalid-input-with-angular-forms-48l">Read Article&lt;/a>&lt;/p>
&lt;p>That&amp;rsquo;s it for this issue, see you next week.&lt;/p></description></item><item><title>Implement Infinite Scrolling in a ListView - Flutter</title><link>https://codinglatte.com/posts/flutter/listview-infinite-scrolling-in-flutter/</link><pubDate>Thu, 03 Oct 2019 22:00:23 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/flutter/listview-infinite-scrolling-in-flutter/</guid><description>&lt;p>Infinite scrolling is a technique where loading of content is done continuously as the user scrolls down, without any action from the user. This has popularized by social media sites and apps such as Twitter, where Twitter loads more tweets as you scroll down. This is a form of pagination but requires no user input to load the next page but instead watches scroll position. When they get close to the end, the next bunch of tweets gets loaded, as shown below:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/flutter/listview-infinite-scrolling-in-flutter/demo.gif" alt="ListView Infinite Scrolling in Flutter" width="300px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;h3 id="prerequisite">Prerequisite&lt;/h3>
&lt;ul>
&lt;li>Flutter Installation and Setup – &lt;a href="https://flutter.dev/docs/get-started/install">Link&lt;/a>.&lt;/li>
&lt;/ul>
&lt;h3 id="creating-a-listview">Creating a ListView&lt;/h3>
&lt;p>We are going to start by creating a ListView to display GitHub Repositories. We will use the GraphQL package for &lt;a href="https://github.com/zino-app/graphql-flutter/">flutter&lt;/a> and will load then in bunches of 20. We are also going to display a loading animation when adding fetching new GitHub repositories.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">ListView(
children: &lt;span style="color:#f92672">&amp;lt;&lt;/span>Widget&lt;span style="color:#f92672">&amp;gt;&lt;/span>[
&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">var&lt;/span> repository &lt;span style="color:#66d9ef">in&lt;/span> repositories)
&lt;span style="color:#75715e">// .. list of widgets
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (result.loading)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: &lt;span style="color:#f92672">&amp;lt;&lt;/span>Widget&lt;span style="color:#f92672">&amp;gt;&lt;/span>[
CircularProgressIndicator(),
],
),
],
),
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="use-scrollcontroller-to-detect-scroll-position">Use ScrollController to Detect Scroll Position&lt;/h3>
&lt;p>Next, we need to determine when to load more GitHub Repositories, i.e. when we are at or near the bottom of the list view. To achieve this, we are going to use ScrollController – &lt;a href="https://api.flutter.dev/flutter/widgets/ScrollController-class.html">Link&lt;/a>. We are going to listen to ScrollController, which will let us know whenever we scroll. We can then check if we are at the end or near the end of ListView, and in that case, we load more Repositories.&lt;/p>
&lt;p>We will start by declaring a new widget property, named &lt;code>_scrollController&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Widget&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> StatelessWidget {
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
ScrollController _scrollController &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> ScrollController();
&lt;span style="color:#960050;background-color:#1e0010">@&lt;/span>override
Widget build(BuildContext context) {
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we need to attach our ScrollController to our ListView above.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">ListView(
controller: _scrollController,
children: &lt;span style="color:#f92672">&amp;lt;&lt;/span>Widget&lt;span style="color:#f92672">&amp;gt;&lt;/span>[
&lt;span style="color:#75715e">// ... widgets
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
),
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, we need to listen to ScrollController and check where the user is at scrolling.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">_scrollController
..addListener(() {
&lt;span style="color:#66d9ef">if&lt;/span> (_scrollController.position.pixels &lt;span style="color:#f92672">==&lt;/span>
_scrollController.position.maxScrollExtent) {
&lt;span style="color:#75715e">// ... call method to load more repositories
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>From the above code, we are waiting until the scroll position is at the very end. This might not be convenient for you and you might want to trigger the method to fetch more items earlier, let’s say at 90%.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">_scrollController
..addListener(() {
&lt;span style="color:#66d9ef">var&lt;/span> triggerFetchMoreSize &lt;span style="color:#f92672">=&lt;/span>
&lt;span style="color:#ae81ff">0.9&lt;/span> &lt;span style="color:#f92672">*&lt;/span> _scrollController.position.maxScrollExtent;
&lt;span style="color:#66d9ef">if&lt;/span> (_scrollController.position.pixels &lt;span style="color:#f92672">&amp;gt;&lt;/span>
triggerFetchMoreSize) {
&lt;span style="color:#75715e">// call fetch more method here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }
});
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>This is a simple way to implement infinite scrolling inside a ListView in flutter. You can find the above demo in my GitHub account &lt;a href="https://github.com/mainawycliffe/flutter-infinite-scrolling">here&lt;/a>.&lt;/p>
&lt;h3 id="additional-resource">Additional Resource&lt;/h3>
&lt;ul>
&lt;li>GraphQL Package for Flutter – &lt;a href="https://github.com/zino-app/graphql-flutter/">Link&lt;/a>.&lt;/li>
&lt;li>ListView API Reference – &lt;a href="https://api.flutter.dev/flutter/widgets/ListView-class.html">Link&lt;/a>.&lt;/li>
&lt;li>ScrollController API Reference – &lt;a href="https://api.flutter.dev/flutter/widgets/ScrollController-class.html">Link&lt;/a>.&lt;/li>
&lt;li>GitHub GraphQL Explorer – &lt;a href="https://developer.github.com/v4/explorer/">Link&lt;/a>.&lt;/li>
&lt;/ul></description></item><item><title>Handling Requesting for Permissions Like a Pro in Flutter</title><link>https://codinglatte.com/posts/flutter/handling-requesting-for-permissions-like-a-pro-in-flutter/</link><pubDate>Sat, 14 Sep 2019 17:19:25 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/flutter/handling-requesting-for-permissions-like-a-pro-in-flutter/</guid><description>&lt;p>In this lesson, we are going to look at how to request and check permissions on Android and IOS in Flutter.&lt;/p>
&lt;h2 id="packages">Package(s)&lt;/h2>
&lt;ul>
&lt;li>Permission Handler (&lt;a href="https://pub.dev/packages/permission_handler">permission_handler&lt;/a>)&lt;/li>
&lt;/ul>
&lt;h3 id="installation">Installation&lt;/h3>
&lt;p>The process of installing a flutter package is quite simple, just open the &lt;strong>pubspec&lt;/strong> file and add the package into your dependency bloc section.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">dependencies&lt;/span>:
&lt;span style="color:#66d9ef">permission_handler&lt;/span>:
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>TIP:&lt;/strong> You can use caret versioning to restrict the package version to a specific major version. For instance, &lt;code>permission_handler: ^3.0.0&lt;/code> restricts it to version 3, but you will get both minor updates and patches.
You can learn more about how dart pub package manager works &lt;a href="https://codinglatte.com/posts/flutter/flutter-a-closer-look-at-how-pub-handles-dependency-versions/">here&lt;/a> if you are interested.&lt;/p>
&lt;/blockquote>
&lt;h2 id="permissions">Permissions&lt;/h2>
&lt;p>First, we need to determine which permissions we need, because your app needs to publicly declare the permissions it needs. Some less-sensitive permissions such as the internet, etc. are granted automatically. While other more sensitive permissions, think of Location, Contacts, etc. require user authorization before your app can use them.&lt;/p>
&lt;h3 id="ios-permissions">iOS permissions&lt;/h3>
&lt;p>In iOS, this done by adding the permissions to &lt;strong>Information Property List File&lt;/strong> i.e. &lt;code>info.plist&lt;/code>, with the Permission you need being the Key, accompanied by the reason why your app needs to use the feature.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-xml" data-lang="xml">&lt;span style="color:#f92672">&amp;lt;key&amp;gt;&lt;/span>NSPhotoLibraryUsageDescription&lt;span style="color:#f92672">&amp;lt;/key&amp;gt;&lt;/span>
&lt;span style="color:#f92672">&amp;lt;string&amp;gt;&lt;/span>This app requires to save your images user gallery&lt;span style="color:#f92672">&amp;lt;/string&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In Flutters’ case, the &lt;code>info.plist&lt;/code> in the &lt;code>iOS/Runner&lt;/code> directory at the root of your project. You can learn more about the &lt;code>info.plist&lt;/code> &lt;a href="https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Introduction/Introduction.html">here&lt;/a>.&lt;/p>
&lt;p>You can find the complete list of permissions &lt;a href="https://www.iosdev.recipes/info-plist/permissions/">here&lt;/a> and guidelines for asking permission on iOS &lt;a href="https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/requesting-permission/">here&lt;/a>.&lt;/p>
&lt;h3 id="android-permissions">Android permissions&lt;/h3>
&lt;p>In Android, you can achieve the same by adding the &lt;code>&amp;lt;uses-permission&amp;gt;&lt;/code> tag to the android manifest, this in the &lt;code>android/src/main/AndroidManifest.xml&lt;/code> directory.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-xml" data-lang="xml">&lt;span style="color:#f92672">&amp;lt;manifest&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;span style="color:#f92672">&amp;lt;uses-permission&lt;/span> &lt;span style="color:#a6e22e">android:name=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;android.permission.SEND_SMS&amp;#34;&lt;/span>&lt;span style="color:#f92672">/&amp;gt;&lt;/span>
&lt;span style="color:#f92672">&amp;lt;application&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>
...
&lt;span style="color:#f92672">&amp;lt;/application&amp;gt;&lt;/span>
&lt;span style="color:#f92672">&amp;lt;/manifest&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about permission on Android &lt;a href="https://developer.android.com/training/permissions/requesting">here&lt;/a> and the best practices &lt;a href="https://developer.android.com/training/permissions/usage-notes">here&lt;/a>.&lt;/p>
&lt;h2 id="requesting-for-permission">Requesting for Permission&lt;/h2>
&lt;p>To request permission, first you need to import the package:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;package:permission_handler/permission_handler.dart&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, let say you want to request contact permission, you can do it like this. You pass a list of permissions you are requesting for, which allows you to ask for multiple permissions you need at once.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">final&lt;/span> PermissionHandler _permissionHandler &lt;span style="color:#f92672">=&lt;/span> PermissionHandler();
&lt;span style="color:#66d9ef">var&lt;/span> result &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">await&lt;/span> _permissionHandler.requestPermissions([PermissionGroup.contacts]);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, you can inspect the result to see if the user granted permission or not. The results object is an array of &lt;code>PermissionStatus&lt;/code>. The key of the array is the permission you were asking.&lt;/p>
&lt;p>The possible permission statuses are:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Status&lt;/th>
&lt;th>Why&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Granted&lt;/strong>&lt;/td>
&lt;td>Your app has been given permission to use the feature in question&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Denied&lt;/strong>&lt;/td>
&lt;td>Your app has been given permission to use the feature in question&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Disabled&lt;/strong>&lt;/td>
&lt;td>Feature in question is disabled i.e. when the Location feature is disabled.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Restricted&lt;/strong> (iOS only)&lt;/td>
&lt;td>OS has restricted access to a specific feature due to something like parental controls.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Unknown&lt;/strong>&lt;/td>
&lt;td>Unknown state of permissions.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>For instance, in our example above, we can check if permission to access contacts was granted like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">if&lt;/span> (result[PermissionGroup.contacts] &lt;span style="color:#f92672">==&lt;/span> PermissionStatus.granted) {
&lt;span style="color:#75715e">// permission was granted
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can also use a switch statement to react to the results of your request.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">switch&lt;/span> (result[PermissionGroup.contacts]) {
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.granted:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.denied:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.disabled:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.restricted:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus. Unknown:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">default&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="checking-if-your-app-has-been-given-permission">Checking if your App has been Given Permission&lt;/h2>
&lt;p>It is important that your app can check if it has permission to access certain features. This allows your app to decide based on if the user has granted permission or not. On top of that, it can help you determine if a feature is available or disabled on the users&amp;rsquo; device.&lt;/p>
&lt;p>You can check for permission by using the &lt;code>checkPermissionStatus&lt;/code> function, which accepts the Permission as a parameter.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">final&lt;/span> PermissionHandler _permissionHandler &lt;span style="color:#f92672">=&lt;/span> PermissionHandler();
&lt;span style="color:#66d9ef">var&lt;/span> permissionStatus &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">await&lt;/span> _permissionHandler.checkPermissionStatus(PermissionGroup.location);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This returns a &lt;code>PermissionStatus&lt;/code> class – we saw it above – which details the status of the permission.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">switch&lt;/span> (permissionStatus) {
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.granted:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.denied:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.disabled:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.restricted:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> PermissionStatus.unknown:
&lt;span style="color:#75715e">// do something
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">default&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="tip">Tip&lt;/h2>
&lt;p>Some permissions such as contacts, calendar, microphone, location, etc. are common across iOS and Android. On the other hand, there are some permissions that either do not match up on both OSs. While others are just on one OS, i.e. storage, SMS, phone, etc. are only on android. You might want to determine which platform it is before requesting permission from the user.&lt;/p>
&lt;p>Take a camera app, for instance, if you wanted photos to appear in the gallery, on iOS, you need photos permission while in android you need external storage permission.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">var&lt;/span> permission &lt;span style="color:#f92672">=&lt;/span> Platform.isAndroid &lt;span style="color:#f92672">?&lt;/span> PermissionGroup.storage &lt;span style="color:#f92672">:&lt;/span> PermissionGroup.photos;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, you can check if the user has granted your app permission:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">await&lt;/span> _permissionHandler.checkPermissionStatus(permission);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Or request for permission:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">await&lt;/span> _permissionHandler.requestPermissions([permission]);
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="resources">Resources&lt;/h2>
&lt;ul>
&lt;li>Requesting for Permission on IOS – &lt;a href="https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/requesting-permission/">Link&lt;/a>.&lt;/li>
&lt;li>Requesting for Permission on Android – &lt;a href="https://developer.android.com/training/permissions/requesting">Link&lt;/a>.&lt;/li>
&lt;li>Permission Best Practices on Android – &lt;a href="https://developer.android.com/training/permissions/usage-notes">Link&lt;/a>.&lt;/li>
&lt;li>About Information Property List Files – &lt;a href="https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html">Link&lt;/a>.&lt;/li>
&lt;li>Android App Manifest – &lt;a href="https://developer.android.com/guide/topics/manifest/manifest-intro">Link&lt;/a>.&lt;/li>
&lt;/ul></description></item><item><title>Lazy Loading Modules &amp; Preloading Strategy in Angular 8</title><link>https://codinglatte.com/posts/angular/lazy-loading-modules-preloading-strategy-in-angular-8/</link><pubDate>Sat, 31 Aug 2019 04:20:00 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/lazy-loading-modules-preloading-strategy-in-angular-8/</guid><description>&lt;p>In this lesson, we are going to cover:&lt;/p>
&lt;ul>
&lt;li>Lazy Loading of Feature Modules&lt;/li>
&lt;li>And Creating Preloading Strategy for Lazy-Loaded Modules&lt;/li>
&lt;/ul>
&lt;h2 id="prerequisite">Prerequisite&lt;/h2>
&lt;ol>
&lt;li>&lt;a href="https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/">Install Angular CLI and Create a new Angular Application&lt;/a>&lt;/li>
&lt;/ol>
&lt;h2 id="lazy-loading-feature-modules">Lazy Loading Feature Modules&lt;/h2>
&lt;p>To use lazy loading, first, you need to create some feature modules. Feature modules are &lt;a href="https://angular.io/guide/ngmodules">NgModules&lt;/a> created for the purpose of code organization. Feature modules allow you to separate code for a feature/functionality from the rest of your app. Components, Pipes, Directives, etc. inside a feature module are isolated from the rest of your app and are only accessible inside the feature module.&lt;/p>
&lt;p>To create feature modules, we have two option – a manual approach and automated approach.&lt;/p>
&lt;h3 id="manual-approach">Manual Approach&lt;/h3>
&lt;p>In this approach, we are going to do everything ourselves. First, we are going to use Angular CLI command &lt;code>ng generate module&lt;/code> to generate a feature module. Please note, for the purpose of lazy loading, our module needs to have routing enabled. We can do this by using the &lt;code>--routing&lt;/code> flag, as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate module lazyloadedmodule1 --routing
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above command is going to create a &lt;code>Lazymodule1Module&lt;/code> and &lt;code>Lazymodule1RoutingModule&lt;/code>. Where the first is the &lt;code>NgModule&lt;/code> and the second is the routing module where routes for our feature module will live.&lt;/p>
&lt;p>Secondly, we will need some components or directives or pipes, etc. for our feature module. The simplest approach is to put components/directives/pipes inside the same directory as our feature module or its sub-directories. This way, they will be registered under our feature module. You can also use the &lt;code>--module&lt;/code> flag if you want your feature module and its related assets to live in separate directories.&lt;/p>
&lt;p>And finally, we need to add the feature module inside our app router module, as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;lazy-module-1&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">loadChildren&lt;/span>&lt;span style="color:#f92672">:&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span>
&lt;span style="color:#66d9ef">import&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;./lazymodule1/lazymodule1.module&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">Lazymodule1Module&lt;/span>)
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="automated-approach">Automated Approach&lt;/h3>
&lt;p>As of Angular 8, you can generate a feature module with routing enabled, a default component and add as a lazy loaded route to the router.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate module lazymodulename --module app --route lazy-module-route
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above command must have the following flags:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>--module&lt;/code> flag (&lt;strong>Required&lt;/strong>) – The module where to register the route for the app.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>--route&lt;/code> flag (&lt;strong>Required&lt;/strong>) - The path for your lazy module route.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>If any of the above flags are missing, it will fail.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can use the &lt;code>canLoad&lt;/code> guard to prevent feature module from loading if the user is not authorized to access a route. You can use &lt;code>canLoad&lt;/code> guard alongside &lt;code>canActivate&lt;/code> and &lt;code>canActivateChild&lt;/code> guards which prevent unauthorized requests.&lt;/p>
&lt;/blockquote>
&lt;h2 id="preloading-strategy-for-lazy-loaded-modules">Preloading Strategy for Lazy-Loaded Modules&lt;/h2>
&lt;p>A preload strategy creates rules that determine which modules to preload. So, if you have multiple lazy-loaded modules, a preloading strategy would determine which modules to preload and when to preload them.&lt;/p>
&lt;p>Angular supplies two preloading strategies out of the box:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>NoPreloading&lt;/code> - No preloading (default)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>PreloadAllModules&lt;/code> - Preload of all lazy-loaded modules.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="no-preloading--default-preloading-strategy">No Preloading – Default preloading strategy&lt;/h3>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">RouterModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>(&lt;span style="color:#a6e22e">routes&lt;/span>, { &lt;span style="color:#a6e22e">preloadingStrategy&lt;/span>: &lt;span style="color:#66d9ef">NoPreloading&lt;/span> })
],
&lt;span style="color:#a6e22e">exports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">RouterModule&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppRoutingModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="preloading-all-modules">Preloading All Modules&lt;/h3>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">RouterModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>(&lt;span style="color:#a6e22e">routes&lt;/span>, { &lt;span style="color:#a6e22e">preloadingStrategy&lt;/span>: &lt;span style="color:#66d9ef">PreloadAllModules&lt;/span> })
],
&lt;span style="color:#a6e22e">exports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">RouterModule&lt;/span>]
})
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="creating-a-custom-preload-strategy">Creating a Custom Preload Strategy&lt;/h3>
&lt;p>The first thing we need to do is to determine the formula/strategy to use to determine which lazy-loaded modules to preload. For instance, we can add a preload flag to the routes you want to preload and then check for the flag when determining whether to preload the lazy-loaded module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;module-8&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">loadChildren&lt;/span>&lt;span style="color:#f92672">:&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">import&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;./lazymodule8/lazymodule8.module&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">Lazymodule8Module&lt;/span>),
&lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#f92672">:&lt;/span> { &lt;span style="color:#a6e22e">preload&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> } &lt;span style="color:#75715e">// preload flag
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then we are going to create a service that implements &lt;code>PreloadingStrategy&lt;/code> interface. To implement the interface, we are going to add a &lt;code>preload&lt;/code> function. The preload function accepts two arguments – a route and a loader function:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>The route is the route to consider for preloading.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>And the loader function loads the lazy-loaded module asynchronously when called.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Inside the preload function, we are going to check If the preload flag is set to true, and then return the loader function else we return a null observable.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">MyPreloadingStrategyService&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">PreloadingStrategy&lt;/span> {
&lt;span style="color:#a6e22e">preload&lt;/span>(&lt;span style="color:#a6e22e">route&lt;/span>: &lt;span style="color:#66d9ef">Route&lt;/span>, &lt;span style="color:#a6e22e">load&lt;/span>&lt;span style="color:#f92672">:&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">route&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">route&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;preload&amp;#39;&lt;/span>]) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">load&lt;/span>();
} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#66d9ef">null&lt;/span>);
}
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, we need to set the preload service we created above as the preloading strategy.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">RouterModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>(&lt;span style="color:#a6e22e">routes&lt;/span>, {
&lt;span style="color:#a6e22e">preloadingStrategy&lt;/span>: &lt;span style="color:#66d9ef">MyPreloadingStrategyService&lt;/span> &lt;span style="color:#75715e">// our preloading service here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> })
],
&lt;span style="color:#a6e22e">exports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">RouterModule&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppRoutingModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="preload-strategy-demo">Preload Strategy Demo&lt;/h4>
&lt;p>The following demo uses the preload strategy above. It has 8 routes, where only even-numbered routes are preloaded. After initially loading the application, the app is taken to offline mode and you will notice only preloaded routes load while the others fail due to lack of network.&lt;/p>
&lt;div class="column has-text-centered">
&lt;video width="100%" controls>
&lt;source src="https://codinglatte.com/posts/angular/lazy-loading-modules-preloading-strategy-in-angular-8/videos/demo.webm" type="video/webm" />
&lt;source src="https://codinglatte.com/posts/angular/lazy-loading-modules-preloading-strategy-in-angular-8/videos/demo.mp4" type="video/mp4" />
&lt;p>Your browser doesn't support HTML5 video. Here is
a &lt;a target="_blank" href="https://codinglatte.com/posts/angular/lazy-loading-modules-preloading-strategy-in-angular-8/videos/demo.mp4">link to the video&lt;/a> instead.&lt;/p>
&lt;/video>
&lt;/div>
&lt;h2 id="tips">TIPS&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>You can use &lt;strong>ngx-quiklink&lt;/strong> library to preload all lazy-loaded modules associated with visible links on the screen. You can learn more &lt;a href="https://github.com/mgechev/ngx-quicklink">here&lt;/a>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Another useful library is &lt;a href="https://github.com/guess-js/guess">guess.js&lt;/a> which uses predictive ML to determine which resources to preload. You can find the Angular guide for Guess.js &lt;a href="https://guess-js.github.io/docs/angular">here&lt;/a>.&lt;/p>
&lt;/li>
&lt;/ol></description></item><item><title>I Migrated From WordPress to Hugo</title><link>https://codinglatte.com/posts/updates/i-migrated-from-wordpress-to-hugo/</link><pubDate>Sat, 24 Aug 2019 06:21:40 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/updates/i-migrated-from-wordpress-to-hugo/</guid><description>&lt;p>This article is a few months too late - around 6 months - but as they say, better late than never. A couple of years ago, I started my blog under a different name - theinfogrid.com - initially, it was meant to be a general tech blog, but slowly I found my niche. I started with one &lt;a href="https://codinglatte.com/angular/">Angular&lt;/a> article and when the reception was good, I stuck with it.&lt;/p>
&lt;h2 id="about-the-old-blog">About the Old Blog&lt;/h2>
&lt;p>I build it using WordPress, with a free theme. It cost me around $20 per year, with most of the cost going to the domain name. The cost of shared hosting was about $5. That’s not a lot of money, but If you happen to be fresh out of college and jobless, it’s not little either.&lt;/p>
&lt;p>In a few months, the blog had outgrown my cheap shared hosting plan as I was getting some decent traffic. This led me to move to a Virtual Private Server (VPS) – &lt;a href="https://aws.amazon.com/lightsail/">AWS LightSail&lt;/a>. I started out with the &lt;a href="https://aws.amazon.com/lightsail/pricing/">$5 plan&lt;/a>, and soon that also wasn’t enough and upgraded to the &lt;a href="https://aws.amazon.com/lightsail/pricing/">$10 plan&lt;/a>.&lt;/p>
&lt;p>This worked well for a brief period, but at least once a week, my website would go offline randomly. This was despite using &lt;a href="https://www.cloudflare.com/">Cloudflare&lt;/a> proxy to reduce traffic to my blogs&amp;rsquo; servers and did a very good job. When the site went offline, I had to shut down my LightSail instance, then start it up manually. The problem would then disappear for another week or so. It was common for me to wake up in the morning to find that my blog was down for quite some time.&lt;/p>
&lt;h2 id="finding-an-alternative-to-wordpress">Finding an Alternative to WordPress&lt;/h2>
&lt;p>The way forward was to upgrade to an even larger plan. And while this alleviated the problem, the cost of running the blog was piling up. For someone without a paying day job - I work for a start-up – keeping the costs down is essential.&lt;/p>
&lt;p>I started to look for an alternative solution. I considered a few solutions including using WordPress as a backend only, with Angular as the frontend. To keep the costs low, I would use a CDN – &lt;a href="https://aws.amazon.com/cloudfront/">CloudFront&lt;/a> – to aggressively cache API calls, because I only posted about 3 times a week. For a time, I also toyed around with the idea of migrating to Medium or a similar site.&lt;/p>
&lt;p>I was strongly considering the Angular + WordPress solution until I came across Static Site Generators (SSGs). This solution was mainly inspired by &lt;a href="http://fireship.io/">fireship.io&lt;/a>, when Jeff Delaney, decided to start a &lt;a href="https://www.youtube.com/watch?v=gun8OiGtlNc">new site&lt;/a> and he open-sourced the code. While inspecting the code, I came across Hugo and did some research.&lt;/p>
&lt;p>I compared different Static Site Generators and finally settled on Hugo. It had glowing reviews from people who used it and loved the fact that it was built using Go – sentiments, I guess. And I started working on my new blog.&lt;/p>
&lt;h2 id="my-new-blog">My New Blog&lt;/h2>
&lt;p>I quickly learned how to use Hugo and I was able to quickly build my own theme for my blog. This is because, for the themes I liked, I had seen a few other blogs using them. Funny enough, I didn’t have the same problem with WordPress. But I am guessing that has more to do with my lack of interest in building WordPress Themes. For some reason, I never grew into it despite working with PHP for years.&lt;/p>
&lt;p>Back to my blog, within a matter of weeks, I had a new blog. I rebranded it from &lt;a href="http://theinfogrid.com/">theinfogrid.com&lt;/a> to &lt;a href="https://codinglatte.com/">codinglatte.com&lt;/a> and launched it, with the least amount of fanfare possible. I just happen to be poor at this Social Media thing.&lt;/p>
&lt;p>I was able to migrate successfully while maintaining Google Search ranks that I had earned with my previous blog. In fact, traffic from Google Search increased and almost doubled. Google Search accounts for most of the traffic I get on my blog.&lt;/p>
&lt;p>The blog – &lt;a href="https://codinglatte.com/">this one&lt;/a> – is currently hosted on Firebase, and the cost of running it is very low. Firebase has a very good free plan, and you only get charged when you go over it. Since I always do, the cost comes to around $1 a month. I am working on improvements over the next few weeks on my blog to improve reader experience and provide more value to my readers.&lt;/p>
&lt;p>WordPress comes with a decent built-in comment system. It has very good spam detection, which I really needed as only 1% of the comments I received were not spam. There are several descent comment systems out there, but they can be quite costly. I found this quite challenging.&lt;/p>
&lt;p>I finally settled on &lt;a href="https://github.com/utterance/utterances">utterances&lt;/a> widget which is a comment Widget powered GitHub issues. In a nutshell, you create a GitHub repository for your blog comments and each article/post gets an issue on the repository. Then users can comment on the issue. Utterances handles this automatically for you, you just need to point it to the correct repository.&lt;/p>
&lt;h2 id="drawbacks">Drawbacks&lt;/h2>
&lt;p>It is not all roses though, as, with any solution, Hugo is not perfect. There are a lot of things I really do miss on WordPress. The first one has to do with the WordPress plugins ecosystem, which has a huge number of decent plugins to help you automate tasks and add functionality. On the other hand, Hugo and I am guessing most SSGs, you need to do it manually for tasks and build the functionality you need yourself. For instance, inserting ads into content or setting up redirects after changing the path to posts.&lt;/p>
&lt;p>Another challenge has to do with posts statistics. With WordPress, if you want to add the most popular posts section, it is easy. On the other hand, with Hugo, you can’t, at least not directly. You would need to build a data API that pulls the data from some analytics service and exposes it to Hugo during build time. You can also use JavaScript to pull the data dynamically.&lt;/p>
&lt;p>Another challenge comes up when working with clients. With WordPress, all you need is to show them how to update their content. Once they update the content, the content will be reflected on the site automatically. Hugo on the other hand, if you want a content update to be reflected, you need to rebuild and deploy. For someone like me, this is easy, for a client not so much. There are solutions to automate the process such as using Netlify and a Git backend. This involves setting up a build and deployment pipeline, but as you can tell, it is not as straight forward as WordPress.&lt;/p>
&lt;p>Don’t get me wrong, I enjoy working with Hugo, but these are some of the drawbacks of working with it – and most SSGs out there. I am just pointing out some of the drawbacks to consider before jumping get started. For me, the benefits simply outweigh the drawbacks.&lt;/p></description></item><item><title>Resetting Firebase Auth Passwords in Angular (Email Based Accounts)</title><link>https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/</link><pubDate>Wed, 21 Aug 2019 12:08:55 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/</guid><description>&lt;p>In this post, we are going to cover the following:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>In Firebase Auth, we will customize:&lt;/p>
&lt;ul>
&lt;li>Password Reset Email Content/Message&lt;/li>
&lt;li>Add a Custom Domain for use by email address&lt;/li>
&lt;li>And Password Reset/Email Verification URL&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>In Angular:&lt;/p>
&lt;ul>
&lt;li>Send Password Reset Request Emails&lt;/li>
&lt;li>Confirm Password Reset Code and Set New Password&lt;/li>
&lt;li>Confirm Email Address&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="prerequisite">Prerequisite&lt;/h2>
&lt;ol>
&lt;li>&lt;a href="https://codinglatte.com/how-to/how-to-create-a-firebase-project/">A Firebase Project&lt;/a> – How to create a new Firebase Project.&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/">Create a new Angular App&lt;/a> – How to Install and Create a new Angular App.&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/">Install and Setup @angular/fire (AngularFire2)&lt;/a> – How to Install and Setup Firebase in Angular.&lt;/li>
&lt;/ol>
&lt;h2 id="firebase-auth">Firebase Auth&lt;/h2>
&lt;h3 id="enable-emailpassword-verification">Enable Email/Password Verification&lt;/h3>
&lt;p>First, we are going to enable email password authentication.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>In your Firebase project home page, go to Authentication, on the side nav under Develop menu item. And then, select the &lt;code>sign-in method&lt;/code> tab.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/enable_email_password/1.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>And then, under sign-in providers, under the &lt;code>Email/Password&lt;/code> provider, hover to reveal the edit icon.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/enable_email_password/2.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>And finally, click toggle enable switch and save the changes.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/enable_email_password/3.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="customize-email-address-domain">Customize Email Address Domain&lt;/h3>
&lt;p>Next, let’s customize the email domain Firebase uses to send password reset requests and send user email verification requests to our users.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Under authentication, select the &lt;code>Templates&lt;/code> tab.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/customize_domain/1.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Then, under &lt;code>Email address Verification&lt;/code>, click on the edit icon next to the &lt;code>from&lt;/code> email address.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/customize_domain/2.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>And then, click on the &lt;code>customize domain&lt;/code> link.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/customize_domain/3.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>After that, you will be prompted for the domain name, enter the name and click next.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/customize_domain/4.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Here, you will be prompted to verify your domain name. This is done by adding the DNS records provided by firebase on the verification window to your domains DNS records. This process varies for different domain registrars but it’s also straightforward.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Once you have added the DNS records, click on the verify button. This can take time to verify the records – up to 48 hours on rare occasions – so don’t panic. Once the verification is done, all email sent by Firebase auth will use your domain name.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/customize_domain/5.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="customize-the-password-reset-action-url">Customize the Password Reset Action URL&lt;/h3>
&lt;p>Next, let&amp;rsquo;s customize the password reset URL. By default, Firebase provides a preset URL with a generic UI that handles password resets. We are going to change this so that we can point it to our angular app which will handle confirmation and setting of the new password. This will be configured under the &lt;code>Templates&lt;/code> Tab in Firebase Authentication.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>On the sidebar, select &lt;code>Password Reset&lt;/code> and scroll to the bottom.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/confirmation_link/1.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Click on the &lt;code>Customize Action URL&lt;/code> link, below the Action URL Text Field and Just Above the Save Button.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/confirmation_link/2.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>A modal window titled Action URL will pop up, prompting you to enter a Custom Action URL. Enter a Custom Action URL of your choice – something like &lt;code>http://localhost:4200/auth/email/action&lt;/code> and save.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/confirmation_link/3.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Keep in mind that both Password Reset, Email address change and Verification will share the same Action URL. A query parameter &lt;code>mode&lt;/code>, alongside the &lt;code>oobCode&lt;/code> parameter is appended to the action URL. The &lt;code>mode&lt;/code> parameter holds the action type the user is performing i.e. password reset etc.&lt;/p>
&lt;/blockquote>
&lt;h3 id="customize-password-reset-message">Customize Password Reset Message&lt;/h3>
&lt;p>This is not entirely necessary, but you might want to have a custom message for your app’s users. From the same page as above, you should see the message field, you can customize that by using HTML. Use the following placeholder strings, to inject dynamic data into the template.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/handling-firebase-password-resets-in-angular/images/email_template_change.jpg" alt="Handling Firebase Password Resets in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;ul>
&lt;li>
&lt;p>%DISPLAY_NAME% - The recipient&amp;rsquo;s display name.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>%APP_NAME% - The name of your app. You can set this value by editing the Public-facing name field on the Settings page.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>%LINK% - The URL that the recipient must visit to complete the account management task. See Customize the action link URL.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>%EMAIL% - The recipient&amp;rsquo;s email address.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>%NEW_EMAIL% - The new email address to set as the recipient&amp;rsquo;s primary address. &lt;em>Used only in the Email Address Change template&lt;/em>.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can also customize the Subject of the email too on the same page.&lt;/p>
&lt;/blockquote>
&lt;h2 id="angular-application">Angular Application&lt;/h2>
&lt;p>Assuming you already have created an Angular App and installed &lt;code>@angular/fire&lt;/code> – check the prerequisite section above if you haven’t – let’s dive into sending a password reset request.&lt;/p>
&lt;h3 id="sending-password-resets-requests-component">Sending Password Resets Requests Component&lt;/h3>
&lt;p>This component will collect user email addresses and request Firebase to send a password request if the email exists. Firebase authentication servers are going to determine is an Email exists or not.&lt;/p>
&lt;p>We are going to start by creating a Reactive Form, with one &lt;code>FormControl&lt;/code>. First, we are going to inject both &lt;code>FormBuilder&lt;/code> and &lt;code>AngularFireAuth&lt;/code> services into our component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">afAuth&lt;/span>: &lt;span style="color:#66d9ef">AngularFireAuth&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">fb&lt;/span>: &lt;span style="color:#66d9ef">FormBuilder&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, we are going to declare &lt;code>frmResetPassword&lt;/code> property of type &lt;code>FormGroup&lt;/code>, then set it to a new instance of &lt;code>FormGroup&lt;/code>, with one form field named &lt;code>email&lt;/code>. The form control is going to have validators for both required and obviously email.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">frmPasswordReset&lt;/span>: &lt;span style="color:#66d9ef">FormGroup&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({
&lt;span style="color:#a6e22e">email&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>]]
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let&amp;rsquo;s add a method to be called on from submit, which is going to send a request to Firebase to Send A Password Reset Request to the provided email if it exists.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">email&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">frmPasswordReset&lt;/span>.&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;email&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">value&lt;/span>;
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">afAuth&lt;/span>.&lt;span style="color:#a6e22e">auth&lt;/span>.&lt;span style="color:#a6e22e">sendPasswordResetEmail&lt;/span>(&lt;span style="color:#a6e22e">email&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(
() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// success, show some message
&lt;/span>&lt;span style="color:#75715e">&lt;/span> },
&lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// handle errors
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>When the above process completes successfully, an email address is sent to the user with the password reset link.&lt;/p>
&lt;p>To handle errors, please check for a code property in the returned error. You can find a list of error codes for Firebase Auth &lt;a href="https://firebase.google.com/docs/reference/js/firebase.auth.Error">here&lt;/a>. I have attached a simple Firebase error parser at the bottom of this post.&lt;/p>
&lt;p>And finally, here is the template for this component:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">form&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">formGroup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmPasswordReset&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">submit&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">sendPasswordResetRequest&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;field has-text-left&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;label&amp;#34;&lt;/span>&amp;gt;Email Address: &amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;control has-icons-left&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;input is-focused&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;icon is-small is-left&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">fa-icon&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">icon&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">faEnvelope&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">fa-icon&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;has-text-danger&amp;#34;&lt;/span>&amp;gt;
Email is required!
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;has-text-danger&amp;#34;&lt;/span> &amp;gt;
A valid email is required!
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;field&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">disabled&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmPasswordReset&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">invalid&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;button is-block is-primary has-text-white is-fullwidth &amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">fa-icon&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">icon&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">faSigninIcon&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">fa-icon&lt;/span>&amp;gt;
Send Request
&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">form&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="confirming-email-and-setting-a-new-password-for-the-user">Confirming Email and Setting a New Password for the User&lt;/h3>
&lt;p>The password reset link and email confirmation/verification link are the same, with the only variants being &lt;code>oobCode&lt;/code> and &lt;code>mode&lt;/code>. The mode will determine whether a user is resetting a password or confirming their email address. It can either be &lt;code>resetPassword&lt;/code> or &lt;code>verifyEmail&lt;/code>.&lt;/p>
&lt;p>This means that these two actions are going to be redirected to the same route in our Angular Application. As such, we are going to need 3 components – One for switching between the modes, one for resetting password and another for confirming/verifying email addresses.&lt;/p>
&lt;h4 id="switching-between-reset-password-and-verify-email-address">Switching Between Reset Password and Verify Email Address&lt;/h4>
&lt;p>Let’s start with the Component for switching between &lt;strong>Reset Password&lt;/strong> and &lt;strong>Confirm Email Address&lt;/strong>. We will start by injecting &lt;code>ActivatedRoute&lt;/code> service into our Component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">activatedActivated&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRoute&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, let&amp;rsquo;s declare a property named mode and assign it the value of Query Parameter &lt;code>mode&lt;/code> from the URL.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">mode&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">activatedActivated&lt;/span>.&lt;span style="color:#a6e22e">snapshot&lt;/span>.&lt;span style="color:#a6e22e">queryParams&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;mode&amp;#39;&lt;/span>];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, in our template, we can use the value of the mode property to either display the &lt;strong>Reset Password Component&lt;/strong> or the &lt;strong>Verify Email Address Component&lt;/strong> using &lt;a href="https://angular.io/api/common/NgSwitch">&lt;code>ng-switch&lt;/code>&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngSwitch&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">action&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- password reset --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchCase&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#39;resetPassword&amp;#39;&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-confirm-password-reset&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-confirm-password-reset&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- verify email address --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchCase&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#39;verifyEmail&amp;#39;&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-confirm-email-address&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-confirm-email-address&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- default action --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchDefault&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!—show an error message --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="confirm-password-reset-code-component">Confirm Password Reset Code Component&lt;/h4>
&lt;p>In this component, we will do two things, first is to request the user to provide enter a new password. And then we will use this password and &lt;code>oobCode&lt;/code> to save the new password. If the &lt;code>oobCode&lt;/code> is valid, the password will be updated successfully, otherwise, it will fail.&lt;/p>
&lt;p>We will start by injecting &lt;code>FormBuilder&lt;/code>, &lt;code>ActivatedRoute&lt;/code>, &lt;code>Router&lt;/code> and AngularFireAuth services into our Component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">afAuth&lt;/span>: &lt;span style="color:#66d9ef">AngularFireAuth&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">fb&lt;/span>: &lt;span style="color:#66d9ef">FormBuilder&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">route&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRoute&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">router&lt;/span>: &lt;span style="color:#66d9ef">Router&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then we will declare a &lt;code>FormGroup&lt;/code> property named &lt;code>frmSetNewPassword&lt;/code>, with new and confirm password form fields:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">frmSetNewPassword&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({
&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>]],
&lt;span style="color:#a6e22e">confirmPassword&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>]]
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, inside our submit method, we will check if the two passwords match:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">password&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">frmSetNewPassword&lt;/span>.&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;password&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">value&lt;/span>;
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">confirmPassword&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">frmSetNewPassword&lt;/span>.&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;confirmPassword&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">value&lt;/span>;
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">password&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#a6e22e">confirmPassword&lt;/span>) {
&lt;span style="color:#75715e">// react to error
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then get the &lt;code>oobCode&lt;/code> from the URL, using the &lt;code>ActivateRoute&lt;/code> service.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">code&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">route&lt;/span>.&lt;span style="color:#a6e22e">snapshot&lt;/span>.&lt;span style="color:#a6e22e">queryParams&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;oobCode&amp;#39;&lt;/span>];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then finally send call the &lt;code>confirmPasswordReset&lt;/code>, passing both the code and new password to update the users password.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">afAuth&lt;/span>.&lt;span style="color:#a6e22e">auth&lt;/span>
.&lt;span style="color:#a6e22e">confirmPasswordReset&lt;/span>(&lt;span style="color:#a6e22e">code&lt;/span>, &lt;span style="color:#a6e22e">password&lt;/span>)
.&lt;span style="color:#a6e22e">then&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#39;signin&amp;#39;&lt;/span>]))
.&lt;span style="color:#66d9ef">catch&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">errorMessage&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">FirebaseErrors&lt;/span>.&lt;span style="color:#a6e22e">Parse&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>.&lt;span style="color:#a6e22e">code&lt;/span>); &lt;span style="color:#75715e">// check this helper class at the bottom
&lt;/span>&lt;span style="color:#75715e">&lt;/span> });
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If successful, we will redirect the user to the sign-in page where they can sign in with their new password, otherwise we will show the error.&lt;/p>
&lt;p>And here is the template for the above form:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">form&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">formGroup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSetNewPassword&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">ngSubmit&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">setPassword&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">h3&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;title is-5 has-text-black&amp;#34;&lt;/span>&amp;gt;
Set a new password
&amp;lt;/&lt;span style="color:#f92672">h3&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">h4&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;subtitle is-6 has-text-grey&amp;#34;&lt;/span>&amp;gt;Please enter and confirm your new password&amp;lt;/&lt;span style="color:#f92672">h4&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;field&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;label&amp;#34;&lt;/span>&amp;gt;Password: &amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;control&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;input &amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;password&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;password&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;password&amp;#34;&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;field&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;label&amp;#34;&lt;/span>&amp;gt;Confirm Password: &amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;control&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;input &amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;password&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;confirmPassword&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;confirmPassword&amp;#34;&lt;/span>&amp;gt;
     &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;has-text-danger&amp;#34;&lt;/span> &amp;gt;
Confirm password is required!
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;field&amp;#34;&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;control&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;button is-fullwidth is-primary&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;submit&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">disabled&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;!&lt;/span>&lt;span style="color:#a6e22e">frmSetNewPassword&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">valid&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;icon&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">fa-icon&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">icon&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">saveIcon&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">fa-icon&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span>&amp;gt;Reset&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">form&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="verify-email-address">Verify Email Address&lt;/h4>
&lt;p>Verifying email addresses is out of the scope for this post, so I won’t go into details. Here is the code snippet to verify user email address:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">code&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">activateRoute&lt;/span>.&lt;span style="color:#a6e22e">snapshot&lt;/span>.&lt;span style="color:#a6e22e">queryParams&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;oobCode&amp;#39;&lt;/span>];
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">afAuth&lt;/span>.&lt;span style="color:#a6e22e">auth&lt;/span>
.&lt;span style="color:#a6e22e">applyActionCode&lt;/span>(&lt;span style="color:#a6e22e">code&lt;/span>)
.&lt;span style="color:#a6e22e">then&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// do something after successful verification
&lt;/span>&lt;span style="color:#75715e">&lt;/span> })
.&lt;span style="color:#66d9ef">catch&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// show error message
&lt;/span>&lt;span style="color:#75715e">&lt;/span> });
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Remember to inject both &lt;code>AngularFireAuth&lt;/code> and &lt;code>ActivatedRoute&lt;/code> services:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">afAuth&lt;/span>: &lt;span style="color:#66d9ef">AngularFireAuth&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">activateRoute&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRoute&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> If you don’t require any user action, you can run the above code &lt;code>OnInit&lt;/code> and show a loading animation.&lt;/p>
&lt;/blockquote>
&lt;h3 id="configure-router">Configure Router&lt;/h3>
&lt;p>And finally, all that is remaining is to configure our Angular Router:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">routes&lt;/span>: &lt;span style="color:#66d9ef">Routes&lt;/span> &lt;span style="color:#f92672">=&lt;/span> [
{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">children&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#75715e">//... Auth Guards For UnAuthenticated Users Here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">children&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> {
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;forgot-password&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">component&lt;/span>: &lt;span style="color:#66d9ef">PasswordResetRequestComponent&lt;/span>,
&lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#f92672">:&lt;/span> { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Forgot Password&amp;#39;&lt;/span> }
}
]
},
{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;email/action&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">component&lt;/span>: &lt;span style="color:#66d9ef">EmailConfirmationComponent&lt;/span>,
&lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#f92672">:&lt;/span> { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Confirm Email Address&amp;#39;&lt;/span> }
}
]
}
];
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="bonus---firebase-auth-errors-parser">Bonus - Firebase Auth Errors Parser&lt;/h3>
&lt;p>Here is a simple helper method for checking errors returned by Firebase Auth:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">FirebaseErrors&lt;/span> {
&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">Parse&lt;/span>(&lt;span style="color:#a6e22e">errorCode&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> {
&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">message&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#66d9ef">switch&lt;/span> (&lt;span style="color:#a6e22e">errorCode&lt;/span>) {
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/wrong-password&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Invalid login credentials.&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/network-request-failed&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Please check your internet connection&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/too-many-requests&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span>
&lt;span style="color:#e6db74">&amp;#39;We have detected too many requests from your device. Take a break please!&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/user-disabled&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span>
&lt;span style="color:#e6db74">&amp;#39;Your account has been disabled or deleted. Please contact the system administrator.&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/requires-recent-login&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Please login again and try again!&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/email-already-exists&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Email address is already in use by an existing user.&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/user-not-found&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span>
&lt;span style="color:#e6db74">&amp;#39;We could not find user account associated with the email address or phone number.&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/phone-number-already-exists&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;The phone number is already in use by an existing user.&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/invalid-phone-number&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;The phone number is not a valid phone number!&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/invalid-email &amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;The email address is not a valid email address!&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth/cannot-delete-own-user-account&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;You cannot delete your own user account.&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">default&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Oops! Something went wrong. Try again later.&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">break&lt;/span>;
}
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">message&lt;/span>;
}
}
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>How to Setup Firebase for Angular</title><link>https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/</link><pubDate>Tue, 20 Aug 2019 16:13:52 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/</guid><description>&lt;p>This is step by step guide about setting up Firebase for your Angular App. This includes using Firebase services from Inside Angular and deploying to Firebase Hosting - optional.&lt;/p>
&lt;amp-youtube data-videoid="O17OWyx08Cg" layout="responsive" width="480" height="270">&lt;/amp-youtube>
&lt;h2 id="prerequisite">Prerequisite&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/">A Firebase Project&lt;/a> – Learn how to create a new Firebase Project&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/">Create an Angular Application&lt;/a> – Learn how to setup Angular CLI and Scaffold a new App.&lt;/li>
&lt;/ul>
&lt;h2 id="get-configs-from-your-firebase-project">Get Configs from your Firebase Project&lt;/h2>
&lt;p>We are going to require some firebase configs that will allow our Angular App to communicate with Firebase. These are unique to each Firebase Project and I am going to show you how to get them for your Firebase project, by following the steps below:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>The first step is to go to the settings of your project. At the bottom of the Projects’ Setting Web Page, you will see a list of “Your Apps” section. If this is a new Firebase project, it will be most likely empty, as shown below.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/2_firebase_app_settings.jpg" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If it’s empty, click on the button highlighted below to create a new Web App and skip to step 5.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/3_firebase_app_create_webapp.jpg" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>If it’s not empty, click on &lt;strong>Add App&lt;/strong> button, on the top left corner of the &lt;strong>Your Apps&lt;/strong> section.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/4_not_empty_app_list.jpg" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>And then click on the button highlighted below to create a new Web App.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/5_not_create_app.jpg" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>In the next step, you will be prompted for the App Nickname and if you would like to host the App using Firebase Hosting, which is optional.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/6_add_firebase_web_app.jpg" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Since we are setting up an Angular App, we are going to skip the next three steps, without doing anything. And in the final step, click on &lt;strong>continue to console&lt;/strong>.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/7_continue_to_console.jpg" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Now you should have at least one app in &lt;strong>Your Apps&lt;/strong> section.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/8_created_web_app.jpg" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Select the app you just created and click on the &lt;strong>config&lt;/strong> radio button to reveals your Web Apps config.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/9_final_configs.jpg" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Copy the above config, as we will need to add them to our Angular App in the next step.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="setup-your-angular-app-to-use-firebase-and-hosting">Setup your Angular App to use Firebase (And Hosting)&lt;/h2>
&lt;h3 id="and-firebase-configs">And Firebase Configs&lt;/h3>
&lt;p>First, inside our environment files (&lt;code>src/environments/*&lt;/code>), we need to add the firebase configs we got above. We will add our Firebase project configs to both &lt;code>src/environment/environment.ts&lt;/code> and &lt;code>src/environment/environment.prod.ts&lt;/code> as shown below:&lt;/p>
&lt;blockquote>
&lt;p>If you don’t know how environment variables work in Angular, check my previous post that covered the topic &lt;a href="https://codinglatte.com/posts/angular/environment-variables-angular/">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#a6e22e">firebase&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">apiKey&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[PROJECT_API_KEY]&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">authDomain&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[PROJECT_AUTH_DOMAIN]&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">databaseURL&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[PROJECT_DB_URL]&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">projectId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[PROJECT_ID]&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">storageBucket&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[STORAGE_BUCKET]&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">messagingSenderId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[MESSAGE_ID]&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">appId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[WEB_APP_ID]&amp;#39;&lt;/span>
}
};
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="install-dependencies-and-enable-hosting">Install Dependencies and Enable Hosting&lt;/h3>
&lt;p>After that, we are going to install &lt;code>@angular/fire&lt;/code> using &lt;a href="https://angular.io/guide/schematics">Angular Schematics&lt;/a> –&lt;code>@angular/fire&lt;/code> is the new name of &lt;code>angularfire2&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng add @angular/fire
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above command is going to install &lt;code>@angular/fire&lt;/code> and then initialize firebase hosting for your Angular App.&lt;/p>
&lt;blockquote>
&lt;p>Please make sure you have install Firebase CLI and logged in, you can follow the instructions &lt;a href="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>You will be prompted to select the Firebase project you are going to deploy your Angular App to.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-setup-firebase-for-angular/images/ng-add-@angular-fire.gif" alt="Hot to Setup Firebase for Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>When the above process completes, both &lt;code>@angular/fire&lt;/code> and related dependencies will be installed, and Firebase hosting will be initialized for our Angular Application.&lt;/p>
&lt;h3 id="import-angularfire-angular-modules">Import &lt;code>@angular/fire&lt;/code> Angular Modules&lt;/h3>
&lt;p>Next, let’s import &lt;code>AngularFireModule&lt;/code> Ng module - this is required to use any Firebase Services.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">BrowserModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/platform-browser&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AngularFireModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/fire&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AppComponent&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app.component&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">environment&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;src/environments/environment&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">AngularFireModule&lt;/span>.&lt;span style="color:#a6e22e">initializeApp&lt;/span>(&lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">firebase&lt;/span>)
],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>On top of &lt;code>AngularFireModule&lt;/code>, we will need to add individual Angular Modules for &lt;code>@angular/fire&lt;/code> that our application needs. Here are list of available modules:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Module&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>AngularFireAuthModule&lt;/td>
&lt;td>Firebase Authentication&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AngularFireDatabaseModule&lt;/td>
&lt;td>Realtime Database&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AngularFireFunctionsModule&lt;/td>
&lt;td>Callable Cloud Firebase Function&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AngularFirestoreModule&lt;/td>
&lt;td>Firebase Cloud Firestore&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AngularFireStorageModule&lt;/td>
&lt;td>Firebase Cloud Storage&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AngularFireMessagingModule&lt;/td>
&lt;td>Firebase Cloud Messaging&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Here is how you can import all of them:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">BrowserModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/platform-browser&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AngularFireModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/fire&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AngularFirestoreModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/fire/firestore&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AngularFireStorageModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/fire/storage&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AngularFireAuthModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/fire/auth&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AngularFireMessagingModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/fire/messaging&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AngularFireDatabaseModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/fire/database&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AngularFireFunctionsModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/fire/functions&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AppComponent&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app.component&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">environment&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;src/environments/environment&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">AngularFireModule&lt;/span>.&lt;span style="color:#a6e22e">initializeApp&lt;/span>(&lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">firebase&lt;/span>),
&lt;span style="color:#a6e22e">AngularFirestoreModule&lt;/span>,
&lt;span style="color:#a6e22e">AngularFireAuthModule&lt;/span>,
&lt;span style="color:#a6e22e">AngularFireStorageModule&lt;/span>,
&lt;span style="color:#a6e22e">AngularFireMessagingModule&lt;/span>,
&lt;span style="color:#a6e22e">AngularFireDatabaseModule&lt;/span>,
&lt;span style="color:#a6e22e">AngularFireFunctionsModule&lt;/span>
],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>How to Set Up Angular CLI for Beginners</title><link>https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/</link><pubDate>Fri, 16 Aug 2019 19:00:20 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/</guid><description>&lt;p>This a step by step guide of setting up Angular CLI. Angular CLI is a first-party CLI tool that helps developers to create, build and deploy applications among other things. It makes the process of building Angular apps easier by handling the most repetitive tasks on your behalf. This allows you to concentrate on building your application rather than setting up webpack among other things.&lt;/p>
&lt;h2 id="prerequisites">Prerequisites&lt;/h2>
&lt;ul>
&lt;li>NodeJS and NPM – To install Angular CLI, we are going to need both NodeJS and NPM installed in our system. The process varies in different OSs, but you can find the instructions on how to install NodeJS &lt;a href="https://nodejs.org/en/">here&lt;/a>. NPM is bundled with NodeJS, so you don’t have to worry about that.
Once you have NodeJS installed, you can verify whether it&amp;rsquo;s working by running &lt;code>node -v&lt;/code> on your CLI/Terminal application. This should echo the version of NodeJS you just installed. You can do the same with NPM - &lt;code>node -v&lt;/code> - which should echo the version of NPM installed on your system.&lt;/li>
&lt;/ul>
&lt;h2 id="installing-angular-cli">Installing Angular CLI&lt;/h2>
&lt;p>Next, let’s install Angular CLI globally using NPM.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install -g @angular/cli
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Once the process is done, you can verify if Angular CLI was installed successfully by running &lt;code>ng version&lt;/code> command. This should output the version of Angular CLI, NodeJS and Operating System, as shown below.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/images/ng-version-screen-shot.png" alt="Angular Version CLI Output" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Since you are not inside an Angular Project, the version of the package will return errors. Don’t panic, it&amp;rsquo;s normal.&lt;/p>
&lt;/blockquote>
&lt;h2 id="create-a-new-angular-project">Create a New Angular Project&lt;/h2>
&lt;p>Next, let’s create a new Angular application using Angular CLI. You do this by running &lt;code>ng new&lt;/code> command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng new project-name
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After you run that application, you will be prompted for two things:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Whether you want to enable routing – this will setup Angular powerful router for you.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Which stylesheet you would like to use for your project – &lt;code>CSS&lt;/code>, &lt;code>SCSS&lt;/code>, etc.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can choose the defaults and change them later as your application requirement evolves using Angular CLI.&lt;/p>
&lt;/blockquote>
&lt;p>Once the above process of scaffolding a new application is complete, switch to the directory and run the scaffolded application, using &lt;code>ng serve&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">cd project-name
ng serve
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can view the web app on your browser by accessing localhost on port 4200 – &lt;a href="http://localhost:4200">http://localhost:4200&lt;/a>.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/images/scaffold_app_angular.png" alt="How to Set Up Angular CLI for Beginners" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div></description></item><item><title>How to Create a Firebase Project</title><link>https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/</link><pubDate>Fri, 16 Aug 2019 09:05:25 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/</guid><description>&lt;p>This is a step by step how to guide to show you how to create a new Firebase project.&lt;/p>
&lt;p>First, visit Firebase Console using this visiting the following URL - &lt;a href="https://console.firebase.google.com/">https://console.firebase.google.com&lt;/a>. Login using your Google Account - if you are not already logged in.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_1_firebase_console_page.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>Then, create a new project, enter the name of the project and click continue.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_2_create_project.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>In the next step, you will be asked whether to set up Google Analytics. Let’s go ahead and set it up.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_3_setup_google_analytics.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;blockquote>
&lt;p>If you don’t need Google Analytics, select “Not at The Moment” option. You can always set it up later.&lt;/p>
&lt;/blockquote>
&lt;p>If you are not setting up Google Analytics, skips the next 3 steps. In the next step, you will be prompted to either select or create a Google Analytics Account. If you already have a Google Analytics account, click on Select Google Account and select the account.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_4_select%20google_analytics_account_LI.jpg" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>If you don’t have one, click on create a new one and enter the name of the account.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_5_create_google_analytics_account.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>Finally, select the Google Analytics Location – default United States – and finally, read and configure Data-sharing settings. Finally, accept Google Analytics Terms and Create Project.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_6_create_project.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>The process should take just a few seconds, once done click continue and you will be taken to projects homepage.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_7_app_home.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;h3 id="change-public-facing-app-name">Change Public-facing App Name&lt;/h3>
&lt;p>Lastly, change the public-facing name of your firebase app to something more friendly.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>First, Go to the settings of your Firebase Application.
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_8_settings.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>And then Under &lt;code>Public Settings&lt;/code>, change the Public-facing name and add a support email address:
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_10_change_public_facing_email.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Click on the edit button next to the public-facing name to change the name
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/how-to/how-to-create-a-firebase-project/resources/step_9_change%20name.png" alt="Firebase Console Homepage" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Save the changes and you are done.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="install-firebase-cli">Install Firebase CLI&lt;/h3>
&lt;blockquote>
&lt;p>“The Firebase CLI (&lt;a href="https://github.com/firebase/firebase-tools">GitHub&lt;/a>) provides a variety of tools for managing, viewing, and deploying to Firebase projects.”&lt;/p>
&lt;/blockquote>
&lt;ul>
&lt;li>
&lt;p>Firebase CLI requires both &lt;a href="https://nodejs.org/en/">NodeJS&lt;/a> and &lt;a href="https://www.npmjs.org/">NPM&lt;/a>. You can install Node by using Node Version Manager (NVM) for &lt;a href="https://github.com/creationix/nvm/blob/master/README.md">Mac/Linux&lt;/a> or &lt;a href="https://github.com/coreybutler/nvm-windows">Windows&lt;/a>. You can also download and install the version of Node directly from their website &lt;a href="https://nodejs.org/en/">here&lt;/a>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Next, install Firebase CLI using the following command:&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install -g firebase-tools
&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>Once the process is complete, Sign in to Firebase by running &lt;code>firebase login&lt;/code>. Make sure to sign in with the same Google account you used to create the Firebase Project above.&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">firebase login
&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>You can test if &lt;code>firebase login&lt;/code> worked by running &lt;code>firebase list&lt;/code>. This is going list projects you have in your Firebase Account.&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">firebase list
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Flutter and GraphQL - How to Upload Files</title><link>https://codinglatte.com/posts/flutter/flutter-and-graphql-how-to-upload-files/</link><pubDate>Mon, 12 Aug 2019 11:21:33 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/flutter/flutter-and-graphql-how-to-upload-files/</guid><description>&lt;p>In this post, I am going to show you how to upload files using GraphQL and flutter. To work with GraphQL in flutter, we are going to use &lt;a href="https://github.com/zino-app/graphql-flutter">graphql_flutter&lt;/a> package, which has over 1000 stars on GitHub and I frequently contribute to.&lt;/p>
&lt;p>So, without further ado, let’s get started.&lt;/p>
&lt;h3 id="our-graphql-schema">Our GraphQL Schema&lt;/h3>
&lt;p>To upload files, we are going to use a very simple schema. Our mutation will accept a file and then return a download URL for the file. We won’t look at the implementation at the server end.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-graphql" data-lang="graphql">&lt;span style="color:#66d9ef">scalar&lt;/span> &lt;span style="color:#a6e22e">Upload&lt;/span>
&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">Mutation&lt;/span> {
upload(file: &lt;span style="color:#a6e22e">Upload&lt;/span>!): &lt;span style="color:#a6e22e">String&lt;/span>!
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> If you are interested, you can find the GraphQL Server for this articles&amp;rsquo; demo &lt;a href="https://github.com/mainawycliffe/flutter-graphql-upload-example/tree/master/backend">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h3 id="demo-and-source-code">Demo and Source Code&lt;/h3>
&lt;p>Here is how our app will work:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/flutter/flutter-and-graphql-how-to-upload-files/demo.gif" alt="Flutter and Graphql - How to Upload Files" width="264px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>You can find the accompanying repo for this article on &lt;a href="https://github.com/mainawycliffe/flutter-graphql-upload-example">here on GitHub&lt;/a>.&lt;/p>
&lt;h3 id="dependencies-and-imports">Dependencies and Imports&lt;/h3>
&lt;p>For this articles&amp;rsquo; demo, we are going to need the following dependencies for our flutter project – &lt;a href="https://github.com/zino-app/graphql-flutter">graphql_flutter&lt;/a> and &lt;a href="https://pub.dev/packages/image_picker">image_picker&lt;/a>.&lt;/p>
&lt;p>Let’s add them to our projects &lt;code>pubspec&lt;/code> file.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">graphql_flutter&lt;/span>: ^&lt;span style="color:#ae81ff">2.0.0&lt;/span>
&lt;span style="color:#66d9ef">image_picker&lt;/span>: ^&lt;span style="color:#ae81ff">0.6.0&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And we are going to import the following packages:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;dart:io&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;package:flutter/material.dart&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;package:graphql_flutter/graphql_flutter.dart&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;package:http/http.dart&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;package:http_parser/http_parser.dart&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;package:image_picker/image_picker.dart&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Feel free to add any extra dependencies and imports to make your UI look better.&lt;/p>
&lt;h3 id="about-our-demo-application">About our Demo Application&lt;/h3>
&lt;p>For this article&amp;rsquo; demo, we are going to use the &lt;a href="https://pub.dev/packages/image_picker">image_picker&lt;/a> package to pick an image. Then, the picked image can then be uploaded to our server. We are going to build a very simplistic UI for our demo application, where we will have a simple button to pick an image. And when an image is picked, it shall be displayed inside an Image widget, and an upload button revealed. The user can then click the upload button to upload the image.&lt;/p>
&lt;p>First, let’s define our GraphQL Mutation – &lt;code>uploadImage&lt;/code> – which will accept variable called &lt;code>$file&lt;/code> of type &lt;code>Upload&lt;/code>. The &lt;code>$file&lt;/code> variable will be the image selected using the image_picker and will be passed to the &lt;code>upload&lt;/code> mutation.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">const&lt;/span> uploadImage &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">r&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;span style="color:#e6db74">mutation($file: Upload!) {
&lt;/span>&lt;span style="color:#e6db74"> upload(file: $file)
&lt;/span>&lt;span style="color:#e6db74">}
&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, inside our &lt;code>StatefulWidget&lt;/code>, let’s add a &lt;code>selectImage&lt;/code> method and a private &lt;a href="https://api.flutter.dev/flutter/dart-io/File-class.html">File&lt;/a> property called &lt;code>_image&lt;/code>. When the &lt;code>select image&lt;/code> method is called, it is going to call the &lt;code>ImagePicker.pickImage&lt;/code> method, showing a file picker dialog, where a user picks an image. After a user selects an image, we are going to set the &lt;code>_image&lt;/code> property to the resulting file (image).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">Future selectImage() &lt;span style="color:#66d9ef">async&lt;/span> {
&lt;span style="color:#66d9ef">var&lt;/span> image &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">await&lt;/span> ImagePicker.pickImage(&lt;span style="color:#66d9ef">source&lt;/span>&lt;span style="color:#f92672">:&lt;/span> ImageSource.gallery);
setState(() {
_image &lt;span style="color:#f92672">=&lt;/span> image;
});
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let&amp;rsquo;s create our UI using:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#960050;background-color:#1e0010">@&lt;/span>override
Widget build(BuildContext context) {
&lt;span style="color:#66d9ef">return&lt;/span> Container(
child: Column(
&lt;span style="color:#75715e">// mainAxisAlignment: MainAxisAlignment.center,
&lt;/span>&lt;span style="color:#75715e">&lt;/span> mainAxisSize: MainAxisSize.max,
children: &lt;span style="color:#f92672">&amp;lt;&lt;/span>Widget&lt;span style="color:#f92672">&amp;gt;&lt;/span>[
&lt;span style="color:#66d9ef">if&lt;/span> (_image &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>)
Flexible(
flex: &lt;span style="color:#ae81ff">9&lt;/span>,
child: Image.file(_image),
)
&lt;span style="color:#66d9ef">else&lt;/span>
Flexible(
flex: &lt;span style="color:#ae81ff">9&lt;/span>,
child: Center(
child: Text(&lt;span style="color:#e6db74">&amp;#34;No Image Selected&amp;#34;&lt;/span>),
),
),
Flexible(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: &lt;span style="color:#f92672">&amp;lt;&lt;/span>Widget&lt;span style="color:#f92672">&amp;gt;&lt;/span>[
FlatButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: &lt;span style="color:#f92672">&amp;lt;&lt;/span>Widget&lt;span style="color:#f92672">&amp;gt;&lt;/span>[
Icon(Icons.photo_library),
SizedBox(
width: &lt;span style="color:#ae81ff">5&lt;/span>,
),
Text(&lt;span style="color:#e6db74">&amp;#34;Select File&amp;#34;&lt;/span>),
],
),
onPressed: () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> selectImage(),
),
&lt;span style="color:#75715e">// Mutation Widget Here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
),
)
],
),
);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, we are just missing is the GraphQL Upload Implementation. There are two approaches for this, and we will look at each below:&lt;/p>
&lt;h3 id="using-the-mutation-widget">Using the &lt;code>Mutation&lt;/code> Widget&lt;/h3>
&lt;p>&lt;code>graphql_flutter&lt;/code> package provides some easy to use widgets that you can drop inside your flutter app. One of these widgets is the Mutation widget which you can use to run mutation. But before using the &lt;code>Mutation&lt;/code> widget, we are going to need a &lt;a href="https://pub.dev/documentation/graphql/latest/graphql/GraphQLClient-class.html">GraphQLClient&lt;/a>. The &lt;a href="https://pub.dev/documentation/graphql/latest/graphql/GraphQLClient-class.html">GraphQLClient&lt;/a> needs to be provided somewhere up our widget tree, preferably at the very beginning.&lt;/p>
&lt;p>You can achieve this by creating a &lt;a href="https://pub.dev/documentation/graphql/latest/graphql/GraphQLClient-class.html">GraphQLClient&lt;/a> and then pass it down the widget tree using the &lt;a href="https://pub.dev/documentation/graphql_flutter/latest/#graphql-provider">&lt;code>GraphQLProvider&lt;/code>&lt;/a> widget. First, lets create a &lt;a href="https://pub.dev/documentation/graphql/latest/graphql/GraphQLClient-class.html">GraphQLClient&lt;/a> wrapped with &lt;a href="https://api.flutter.dev/flutter/foundation/ValueNotifier-class.html">ValueNotifier&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">final&lt;/span> httpLink &lt;span style="color:#f92672">=&lt;/span> HttpLink(
uri: &lt;span style="color:#e6db74">&amp;#39;http://&lt;/span>&lt;span style="color:#e6db74">$&lt;/span>host&lt;span style="color:#e6db74">:8080/query&amp;#39;&lt;/span>,
);
&lt;span style="color:#66d9ef">var&lt;/span> client &lt;span style="color:#f92672">=&lt;/span> ValueNotifier(
GraphQLClient(
cache: InMemoryCache(),
link: httpLink,
),
);
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> The host points to localhost, which is different between IOS and Android emulator:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">String&lt;/span> &lt;span style="color:#66d9ef">get&lt;/span> host &lt;span style="color:#f92672">=&amp;gt;&lt;/span> Platform.isAndroid &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#e6db74">&amp;#39;10.0.2.2&amp;#39;&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;localhost&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to pass down the above client down the widget tree using the &lt;a href="https://pub.dev/documentation/graphql_flutter/latest/#graphql-provider">&lt;code>GraphQLProvider&lt;/code>&lt;/a> widget. In our case, we are going to wrap the Scaffold widget with it, you can also wrap the MaterialApp with if you so wish.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">return&lt;/span> MaterialApp(
title: &lt;span style="color:#e6db74">&amp;#39;Flutter Demo&amp;#39;&lt;/span>,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: GraphQLProvider(
client: client,
child: Scaffold(
appBar: AppBar(
title: Text(&lt;span style="color:#e6db74">&amp;#34;Graphql Upload Image Demo&amp;#34;&lt;/span>),
),
body: MyHomePage(),
),
),
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we are ready to use the Mutation widget. To use the Mutation widget, you just need to pass &lt;code>MutationOptions&lt;/code>, a Widget Builder method and an &lt;code>onCompleted&lt;/code> and/or update callbacks. The last two callbacks are called when a mutation is completed. With &lt;code>onCompleted&lt;/code> callback passing the resulting data from the mutation results. While the &lt;code>update&lt;/code> passing the &lt;a href="https://pub.dev/documentation/graphql/latest/graphql/QueryResult-class.html">QueryResults&lt;/a> object which you can use to check for errors.&lt;/p>
&lt;p>To use the Mutation widget, we are going to add it next to the select image button. We are going to also check whether the &lt;code>_image&lt;/code> property is set before displaying the widget.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">if&lt;/span> (_image &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>)
Mutation(
options: MutationOptions(
document: uploadImage,
),
builder: (RunMutation runMutation, QueryResult result) {
&lt;span style="color:#66d9ef">return&lt;/span> FlatButton(
child: _isLoadingInProgress(),
onPressed: () {},
);
},
onCompleted: (d) {},
update: (cache, results) {},
),
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The Mutation widget is going to return an upload button, which a user can press to upload the image. Let’s implement the &lt;code>onPressed&lt;/code> method of the button so that it will upload the image when pressed. First, we are going to prepare the image for uploading by converting it into a &lt;a href="https://pub.dev/documentation/http/latest/http/MultipartFile-class.html">&lt;code>MultipartFile&lt;/code>&lt;/a>. Then, we can pass the resulting &lt;a href="https://pub.dev/documentation/http/latest/http/MultipartFile-class.html">MultipartFile&lt;/a> variable as the variable for our Mutation, when calling the &lt;code>runMutation&lt;/code> method passed from the builder.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">var&lt;/span> byteData &lt;span style="color:#f92672">=&lt;/span> _image.readAsBytesSync();
&lt;span style="color:#66d9ef">var&lt;/span> multipartFile &lt;span style="color:#f92672">=&lt;/span> MultipartFile.fromBytes(
&lt;span style="color:#e6db74">&amp;#39;photo&amp;#39;&lt;/span>,
byteData,
filename: &lt;span style="color:#e6db74">&amp;#39;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>DateTime.now().second&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">.jpg&amp;#39;&lt;/span>,
contentType: MediaType(&lt;span style="color:#e6db74">&amp;#34;image&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;jpg&amp;#34;&lt;/span>),
);
runMutation(&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">String&lt;/span>, &lt;span style="color:#66d9ef">dynamic&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>{
&lt;span style="color:#e6db74">&amp;#34;file&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> multipartFile,
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then we can use the update call-back to check if the upload has been completed successfully and show a response.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">update: (cache, results) {
&lt;span style="color:#66d9ef">var&lt;/span> message &lt;span style="color:#f92672">=&lt;/span> results.hasErrors
&lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>results.errors.join(&lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&lt;/span>
&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Image was uploaded successfully!&amp;#34;&lt;/span>;
&lt;span style="color:#66d9ef">final&lt;/span> snackBar &lt;span style="color:#f92672">=&lt;/span> SnackBar(content: Text(message));
Scaffold.of(context).showSnackBar(snackBar);
},
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it when a GraphQL operation completes successfully, a success message is going to be displayed, else the resulting error message will be displayed using a &lt;a href="https://flutter.dev/docs/cookbook/design/snackbars">snackbar&lt;/a>.&lt;/p>
&lt;h3 id="without-using-the-mutation-widgets">Without using the Mutation Widgets&lt;/h3>
&lt;p>There a lot of people who don’t like using the Mutation widget for various reasons. You can also do that with the graphql_flutter. We are going to replace the Mutation widget above, with a simple button, which will call a method – &lt;code>_uploadImage&lt;/code> – when pressed. We are going to place the &lt;code>_uploadImage&lt;/code> method inside our StatefulWidget.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">if&lt;/span> (_image &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>)
FlatButton(
child: _isLoadingInProgress(),
onPressed: () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> _uploadImage(context),
),
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then inside our &lt;code>_uploadImage&lt;/code> method, we are going to first convert the image to a &lt;code>MultipartFile&lt;/code> just like we did before.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">var&lt;/span> byteData &lt;span style="color:#f92672">=&lt;/span> _image.readAsBytesSync();
&lt;span style="color:#66d9ef">var&lt;/span> multipartFile &lt;span style="color:#f92672">=&lt;/span> MultipartFile.fromBytes(
&lt;span style="color:#e6db74">&amp;#39;photo&amp;#39;&lt;/span>,
byteData,
filename: &lt;span style="color:#e6db74">&amp;#39;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>DateTime.now().second&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">.jpg&amp;#39;&lt;/span>,
contentType: MediaType(&lt;span style="color:#e6db74">&amp;#34;image&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;jpg&amp;#34;&lt;/span>),
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then create &lt;a href="https://pub.dev/documentation/graphql/latest/graphql/MutationOptions-class.html">MutationOptions&lt;/a> variable for our mutation, passing the document and the multipart file above.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">var&lt;/span> opts &lt;span style="color:#f92672">=&lt;/span> MutationOptions(
document: uploadImage,
variables: {
&lt;span style="color:#e6db74">&amp;#34;file&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> multipartFile,
},
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, create our GraphQLClient:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">final&lt;/span> httpLink &lt;span style="color:#f92672">=&lt;/span> HttpLink(
uri: &lt;span style="color:#e6db74">&amp;#39;http://&lt;/span>&lt;span style="color:#e6db74">$&lt;/span>host&lt;span style="color:#e6db74">:8080/query&amp;#39;&lt;/span>,
);
&lt;span style="color:#66d9ef">var&lt;/span> client &lt;span style="color:#f92672">=&lt;/span> GraphQLClient(
cache: InMemoryCache(),
link: httpLink,
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, run the mutation by calling &lt;code>client.Mutation&lt;/code> function which returns a &lt;code>Future&lt;/code> of &lt;a href="https://pub.dev/documentation/graphql/latest/graphql/QueryResult-class.html">QueryResults&lt;/a>, which you can use to show the final response:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">var&lt;/span> results &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">await&lt;/span> client.mutate(opts);
&lt;span style="color:#66d9ef">var&lt;/span> message &lt;span style="color:#f92672">=&lt;/span> results.hasErrors
&lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>results.errors.join(&lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&lt;/span>
&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Image was uploaded successfully!&amp;#34;&lt;/span>;
&lt;span style="color:#66d9ef">final&lt;/span> snackBar &lt;span style="color:#f92672">=&lt;/span> SnackBar(content: Text(message));
Scaffold.of(context).showSnackBar(snackBar);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>With this you can use it with scope models, BLoCs or any state management solution you comfortable with.&lt;/p>
&lt;h4 id="tip">TIP&lt;/h4>
&lt;blockquote>
&lt;p>If you are not interested in using the &lt;a href="https://pub.dev/packages/graphql_flutter">flutter_graphql&lt;/a> widgets, you can instead directly use the &lt;a href="https://pub.dev/packages/graphql">graphql&lt;/a> package, which is the core of the &lt;a href="https://pub.dev/packages/graphql_flutter">flutter_graphql&lt;/a> and are both maintained by the same &lt;a href="https://github.com/zino-app/graphql-flutter">team&lt;/a>.&lt;/p>
&lt;/blockquote></description></item><item><title>How to Add Async Validators to an Angular Reactive Form</title><link>https://codinglatte.com/posts/angular/how-to-add-async-validators-to-an-angular-reactive-form/</link><pubDate>Mon, 22 Jul 2019 01:00:00 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/how-to-add-async-validators-to-an-angular-reactive-form/</guid><description>&lt;p>Occasionally, you may want to validate form input against data that is available asynchronous source i.e. a HTTP backend. For instance, checking if a username or email address exists before form submission. In Angular, you achieve this using Async Validators, which we are going to look at in this post.&lt;/p>
&lt;p>We are going to build a simple reactive form. It will contain a single form field called username. Then, whenever the user enters their username, we are going to check if it exists and return the response. If the username exists, then the form shall report the following error – &lt;code>The username is already taken.&lt;/code>, as shown below.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/how-to-add-async-validators-to-an-angular-reactive-form/demo.gif" alt="How to Add Async Validators to an Angular Reactive Form" width="400px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>Full demo &lt;a href="https://mainawycliffe.github.io/angular-async-validator/">here&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>If you are new to Reactive Forms in Angular, please refer to this guide &lt;a href="https://angular.io/guide/reactive-forms">here&lt;/a> on getting started.&lt;/p>
&lt;/blockquote>
&lt;p>Without further ado, let’s get started.&lt;/p>
&lt;h3 id="prerequisite">Prerequisite&lt;/h3>
&lt;p>I am going to skip the process of setting up a new Angular Project. Once you have your Angular project setup, in your app module, you will need to import &lt;code>ReactiveFormsModule&lt;/code> from &lt;code>@angular/forms&lt;/code>. This is the only module we require to use Reactive Forms inside our angular application.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">ReactiveFormsModule&lt;/span>
],
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, lets add a method for looking up username methods.&lt;/p>
&lt;h3 id="username-lookup-method">Username Lookup Method&lt;/h3>
&lt;p>First, we are going to add a method to check whether the user’s username exists. In a normal application, this is where you would make a HTTP request to your backend API – either a REST, a GraphQL API etc. But for the purpose of this post, we are going to simulate a HTTP request using &lt;a href="http://reactivex.io/documentation/operators/delay.html">RXJS Delay Operator&lt;/a>. This will delay our responses by about one second and return an observable just like a HTTP request in Angular.&lt;/p>
&lt;p>To achieve this, we are going to create an array of taken usernames - &lt;code>takenUsernames&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">takenUsernames&lt;/span> &lt;span style="color:#f92672">=&lt;/span> [
&lt;span style="color:#e6db74">&amp;#39;hello&amp;#39;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#39;world&amp;#39;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#39;username&amp;#39;&lt;/span>
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then given a username, we are going to determine if it exists within the array using array includes method. After that, whatever the results, we will then delay the response for about a second and return the results as a boolean Observable – &lt;code>Observables&amp;lt;boolean&amp;gt;&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">checkIfUsernameExists&lt;/span>(&lt;span style="color:#a6e22e">username&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">takenUsernames&lt;/span>.&lt;span style="color:#a6e22e">includes&lt;/span>(&lt;span style="color:#a6e22e">username&lt;/span>)).&lt;span style="color:#a6e22e">pipe&lt;/span>(&lt;span style="color:#a6e22e">delay&lt;/span>(&lt;span style="color:#ae81ff">1000&lt;/span>));
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="adding-an-async-validator">Adding an Async Validator&lt;/h3>
&lt;p>Next up, we are going to create our async validator. To create this, we just need to implement the &lt;a href="https://angular.io/api/forms/AsyncValidatorFn">&lt;code>AsyncValidatorFn&lt;/code>&lt;/a> interface. To implement the &lt;code>AsyncValidatorFN&lt;/code> interface, you need a method that receives a form control class (AKA &lt;a href="https://angular.io/api/forms/AbstractControl">&lt;code>AbstractControl&lt;/code>&lt;/a>) as a parameter. The method then needs to return a promise or an observable of &lt;code>ValidationErrors&lt;/code> or &lt;code>null&lt;/code>. If there are any errors, the method returns &lt;code>ValidationErrors&lt;/code>, otherwise it just returns null.&lt;/p>
&lt;p>A &lt;code>ValidationErrors&lt;/code> is an another interface, which is just a &lt;a href="https://angular.io/api/forms/ValidationErrors">key value map&lt;/a> of all errors thrown, as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">type&lt;/span> &lt;span style="color:#a6e22e">ValidationErrors&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
[&lt;span style="color:#a6e22e">key&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span>;
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For instance, our error for this posts demo shall look something like this &lt;code>{ usernameExists: true }&lt;/code>. The key of the returned error allows you to check for specific errors on your form and display them to the user. This allows you to give a more precise feedback to the user instead of generic feedback.&lt;/p>
&lt;blockquote>
&lt;p>Please note, when there are no errors, you should always return null. If you don’t return null, your Angular Form will be in an invalid state. This could have some undesired side effects.&lt;/p>
&lt;/blockquote>
&lt;p>In our method to check for errors, we will map the boolean response from &lt;code>checkIfUsernameExists&lt;/code> method above to a &lt;code>ValidationErrors&lt;/code> or null response. It will return null if false and a &lt;code>ValidationErrors&lt;/code> object if true.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">usernameValidator&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">AsyncValidatorFn&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> (&lt;span style="color:#a6e22e">control&lt;/span>: &lt;span style="color:#66d9ef">AbstractControl&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">ValidationErrors&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">checkIfUsernameExists&lt;/span>(&lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>).&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// if res is true, username exists, return true
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">?&lt;/span> { &lt;span style="color:#a6e22e">usernameExists&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> } &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#75715e">// NB: Return null if there is no error
&lt;/span>&lt;span style="color:#75715e">&lt;/span> })
);
};
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We will tack the above method inside our username lookup service.&lt;/p>
&lt;h3 id="adding-async-validators-to-our-reactive-form">Adding Async Validators to Our Reactive Form&lt;/h3>
&lt;p>Now that we have a full working service, we need to use the async validator we just created above. This is a simple matter of adding the array of async validators, after synchronous validators, as shown below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({
&lt;span style="color:#a6e22e">username&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#66d9ef">null&lt;/span>, [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>], [&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">usernameService&lt;/span>.&lt;span style="color:#a6e22e">usernameValidator&lt;/span>()]
]
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Remember to inject the &lt;code>usernameLookupService&lt;/code> into the component you are using it in.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">fb&lt;/span>: &lt;span style="color:#66d9ef">FormBuilder&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">usernameService&lt;/span>: &lt;span style="color:#66d9ef">UsernameValidationService&lt;/span>) {
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="ui-implementation">UI Implementation&lt;/h3>
&lt;p>And finally, inside your template, you can check if the form has errors. You can check if a form field has an validation error inside the template as shown below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">frmAsyncValidator&lt;/span>.&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;username&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">errors&lt;/span>&lt;span style="color:#f92672">?&lt;/span>.&lt;span style="color:#a6e22e">usernameExists&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This returns true if there is an error, else it is undefined, hence the use of &lt;a href="https://angular.io/guide/template-syntax#safe-navigation-operator">&lt;code>safe navigation operator (?)&lt;/code>&lt;/a>. And here is the full template for our form:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">form&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">formGroup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmAsyncValidator&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;field has-text-left&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;label&amp;#34;&lt;/span>&amp;gt;Username &amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;{&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">is-loading&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">:&lt;/span>
&lt;span style="color:#a6e22e">frmAsyncValidator&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">username&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">pending&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">}&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;control&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;{&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">is-danger&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">:&lt;/span> &lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">username&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;,&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)}&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;username&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;input is-focused&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;username&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Your username&amp;#34;&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;has-text-danger&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;frmAsyncValidator.controls[&amp;#39;username&amp;#39;].errors?.usernameExists&amp;#34;&lt;/span>&amp;gt;
This username is already taken!
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">form&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="a-note-on-performance">A Note on Performance&lt;/h3>
&lt;p>Currently as we have implemented our async validator, it runs on form value changes. For sync validators, you will likely never notice any performance impact. For async validators however, this can have some undesired side effects. This is because you will most likely be sending HTTP requests to some sort of backend for validation. Running validation on form value changes can end up straining the backend with too many requests.&lt;/p>
&lt;p>For this reason, you can change your validators to run &lt;code>onBlur&lt;/code>, instead of on form value changes. You can achieve this by adding the &lt;code>updateOn&lt;/code> property to &lt;code>{ updateOn: 'blur' }&lt;/code> for either an individual form control or the entire form:&lt;/p>
&lt;p>This is how you can set &lt;code>{ updateOn: ‘blur’ }&lt;/code> property for an entire form:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({&lt;span style="color:#75715e">/** field here */&lt;/span>}, { &lt;span style="color:#a6e22e">updateOn&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;blur&amp;#39;&lt;/span> });
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And this is how you do it for an individual form control:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">username&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#66d9ef">null&lt;/span>,
{
&lt;span style="color:#a6e22e">validators&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>],
&lt;span style="color:#a6e22e">asyncValidators&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">usernameService&lt;/span>.&lt;span style="color:#a6e22e">usernameValidator&lt;/span>()],
&lt;span style="color:#a6e22e">updateOn&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;blur&amp;#39;&lt;/span>
}
]
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="conclusion">Conclusion&lt;/h3>
&lt;p>That’s it for me in this post, you can find the code for this posts example &lt;a href="https://github.com/mainawycliffe/angular-async-validator">here&lt;/a> on GitHub. If you have any questions/issue/suggestion, feel free to use the comment section below. You can also join me on my new Slack channel &lt;a href="https://forms.gle/PdD4RcAS8kK6TMbF9">here&lt;/a> or on &lt;a href="https://twitter.com/mwycliffe_dev">Twitter @mwycliffe_dev&lt;/a> where am available to help in any way I can.&lt;/p>
&lt;p>Thank you.&lt;/p></description></item><item><title>Flutter - A Closer Look at How Pub Handles Dependency Versions</title><link>https://codinglatte.com/posts/flutter/flutter-a-closer-look-at-how-pub-handles-dependency-versions/</link><pubDate>Wed, 10 Jul 2019 15:14:56 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/flutter/flutter-a-closer-look-at-how-pub-handles-dependency-versions/</guid><description>&lt;p>In this post, I want to look closely at how dart pub handles dependency versions. The end goal is to help you understand how to manage your flutter dependencies versions with some finesse. So, without further ado, let’s get started.&lt;/p>
&lt;h3 id="how-dart-pub-handles-dependencies">How Dart Pub Handles Dependencies&lt;/h3>
&lt;p>Dart package manager (PUB) doesn’t allow multiple versions of the same dependency. Instead, it uses version constraints to give you flexibility in situations where you have two dependencies you are depending on depend on different versions of the same a dependency.&lt;/p>
&lt;p>This means that, instead of having a specific version of a dependency, you will instead specify a range of versions that can work with your application or library. For instance, if two dependencies require the same but different versions of a dependency. Then using version constraints increases the chances that the specified version ranges will overlap. The latest version where both two packages version requirement overlap is used.&lt;/p>
&lt;p>For instance, Let’s say you have two dependencies. Where the first dependency depends on &lt;code>package-x&lt;/code> with version range of &lt;code>1.3 to 1.8&lt;/code>. While the second dependency depended on the same &lt;code>package-x&lt;/code> but between version &lt;code>1.6 to 2.0&lt;/code>. In this case, dart package manager would install version &lt;code>1.7.x&lt;/code>, where x is the latest patch version. This is because it’s the latest version that both dependencies depend on.&lt;/p>
&lt;p>This works well in a perfect world. But the world we live in is anything but perfect. There are some cases where you might find that your dependencies version ranges don’t overlap. In such cases and &lt;a href="https://dart.dev/tools/pub/versioning#when-things-go-wrong">other similar cases&lt;/a>, you might have to choose one dependency over the other.&lt;/p>
&lt;p>This is just an overview of how dart pub package works, you find detailed documentation &lt;a href="https://dart.dev/tools/pub/versioning">here&lt;/a>.&lt;/p>
&lt;h3 id="semantic-versioning">Semantic Versioning&lt;/h3>
&lt;p>In order to use version constraints, you need to know which future versions of your dependencies won’t break your app or library. This is where Semantic versioning come in. Semantic versions provide guidelines on how dependencies are upgraded. With Semantic versioning, a dependency version is in the form of X.Y.Z where X is the major version, Y is the minor version and Z is the patch version. For more information, check the full documentation on semantic versions &lt;a href="https://semver.org/spec/v2.0.0-rc.1.html">here&lt;/a>.&lt;/p>
&lt;p>With Semantic versioning, when a backward compatible feature is added to the public API, then the minor version is incremented. If a non-backward compatible feature is added to the public API, then the major version is incremented. And the patch version is incremented only when bug fixes which are backward compatible are introduced.&lt;/p>
&lt;p>With that in mind, you can specify the version constraints of your dependencies for your library and application full knowing that a minor or parch version won’t break anything. You can learn more about Semantic versions &lt;a href="https://semver.org/spec/v2.0.0-rc.1.html">here&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Pub uses version 2.0.0-rc.1 of semantic versioning which allow packages to use build identifies to differentiate different versions. This is why you can come across dependency versions looking like this &lt;code>X.Y.Z+12345&lt;/code>.
&lt;strong>NB:&lt;/strong> When the major version is at zero – i.e. &lt;code>0.1.5&lt;/code> – dart convention defers slightly from semantic versioning. Instead, the X.Y.Z interpretation above is shifted down a slot. This makes Y behave like the major version, and Z like the minor version.
In order to indicate the patch version, then a build identifier is used i.e. &lt;code>0.Y.Z+1&lt;/code>. This behaves the same as the patch version.
This is because, prior to version 1.0.0, semantic versioning does not promise compatibility between versions. Dart on the other hand offers promise of version compatibility between different versions.&lt;/p>
&lt;/blockquote>
&lt;h3 id="types-of-dependencies">Types of Dependencies&lt;/h3>
&lt;p>Pub supports two types of dependencies – regular and dev. Dev dependencies are those dependencies that are not part of your application or library but rather used for development workflow. For instance, test dependencies – &lt;code>mockito&lt;/code> or &lt;code>tests&lt;/code> – for running tests or generators dependency for generating PODOs for your application. Regular dependency are dependencies that are used inside your application and library – i.e. they are kind of important for your application to run.&lt;/p>
&lt;h3 id="how-to-add-dependencies-to-your-application">How to add Dependencies to your Application&lt;/h3>
&lt;p>You add your dependencies in the &lt;code>pubspec&lt;/code> file – located at the root of your application. This is automatically generated when creating a new flutter application. Regular dependencies are added under &lt;code>dependencies&lt;/code> field while dev dependencies are listed under &lt;code>dev_dependencies&lt;/code> field. You can learn more about fields of a&lt;code>pubspec&lt;/code> file &lt;a href="https://dart.dev/tools/pub/pubspec">here&lt;/a>.&lt;/p>
&lt;p>To add a dependency in dart, you simply specify the name of the dependency and the version you want to use.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">dependencies&lt;/span>:
&lt;span style="color:#66d9ef">flutter&lt;/span>:
&lt;span style="color:#66d9ef">sdk&lt;/span>: flutter
&lt;span style="color:#66d9ef">font_awesome_flutter&lt;/span>: &lt;span style="color:#ae81ff">8.4.0&lt;/span>
&lt;span style="color:#66d9ef">bloc&lt;/span>: &lt;span style="color:#ae81ff">0.14.4&lt;/span>
&lt;span style="color:#66d9ef">flutter_bloc&lt;/span>: &lt;span style="color:#ae81ff">0.18.3&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For an application with few dependencies, you can specify an exact version and manually update as new versions get released. On the other hand, you might want to use version constraints to get the latest package without manually updating your &lt;code>pubspec&lt;/code> file. Because dart uses semantic versioning, it is easy to predict up to which future version of a dependency you can use inside your application without breaking anything.&lt;/p>
&lt;p>In case you are developing a dart/flutter library, version constraints are highly recommended. As we discussed above, it gives your library high chance of compatibility with other libraries that an app developer is using.&lt;/p>
&lt;p>To specify version constraints, you use the &lt;code>greater than (&amp;gt;)&lt;/code>, &lt;code>less than (&amp;lt;)&lt;/code>, &lt;code>greater than or equal to (&amp;gt;=)&lt;/code> and &lt;code>less than or equal to (&amp;lt;=)&lt;/code> symbols as shown below:&lt;/p>
&lt;ol>
&lt;li>&lt;code>&amp;gt;=1.0.0&lt;/code> – any version that is greater or equal to &lt;code>1.0.0&lt;/code> – i.e. &lt;code>bloc: &amp;gt;=0.14.4&lt;/code>.&lt;/li>
&lt;li>&lt;code>&amp;gt;1.0.0&lt;/code> – any version greater than &lt;code>1.0.0&lt;/code> – i.e. &lt;code>bloc: &amp;gt;1.0.0&lt;/code>.&lt;/li>
&lt;li>&lt;code>&amp;lt;=1.0.0&lt;/code> – any version less than or equal to 1.0.0 i.e. &lt;code>bloc: &amp;lt;=1.0.0&lt;/code> – This sets the upper limit of the version to install as version 1 and any version lower than that.&lt;/li>
&lt;li>&lt;code>&amp;lt;1.0.0&lt;/code> – any version less than 1.0.0 i.e. &lt;code>bloc: &amp;lt;1.0.0&lt;/code> – This basically does the same as the above except it excludes version 1.0.0.&lt;/li>
&lt;li>&lt;code>any&lt;/code> – any version of that dependency – not recommended for performance reasons. The same as leaving the version section empty, but more explicit.&lt;/li>
&lt;/ol>
&lt;p>On top of that, you can also combine the above versions constraints to provide an upper and lower limit for a dependency. For instance: &lt;code>bloc: '&amp;gt;=1.0.0 &amp;lt; 2.0.0'&lt;/code> which limits the versions for your bloc package to between 1 and less than two. This is recommended especially for libraries.&lt;/p>
&lt;h4 id="caret-syntax-version">Caret Syntax (&lt;code>^version&lt;/code>)&lt;/h4>
&lt;p>You may have come across this, where a dependency version is specified with a caret before it – &lt;code>^version&lt;/code>. This provides a simple way of expressing common version constraints discussed above. When using the caret syntax, you are setting the version constraints to be greater or equal to the listed version, but less than the next major version. You simply don’t want a version with breaking changes being installed. For instance, &lt;code>^1.2.3&lt;/code> is the equivalent of &lt;code>&amp;gt;=1.2.3 &amp;lt;2.0.0&lt;/code> while &lt;code>^0.1.2&lt;/code> is equivalent of &lt;code>&amp;gt;=0.1.2 &amp;lt;0.2.0&lt;/code>.&lt;/p>
&lt;h3 id="tips">TIPs&lt;/h3>
&lt;p>For libraries, it is recommended not to commit the dependency &lt;code>lockfile&lt;/code>. For applications on the other hand, you should commit the dependency &lt;code>lockfile&lt;/code>. The reason for committing the &lt;code>lockfile&lt;/code> for applications is to ensure that all developers are working on exact the same version of dependencies. The &lt;code>lockfile&lt;/code> is only updated when you upgrade dependencies (&lt;code>flutter pub upgrade&lt;/code>) but not when you get packages (&lt;code>flutter pub get&lt;/code>). You can learn more &lt;a href="https://dart.dev/guides/libraries/private-files">here&lt;/a> about what to commit and not to commit.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>Libraries are the biggest beneficiaries for using version constraints. If you maintain a flutter/dart library, you should switch to version constraints if you haven’t already. For application, I also think using version constraints is beneficial.&lt;/p>
&lt;p>For instance, you might want to have minor and patch versions of a dependency installed when available, without having to manually track them yourself. This allows you to run the &lt;code>flutter pub upgrade&lt;/code> and it will update the dependency versions in the&lt;code>lockfile&lt;/code> within version constraints on the &lt;code>pubspec&lt;/code> file.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> For flutter applications, you should not use &lt;code>pub get&lt;/code> or &lt;code>pub upgrade&lt;/code> commands to manage yours apps dependencies. Instead, you should use &lt;code>flutter pub get&lt;/code> or &lt;code>flutter pub upgrade&lt;/code>.&lt;/p>
&lt;/blockquote>
&lt;p>That’s it from me, if you have any question or any criticism, use the comment section below. You can also follow me on &lt;a href="https://twitter.com/mwycliffe_dev">twitter&lt;/a> or join my &lt;a href="https://forms.gle/PdD4RcAS8kK6TMbF9">slack workspace&lt;/a>. I offer help whenever I can.&lt;/p>
&lt;p>Thank you.&lt;/p></description></item><item><title>Customizing Angular App Behavior per Build Environment</title><link>https://codinglatte.com/posts/angular/customizing-angular-app-behavior-per-build-environment/</link><pubDate>Tue, 02 Jul 2019 08:33:02 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/customizing-angular-app-behavior-per-build-environment/</guid><description>&lt;p>If you have used angular for even a brief period, you probably have come across the environment configuration files. By default, they are two of them – one for production and another for development. They allow you to specify configs or settings that are unique to a specific deployment environment. This may include configs such as the URL API Endpoint or even Firebase Configs for the said environment.&lt;/p>
&lt;p>For instance, Angular uses the &lt;code>prod&lt;/code> property from environment variables to enable the Service Worker when true – i.e. in production deployment only.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#a6e22e">ServiceWorkerModule&lt;/span>.&lt;span style="color:#a6e22e">register&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;ngsw-worker.js&amp;#39;&lt;/span>, {
&lt;span style="color:#a6e22e">enabled&lt;/span>: &lt;span style="color:#66d9ef">environment.production&lt;/span>
}),
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can also build on this, so that you can have even more configs for different target environment. For instance – &lt;code>development&lt;/code>, &lt;code>staging&lt;/code> and &lt;code>production&lt;/code>. To learn more about mastering environment configurations, checkout my previous &lt;a href="https://codinglatte.com/posts/angular/environment-variables-angular/">post&lt;/a> here.&lt;/p>
&lt;p>In this post, we are going to take environment specific configurations a bit further. We are going to see how we can customize not only the variables but styles, scripts, assets and even classes. In order to do this, you will need to be comfortable tinkering with the &lt;code>angular.json&lt;/code> – the config file your angular &lt;a href="https://angular.io/guide/workspace-config">workspace&lt;/a>.&lt;/p>
&lt;h3 id="why">Why&lt;/h3>
&lt;p>For most project, including most of mine, the default Angular CLI configs work out of the box, with no or minimal need for any customization.&lt;/p>
&lt;p>But, from time to time, you may need to customize the behaviour of your angular application based on the environment you are building it for. For instance, you may want to have a different theme, logo etc. for your alpha, beta and production environments – enabling your users/testers to easily identify which environment they are in.&lt;/p>
&lt;p>In such a case you could have different colors for your different environments, while also correcting more telemetry information on the pre-release versions as compared to the stable release, where most of users will be.&lt;/p>
&lt;p>So, without further ado, let’s get started:&lt;/p>
&lt;h3 id="customizing-styles-and-scripts">Customizing Styles and Scripts&lt;/h3>
&lt;p>By default, if you have some global styles and scripts for your web app, you can add them to the styles array.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;projects&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;angular-extreme-build-configuration&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;builder&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;@angular-devkit/build-angular:browser&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;styles&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;styles1.scss&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;styles2.scss&amp;#34;&lt;/span>,
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
],
&lt;span style="color:#f92672">&amp;#34;scripts&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;script1.json&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;script2.json&amp;#34;&lt;/span>,
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
]
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will and other configuration you make in this section will act as default configuration for all build environment (i.e. prod, serve, staging) you have setup for your app. But what we want in our case, is to set different styles for different environment we are targeting.&lt;/p>
&lt;p>To achieve this, we are going to pass a different set of styles and scripts for each environment. You do this by adding the styles and scripts properties under the environment you want to. Each property accepts an array of file paths relative to the root of the angular workspace.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;projects&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;angular-extreme-build-configuration&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;styles&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;src/styles.scss&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">default&lt;/span>
],
&lt;span style="color:#f92672">&amp;#34;scripts&amp;#34;&lt;/span>: []
},
&lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;staging&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;styles&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;src/styles.staging.scss&amp;#34;&lt;/span>
],
&lt;span style="color:#f92672">&amp;#34;scripts&amp;#34;&lt;/span>: []
},
&lt;span style="color:#f92672">&amp;#34;production&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;styles&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;src/styles.prod.scss&amp;#34;&lt;/span>
],
&lt;span style="color:#f92672">&amp;#34;scripts&amp;#34;&lt;/span>: []
}
}
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Any environment, that you don’t configure the scripts and styles for, will fall-back to the default. So, you can add the default scripts and styles, then configure the specific environment you want to be different.&lt;/p>
&lt;/blockquote>
&lt;p>For instance, if you were using bootstrap or any other CSS framework, you can theme your web app differently based on the environment. This gives you the freedom to customize the look and feel of your web app across multiple target environments. You can have a production web app that looks completely different from staging, yet the underlying code is largely the same.&lt;/p>
&lt;p>Checkout the demo &lt;a href="https://github.com/mainawycliffe/angular-extreme-build-configuration">here&lt;/a>, to see this in action.&lt;/p>
&lt;h3 id="unique-assets-for-different-target-environments">Unique Assets for Different Target Environments&lt;/h3>
&lt;p>Just like Assets and Scripts above, you can also provide a list of assets for your app. Basically, this are files that are not part of your app code. When you specify them, Angular CLI will then copy them as they are, to the build directory during build time. This is suitable for things like logos, icons etc.&lt;/p>
&lt;p>By default, you specify individual images or directory and Angular will copy them as they are, relative to the root of angular workspace.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;projects&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;angular-extreme-build-configuration&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;assets&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;src/favicon.ico&amp;#34;&lt;/span>,
&lt;span style="color:#e6db74">&amp;#34;src/assets&amp;#34;&lt;/span>
],
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will not work very well for multi environment configuration. In such situations, you can provide more instruction to angular cli on how to copy assets for a specific environment. Instead of a simple path to the file or directory, you can specify a field with the following fields:&lt;/p>
&lt;ol>
&lt;li>&lt;code>glob&lt;/code> - This specifies the file pattern to copy, uses the input directory as the base&lt;/li>
&lt;li>&lt;code>input&lt;/code> - The input directory, relative to the angular workspace&lt;/li>
&lt;li>&lt;code>output&lt;/code> - The output directory, relative to the build directory&lt;/li>
&lt;li>&lt;code>ignore&lt;/code> - the list of globs to ignore in the input directory&lt;/li>
&lt;/ol>
&lt;p>Take this scenario, you have two build environments, staging and production, each with a unique asset. First, you create two directories, one for production assets – &lt;code>prod_assets&lt;/code> and the other for staging assets – &lt;code>staging_assets&lt;/code>. During build for each of this configuration, you need the prod and staging assets copied over to the &lt;code>assets&lt;/code> directory in the build directory.&lt;/p>
&lt;p>In this case, your staging assets configuration would look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;projects&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;angular-extreme-build-configuration&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;staging&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;assets&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;src/favicon.ico&amp;#34;&lt;/span>,
{
&lt;span style="color:#f92672">&amp;#34;glob&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;**/*&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/staging_assets/&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;output&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/assets/&amp;#34;&lt;/span>
}
],
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
}&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the production configuration would look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;projects&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;angular-extreme-build-configuration&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;production&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;assets&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;src/favicon.ico&amp;#34;&lt;/span>,
{
&lt;span style="color:#f92672">&amp;#34;glob&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;**/*&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/prod_assets/&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;output&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/assets/&amp;#34;&lt;/span>
}
],
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
},
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
}&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="using-file-replacement-for-typescript-classes">Using File Replacement for Typescript Classes&lt;/h3>
&lt;p>The configs for File replacement allow you to instruct Angular CLI to replace a specific file with another before building your web app. For instance, you could replace a typescript class with another class – provided the properties and methods required are available in both – depending on your build target environment.&lt;/p>
&lt;p>In fact, Angular CLI uses this to replace the default &lt;code>environment.ts&lt;/code> file with &lt;code>environment.prod.ts&lt;/code> when building with the &lt;code>--prod&lt;/code> flag. The setting accepts an array of objects, which means you can have multiple file replacement. The object has two properties – replace and with, where the first is the file to replace, and the latter is the path to the replacement file.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;fileReplacements&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
{
&lt;span style="color:#f92672">&amp;#34;replace&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;path/for/file/to/replace&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;with&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;path/for/file/to/replace/with&amp;#34;&lt;/span>
}
]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let’s take this scenario, you have two logging classes, during development, you just want to log to console. But during production you want to log to a logging service – remotely. You could create two classes or services – &lt;code>logging.ts&lt;/code> and &lt;code>logging.prod.ts&lt;/code> - and having angular CLI replace the default class with the production class when building for production.&lt;/p>
&lt;p>To achieve this, under &lt;code>fileReplacements&lt;/code> for production configuration, you just need to specify which file to replace and the replacement file, as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;production&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
&lt;span style="color:#f92672">&amp;#34;fileReplacements&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;replace&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/app/logging.ts&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;with&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/app/logging.prod.ts&amp;#34;&lt;/span>
}
],
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>I know that is a bit of a stretch using file replacement like that, but I didn’t have a better idea and you still get the point.&lt;/p>
&lt;p>That’s it from me on this topic for now. If you have any more ideas on build configuration customization, use the comment section below, it will be helpful to me and future readers of this post.&lt;/p>
&lt;p>All the source code for this post can be found on &lt;a href="https://github.com/mainawycliffe/angular-extreme-build-configuration">GitHub&lt;/a>. If you have any question for me, feel free to use the comment section below or shoot me a message on &lt;a href="https://forms.gle/PdD4RcAS8kK6TMbF9">Slack&lt;/a>.&lt;/p></description></item><item><title>Flutter Building a Bottom Navigation Bar with "Flutter_Bloc"</title><link>https://codinglatte.com/posts/flutter/flutter-building-bottomnavigationbar-with-flutter-bloc/</link><pubDate>Thu, 28 Mar 2019 08:59:02 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/flutter/flutter-building-bottomnavigationbar-with-flutter-bloc/</guid><description>&lt;p>I was in the middle implementing a BottomNavigationBar, when a thought crossed mind. Can I use bloc pattern to manage its state? Admittedly, it&amp;rsquo;s not the most brilliant idea, not even close to one, but I thought it was a very good way to improve my understanding of the bloc pattern. So, when I was done, I decided to create my first ever post on flutter.&lt;/p>
&lt;h3 id="introduction">Introduction&lt;/h3>
&lt;p>This what we are building:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/flutter/flutter-building-bottomnavigationbar-with-flutter-bloc/bottom_navbar_bloc_sm.gif" alt="Blocs BottomNavigationBar Demo" width="300px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>To achieve this, we are going to be using the &lt;a href="https://pub.dartlang.org/packages/flutter_bloc">flutter_bloc&lt;/a> package, which depends on &lt;a href="https://pub.dartlang.org/packages/bloc">core&lt;/a> bloc package. The goal of the bloc package is to simplify the implementation of the bloc pattern, by reducing the amount of boilerplate required. It has a package wrapper for both flutter and angular dart, allowing you to share your business logic between your flutter app and web app (AngularDart).&lt;/p>
&lt;p>If you are unfamiliar with bloc concepts, please learn more &lt;a href="https://felangel.github.io/bloc/#/coreconcepts">here&lt;/a> before you can continue, this will make it easier for you to follow this post.&lt;/p>
&lt;p>Let’s get started:&lt;/p>
&lt;h3 id="dependencies">Dependencies&lt;/h3>
&lt;p>For this project, we are going to require at least the following dependencies:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Bloc – &lt;a href="https://pub.dartlang.org/packages/bloc">Link&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>flutter_bloc – &lt;a href="https://pub.dartlang.org/packages/flutter_bloc">Link&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Feel free to add any other dependencies to fit your projects needs. Assuming you have successfully installed the above dependencies, let’s start coding:&lt;/p>
&lt;p>To implement a bloc for a BottomNavigationBar, we are going to need 3 things: Events, State and a Bloc.&lt;/p>
&lt;p>Let’s start by implementing events:&lt;/p>
&lt;h3 id="events">Events&lt;/h3>
&lt;p>We are going to start by defining our events. In our case, we are going to have just 3 &lt;strong>BottomNavigationBarItems&lt;/strong>, each display a different color when clicked. As such we are going to define 3 events, each representing each of &lt;strong>BottomNavigationBarItems&lt;/strong>. This seems perfect for an enum with our three constants, for each BottomNavigationBarItem:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">enum NavbarItems { Red, Green, Blue }
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="state">State&lt;/h3>
&lt;p>Now that we have our bloc events constants, we need to create a state for each of the &lt;strong>BottomNavigationBarItems&lt;/strong>. But first, we let’s create a state for &lt;strong>BottomNavigationBar&lt;/strong>, then the other 3 states will extend it – the parent state.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">abstract&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">NavbarState&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, for each of our items states, we shall hold the Scaffold Widgets title and its &lt;strong>BottomNavigationBarItems&lt;/strong> index. This will allows us to highlight the active item and set the page title.&lt;/p>
&lt;p>For instance, for our &lt;code>ShowRed&lt;/code> state, it will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ShowRed&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> NavbarState {
&lt;span style="color:#66d9ef">final&lt;/span> &lt;span style="color:#66d9ef">String&lt;/span> title &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Red&amp;#34;&lt;/span>;
&lt;span style="color:#66d9ef">final&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> itemIndex &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the same applies to our other two states:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#75715e">// ShowBlue State
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ShowBlue&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> NavbarState {
&lt;span style="color:#66d9ef">final&lt;/span> &lt;span style="color:#66d9ef">String&lt;/span> title &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Blue&amp;#34;&lt;/span>;
&lt;span style="color:#66d9ef">final&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> itemIndex &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
}
&lt;span style="color:#75715e">// ShowGreen State
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ShowGreen&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> NavbarState {
&lt;span style="color:#66d9ef">final&lt;/span> &lt;span style="color:#66d9ef">String&lt;/span> title &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Green&amp;#34;&lt;/span>;
&lt;span style="color:#66d9ef">final&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> itemIndex &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it for our state, next let’s build our bloc.&lt;/p>
&lt;h3 id="bloc">Bloc&lt;/h3>
&lt;p>Our bloc will simply map events to states. For instance, our Red event will be mapped to the &lt;code>ShowRed&lt;/code> state and so on. Let’s define our bloc, which will extend the bloc class, which takes in events and maps it to a state. So, for our case, we will be mapping NavbarItems events we defined above to the NavbarState, our parent state.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">NavbarBloc&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> Bloc&lt;span style="color:#f92672">&amp;lt;&lt;/span>NavbarItems, NavbarState&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// object code here ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, inside our bloc, let’s add an initial state – which will be the default selected item. This is done by using the &lt;code>initialState&lt;/code> method. The &lt;code>initialState&lt;/code> method is triggered before any event has been dispatched. For our case, the initial state will be &lt;code>ShowRed&lt;/code> state;&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#960050;background-color:#1e0010">@&lt;/span>override
NavbarState &lt;span style="color:#66d9ef">get&lt;/span> initialState &lt;span style="color:#f92672">=&amp;gt;&lt;/span> ShowRed();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we must define a &lt;code>mapEventToState&lt;/code> method inside our bloc. This is triggered each time an event is dispatched, for instance, clicking on a &lt;strong>BottomNavigationBarItem&lt;/strong>. The method accepts the current state and the event that triggered it and streams the current state. Then inside the presentation layer, you can listed to this stream and react accordingly.&lt;/p>
&lt;p>In our case, we only have 3 events – &lt;code>Red&lt;/code>, &lt;code>Blue&lt;/code> and &lt;code>Green&lt;/code>. So, we will map them to the appropriate state. For instance, when the event that was dispatched was &lt;code>Red&lt;/code>, then will map that to the &lt;code>ShowRed&lt;/code> state and so on. To achieve this, we will use a simple switch case:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#960050;background-color:#1e0010">@&lt;/span>override
Stream&lt;span style="color:#f92672">&amp;lt;&lt;/span>NavbarState&lt;span style="color:#f92672">&amp;gt;&lt;/span> mapEventToState(NavbarState state, NavbarItems event) &lt;span style="color:#66d9ef">async&lt;/span>&lt;span style="color:#f92672">*&lt;/span> {
&lt;span style="color:#66d9ef">switch&lt;/span> (event) {
&lt;span style="color:#66d9ef">case&lt;/span> NavbarItems.Blue:
&lt;span style="color:#66d9ef">yield&lt;/span> ShowBlue();
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">case&lt;/span> NavbarItems.Green:
&lt;span style="color:#66d9ef">yield&lt;/span> ShowGreen();
&lt;span style="color:#66d9ef">break&lt;/span>;
&lt;span style="color:#66d9ef">default&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;span style="color:#66d9ef">yield&lt;/span> ShowRed();
&lt;span style="color:#66d9ef">break&lt;/span>;
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it for our bloc. Now let’s move to the presentation layer:&lt;/p>
&lt;h3 id="presentation">Presentation&lt;/h3>
&lt;p>Next, let’s build our User Interface. We are going to wrap our scaffold widget with a &lt;code>BlocBuilder&lt;/code>, so we can be able to change the title, body and set selected item index.&lt;/p>
&lt;p>First, let’s define a local variable for our bloc:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">NavbarBloc _navbarBloc;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, on state initialization, lets set our bloc variable from above to the &lt;strong>BottomNavigationBar&lt;/strong> Bloc:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#960050;background-color:#1e0010">@&lt;/span>override
&lt;span style="color:#66d9ef">void&lt;/span> initState() {
&lt;span style="color:#66d9ef">super&lt;/span>.initState();
_navbarBloc &lt;span style="color:#f92672">=&lt;/span> NavbarBloc();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, we need to be able to dispose of our bloc, when the stateful widget is disposed:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#960050;background-color:#1e0010">@&lt;/span>override
&lt;span style="color:#66d9ef">void&lt;/span> dispose() {
_navbarBloc.dispose();
&lt;span style="color:#66d9ef">super&lt;/span>.dispose();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we are going to use &lt;code>BlocBuilder&lt;/code> to provide our &lt;code>BottomNavigationBar&lt;/code> bloc above to build our UI based on the selected state. But first, to make things a tad bit easier, lets create a method to build our Scaffold widget. Let’s call it &lt;code>buildHomepage&lt;/code>, and will accept &lt;code>title&lt;/code>, &lt;code>color&lt;/code> and &lt;code>currentIndex&lt;/code>. And it is going to return a Scaffold widget.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">Scaffold buildHomepage(&lt;span style="color:#66d9ef">String&lt;/span> title, Color color, &lt;span style="color:#66d9ef">int&lt;/span> currentIndex) {
&lt;span style="color:#66d9ef">return&lt;/span> Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
color: color,
child: Center(
child: Text(title),
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
onTap: (index) {
&lt;span style="color:#75715e">// on tap method here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> },
items: [
BottomNavigationBarItem(
icon: Icon(Icons.looks_one),
title: Text(&lt;span style="color:#e6db74">&amp;#34;Red&amp;#34;&lt;/span>),
),
BottomNavigationBarItem(
icon: Icon(Icons.looks_two),
title: Text(&lt;span style="color:#e6db74">&amp;#34;Blue&amp;#34;&lt;/span>),
),
BottomNavigationBarItem(
icon: Icon(Icons.looks_3),
title: Text(&lt;span style="color:#e6db74">&amp;#34;Green&amp;#34;&lt;/span>),
)
],
),
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, we can use the &lt;code>BlocBuilder&lt;/code> to provide our bloc in order to build the UI based on the selected &lt;strong>BottomNavigationBar&lt;/strong> state:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#960050;background-color:#1e0010">@&lt;/span>override
Widget build(BuildContext context) {
&lt;span style="color:#66d9ef">return&lt;/span> BlocBuilder(
bloc: _navbarBloc,
builder: (BuildContext context, NavbarState state) {
&lt;span style="color:#75715e">// check state and show appropriate content here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> },
);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, inside the builder method, we will check which is the current state and show the appropriate content. For instance, when the state is &lt;code>ShowRed&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">if&lt;/span> (state &lt;span style="color:#66d9ef">is&lt;/span> ShowRed)
&lt;span style="color:#66d9ef">return&lt;/span> buildHomepage(state.title, Colors.red, state.itemIndex);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the same applies to the other two states:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">&lt;span style="color:#66d9ef">if&lt;/span> (state &lt;span style="color:#66d9ef">is&lt;/span> ShowBlue)
&lt;span style="color:#66d9ef">return&lt;/span> buildHomepage(state.title, Colors.blue, state.itemIndex);
&lt;span style="color:#66d9ef">if&lt;/span> (state &lt;span style="color:#66d9ef">is&lt;/span> ShowGreen)
&lt;span style="color:#66d9ef">return&lt;/span> buildHomepage(state.title, Colors.green, state.itemIndex);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, the only thing that’s remaining is to dispatch the actions whenever a &lt;strong>BottomNavigationBarItem&lt;/strong> is tapped, using the &lt;code>onTap&lt;/code> event listener:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dart" data-lang="dart">onTap: (index) {
&lt;span style="color:#66d9ef">if&lt;/span> (index &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>) _navbarBloc.dispatch(NavbarItems.Red);
&lt;span style="color:#66d9ef">if&lt;/span> (index &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>) _navbarBloc.dispatch(NavbarItems.Blue);
&lt;span style="color:#66d9ef">if&lt;/span> (index &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>) _navbarBloc.dispatch(NavbarItems.Green);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it, you now have a BottomNavigationBar that uses bloc pattern to keep track of the selected items. You can find the whole source code &lt;a href="https://github.com/coding-latte/bottom-navbar-with-bloc-flutter">here&lt;/a>.``&lt;/p></description></item><item><title>Golang – Building a Graphql Server (Part 1)</title><link>https://codinglatte.com/posts/golang/golang-building-a-graphql-server-part-1/</link><pubDate>Mon, 25 Mar 2019 03:50:00 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/golang/golang-building-a-graphql-server-part-1/</guid><description>&lt;p>Over the last 3 months, I have been involved on a project where I ended up building a GraphQL Server using Go. Before this, I had not worked on GraphQL before, on either frontend or backend. In this post, I would like to focus on two things: First, why I decided to use GraphQL over REST. And secondly, the Go Libraries that can help you build a graphql server from the grounds up.&lt;/p>
&lt;p>This is going to be the first of a series of posts, in which am going to share my experiences on various aspects of building a GraphQL Server. I hope there will be at least three more posts with more technical details on how to solve and approach various issues that I came across.&lt;/p>
&lt;h3 id="why-i-chose-graphql">Why I chose GraphQL&lt;/h3>
&lt;p>The main reason, at least for me, was over fetching and under fetching. GraphQL allows the client to define exactly the data it needs from the server. The server will then return only that information. Let’s say a client needs a customer contact details, it will just get that and not more or less.&lt;/p>
&lt;p>This is very difficult to achieve on REST, you will most likely end up returning related data on a request based on your best guess on what a client might need. Basically, contact details would also have other customer data that the client might not need at that specific time.&lt;/p>
&lt;p>In simple terms, graphql allows you to treat your backend like a database that you can query for information you need and get exactly that.&lt;/p>
&lt;p>Other reasons are:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Strongly Typed – graphql clients know exactly the data types to expect.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Acts as a single source of truth as proxy in front of your various end points or microservices.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Easy and Self Documentation, especially when combined GraphiQL. Updated automatically when you make changes.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h3 id="graphql-with-go--which-library-to-use">GraphQL with Go – Which Library to use&lt;/h3>
&lt;p>There are 4 main contenders for you to choose from, with each taking some sort of different approach to building GraphQL servers in go. Let’s have a brief look at them:&lt;/p>
&lt;blockquote>
&lt;p>Disclaimer: I have only had first-hand experience with the first and the last of the libraries below, information on the other 3 is mostly from my research.&lt;/p>
&lt;/blockquote>
&lt;h4 id="1-graphql-gographql">1. graphql-go/graphql&lt;/h4>
&lt;p>This is one of the most popular graphql library in this list. With this library, GraphQL types and schema are defined inside your go code. Well, this leads to a lot of boilerplate. You will notice that each of this library take a different approach on how you define schema and types creation. It was my first attempt at building a graphql server and worked very well.&lt;/p>
&lt;p>The main reason why I switched to gqlgen, was that it doesn’t handle circular reference very well. And won’t event compile if there is one. There is a work around though which I didn’t find very intuitive for me, this may change in the future though.&lt;/p>
&lt;p>Boilerplate aside, use this if you don’t mind your GraphQL schema and types definition living inside your go code. &lt;a href="https://github.com/graphql-go/graphql">Here&lt;/a> is a link to the GitHub repository.&lt;/p>
&lt;h4 id="2-graph-gophersgraphql-go">2. graph-gophers/graphql-go&lt;/h4>
&lt;p>This is one of the two schema first graphql libraries for go. Being schema first, simply means that you write your schema in schema definition language and have go parse it. As far as I can tell, it doesn’t use a generator or at least it’s not mandatory. This library aims to provide support for graphql draft specification with easy to use go APIs.&lt;/p>
&lt;p>&lt;a href="https://github.com/graph-gophers/graphql-go">Here&lt;/a> is a link to the GitHub repository.&lt;/p>
&lt;h4 id="3-samsarahqthunder">3. samsarahq/thunder&lt;/h4>
&lt;p>This is unlike any other library in this list, because it’s structs first and aimed to be a framework for rapid graphql server development. Being struct first means, you basically define your schema as structs, following all the rules of structs of exported fields. This will then generate resolvers automatically from Go struct types and function definitions. It also offers special go structs tags to give you more control on field names and which fields to skip.&lt;/p>
&lt;p>One thing to keep in mind is that while it has been used in house production at samsarahq, it’s still in development and breaking changes may be introduced. &lt;a href="https://github.com/samsarahq/thunder">Here&lt;/a> is a link to the GitHub repository.&lt;/p>
&lt;h4 id="4-99designsgqlgen">4. 99designs/gqlgen&lt;/h4>
&lt;p>This is a schema first and type safe graphql library. Unlike &lt;code>graph-gophers/graphql-go&lt;/code> from above, after writing your schema and types, you need to run the gqlgen code generator. The generator will then generate all necessary go files (boring bits) that you need to build your graphql server. The resolver file is only generated initially, but the &lt;code>models.go&lt;/code> and &lt;code>generated.go&lt;/code> files are regenerated every time to reflect your changes, and you shouldn’t edit them.&lt;/p>
&lt;p>This allows you to bring over your schema from let’s say Apollo server and it will automatically generate all the resolvers for you. Then it’s a matter of writing resolver to your code. It is also very configurable, giving you options to re-use your models from the database, specify which struct tags to use, split up your schema files into multiple files etc. This configurations are placed inside a &lt;code>gqlgen.yaml&lt;/code> file.&lt;/p>
&lt;p>On top of that, Gqlgen is the most feature rich library in this list, as of the time of writing this. This is the library I ended up using and we are going focus more on it over the next few posts. Below, is a feature comparison from all four graphql libraries (it was created by gqlgen).&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/golang/golang-building-a-graphql-server-part-1/graphql-libraries-feature-comparison.jpg" alt="Golang – Building a Graphql Server" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>You can find the official documentation of gqlgen &lt;a href="https://github.com/99designs/gqlgen">here&lt;/a>.&lt;/p></description></item><item><title>Working With Assets and Global Styles and Scripts in Angular</title><link>https://codinglatte.com/posts/angular/working-with-assets-styles-and-scripts-in-angular/</link><pubDate>Mon, 25 Feb 2019 00:40:50 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/working-with-assets-styles-and-scripts-in-angular/</guid><description>&lt;p>In this post, we are going to take a closer look at how we to work with assets (web assets) and global styles and scripts on our angular project. The three (Assets, Styles and Scripts) cover all the resources you might need for your Angular app. We will cover common scenarios in which you might come across while working with web resources for your project.&lt;/p>
&lt;p>So, without further ado, let’s get started:&lt;/p>
&lt;h3 id="working-with-assets">Working with Assets&lt;/h3>
&lt;p>Let’s start with assets, this could be anything from images, videos, json files to styles and scripts. By default, Angular has an asset directory, located under the &lt;code>/src&lt;/code> directory at the root of your angular project. This is copied over to the build directory by Angular CLI during the build process of your app. If you have some images, you can simply drop them in to this directory. Then, just reference to them as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">img&lt;/span> &lt;span style="color:#a6e22e">src&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/assets/image.png&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span> /&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can even drop a directory with assets inside the assets’ directory, and everything will be copied as is.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">img&lt;/span> &lt;span style="color:#a6e22e">src&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/assets/images/image.jpg&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span> /&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And if you don’t want to use the assets directory, Angular got you covered here as well. You can configure Angular CLI to automatically copy a file or directory over to the build directory by adding those files to the assets array inside &lt;code>angular.json&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;projects&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;project-name&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;assets&amp;#34;&lt;/span>: [
&lt;span style="color:#e6db74">&amp;#34;src/favicon.ico&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">default&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;src/assets&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">//default&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Add&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">more&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">assets&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">here&lt;/span>
]
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>By default, there are two files in the assets array, the &lt;code>assets&lt;/code> directory and &lt;code>favicon.ico&lt;/code> file, as show above. You can add your own assets, relative to the root of your &lt;a href="https://codinglatte.com/posts/angular/angular-6-angular-cli-workspaces/">Angular workspace&lt;/a>. The above assets will apply to both development and production builds of your app.&lt;/p>
&lt;p>But if you wanted, you can also have different assets for each deployment &lt;a href="https://codinglatte.com/posts/angular/environment-variables-angular/">environment&lt;/a> in Angular too. For instance, if you had a different logo for each build environment, you might want the logo to be copied in the same exact location, in each environment, to make it easier to reference to it.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">img&lt;/span> &lt;span style="color:#a6e22e">src&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;path/to/logo&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span> /&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To achieve this, you can use the objects for assets configurations, instead of a simple path string shown above. Inside this object you need to specify the following properties:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;glob&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;pattern of files to copy (can include a filename)&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;ignore&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;files to ignore&amp;#34;&lt;/span>],
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;path to directory in which the assets are&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;output&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;directory to copy assets to (inside build directory)&amp;#34;&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For instance, if you wanted a different set of assets for productions, you just need to add the assets array, with necessary assets:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;projects&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;project-name&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;production&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;fileReplacements&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;replace&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.ts&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;with&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.prod.ts&amp;#34;&lt;/span>
}
],
&lt;span style="color:#f92672">&amp;#34;assets&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;glob&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;**/*&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">copy&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">everything&lt;/span>
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/prod/assets&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;output&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/assets/&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;glob&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;favicon.ico&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">copy&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">only&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">favicon.ico&lt;/span>
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/prod&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;output&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">copy&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">to&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">root&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">directory&lt;/span>
}
]
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
}
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
}
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> By adding an assets array for a specific build environment i.e. production, Angular CLI will ignore all assets specified for all environments and use only those specified for that environment only.&lt;/p>
&lt;/blockquote>
&lt;h3 id="local-global-styles-and-scripts">Local Global Styles and Scripts&lt;/h3>
&lt;p>In the previous section we were focusing on general assets, but let’s now focus only on stylesheets and scripts. By default, Angular CLI adds an empty stylesheet file – &lt;code>styles.css&lt;/code> – inside the &lt;code>src&lt;/code> directory. The extension of that file will depend on the stylesheet you chose when you were prompted for when you were creating a new project. You can simply add your &lt;code>CSS/SASS/LESS&lt;/code> styles here and you are good to go. Remember to change the stylesheet extension appropriately.&lt;/p>
&lt;p>But things are never that easy, inside &lt;code>angular.json&lt;/code>, there is an array for scripts and styles, much similar to the one for assets above. Inside the two arrays, you can add paths to your styles and scripts, in the appropriate array.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;styles&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;src/styles.scss&amp;#34;&lt;/span>],
&lt;span style="color:#f92672">&amp;#34;scripts&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;some/path/to/a/script&amp;#34;&lt;/span>]
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Unlike the assets array above, where the files are simply copied over to the build directory, this will be bundled in to the angular final build bundles. However, if you don’t want that, you can use an object to configure either style or script. This will allow you to specify how each style or script will be built. The object configuration can have up to 3 fields:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">path&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">to&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">style&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">or&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">script&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">file&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(required)&lt;/span>
&lt;span style="color:#f92672">&amp;#34;bundleName&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">output&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">bundle&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">name,&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">don’t&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">add&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">extension&lt;/span>
&lt;span style="color:#f92672">&amp;#34;lazy&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">when&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">set&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">to&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">the&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">file&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">will&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">not&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">be&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">added&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">to&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">index.html&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>When the &lt;code>bundleName&lt;/code> is specified, the resulting file is added independently to &lt;code>index.html&lt;/code>, in the order specified in the array. The third field specifies whether the resulting bundle, will be included inside the index.html file. If set to true, it will be bundled and added to the build directory but will not added inside the &lt;code>index.html&lt;/code>. A hash will also not be added to the name of the bundle, making it easy to refer to it. This allows you to be able to &lt;a href="https://codinglatte.com/posts/angular/optimizing-your-angular-app-using-lazy-loading/">lazy load&lt;/a> such a script or style inside your app later along.&lt;/p>
&lt;h3 id="lazy-loading-local-and-remote-scripts">Lazy Loading Local and Remote Scripts&lt;/h3>
&lt;p>Some scripts are only required on very specific times, hence adding them to the index.html doesn’t make sense. For instance, PayPal Checkout.js is only required when the user is checking out and not when browsing the list of products. Therefore, adding it to the index.html and having it loaded alongside other important resources doesn’t make sense. It makes sense to load it only when required and not a moment before, which could have a negative impact on your app performance.&lt;/p>
&lt;p>You can load such scripts and styles inside your app, as shown below:&lt;/p>
&lt;p>&lt;strong>Script:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>(&lt;span style="color:#a6e22e">resolve&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">scriptElement&lt;/span> &lt;span style="color:#f92672">=&lt;/span> document.&lt;span style="color:#a6e22e">createElement&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;script&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">scriptElement&lt;/span>.&lt;span style="color:#a6e22e">src&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;URL TO SCRIPT&amp;#39;&lt;/span>;
&lt;span style="color:#a6e22e">scriptElement&lt;/span>.&lt;span style="color:#a6e22e">onload&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">resolve&lt;/span>;
document.&lt;span style="color:#a6e22e">body&lt;/span>.&lt;span style="color:#a6e22e">appendChild&lt;/span>(&lt;span style="color:#a6e22e">scriptElement&lt;/span>);
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Styles&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>((&lt;span style="color:#a6e22e">resolve&lt;/span>, &lt;span style="color:#a6e22e">reject&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">styleElement&lt;/span> &lt;span style="color:#f92672">=&lt;/span> document.&lt;span style="color:#a6e22e">createElement&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;link&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">styleElement&lt;/span>.&lt;span style="color:#a6e22e">href&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">styleUrl&lt;/span>;
&lt;span style="color:#a6e22e">styleElement&lt;/span>.&lt;span style="color:#a6e22e">onload&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">resolve&lt;/span>;
document.&lt;span style="color:#a6e22e">head&lt;/span>.&lt;span style="color:#a6e22e">appendChild&lt;/span>(&lt;span style="color:#a6e22e">styleElement&lt;/span>);
});
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> If you enable caching for your web app, only the initial load will take some noticeable time, subsequent loads will use the cached script, and will be much faster.&lt;/p>
&lt;/blockquote></description></item><item><title>Separating Dev and Prod Environment on Firebase</title><link>https://codinglatte.com/posts/angular/separating-dev-and-prod-environment-on-firebase/</link><pubDate>Sat, 16 Feb 2019 05:24:48 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/separating-dev-and-prod-environment-on-firebase/</guid><description>&lt;p>It is common for developers to setup multiple environments for our application. This usually include a development/staging and production environment. This gives us the freedom to experiment with our development/staging environment, without messing with the production environment. Only after thorough testing do we deploy to production.&lt;/p>
&lt;p>On top of that, the staging environment can be used to demonstrate and test new features before deploying them to production. Think of it like the &lt;a href="https://insider.windows.com/en-us/">Windows Insider Program&lt;/a>, where testers (Insiders) get new features beforehand to test and provide feedback. For instance, you can push changes to a staging environment to show your client new features. This enables you to collect their feedback and approval before deployment to production.&lt;/p>
&lt;p>We are going to use multiple firebase projects for a multi-environment setup. This is because we want to isolate everything i.e. functions, cloud Firestore etc. in each environment. Ensuring that changes we make on development/staging don’t affect the production environment – or in this case firebase project.&lt;/p>
&lt;p>This way, we can develop our application while knowing that all the changes we make will not break our production application. Then, once satisfied with our work, we can safely deploy to our production application.&lt;/p>
&lt;blockquote>
&lt;p>NB: We are going to be using Angular, but with some minor changes, this will work with any client app – frontend or mobile.&lt;/p>
&lt;/blockquote>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>We are going to start by creating two new firebase projects. One for production and the other for both development and staging purposes. We are using one for both development and staging to keep things simple. If you already have an existing project, you can just add another, with an appropriate name.&lt;/p>
&lt;p>Once you have created your projects, copy the configs for web from both of your firebase projects. They should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-js" data-lang="js">&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">config&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">apiKey&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;API_KEY&amp;gt;&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">authDomain&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;PROJECT_ID&amp;gt;.firebaseapp.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">databaseURL&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;https://&amp;lt;DATABASE_NAME&amp;gt;.firebaseio.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">projectId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;PROJECT_ID&amp;gt;&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">storageBucket&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;BUCKET&amp;gt;.appspot.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">messagingSenderId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;SENDER_ID&amp;gt;&amp;#39;&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, inside our Angular project, we need to add the above firebase configs, to our angular environment files. You can learn more about configuring Angular deployments environments &lt;a href="https://codinglatte.com/posts/angular/environment-variables-angular/">here&lt;/a>. But in a nutshell, by default, angular provides two environment files, located inside the &lt;code>environment&lt;/code> directory under the &lt;code>src&lt;/code> directory of your angular project. During compilation, Angular will replace the default environment file with the production, when the &lt;code>--prod&lt;/code> flag is used.&lt;/p>
&lt;p>Add the configurations from your &lt;code>dev/staging&lt;/code> firebase project to &lt;code>environment.ts&lt;/code>. And those from you production firebase project to &lt;code>environment.prod.ts&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#75715e">// environment.ts
&lt;/span>&lt;span style="color:#75715e">// configurations for dev/staging firebase projects
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#a6e22e">firebase&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">apiKey&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;API_KEY&amp;gt;&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">authDomain&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;PROJECT_ID&amp;gt;.firebaseapp.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">databaseURL&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;https://&amp;lt;DATABASE_NAME&amp;gt;.firebaseio.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">projectId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;PROJECT_ID&amp;gt;&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">storageBucket&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;BUCKET&amp;gt;.appspot.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">messagingSenderId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;SENDER_ID&amp;gt;&amp;#39;&lt;/span>
}
};
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#75715e">// environment.prod.ts
&lt;/span>&lt;span style="color:#75715e">// configurations for production firebase projects
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#a6e22e">firebase&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">apiKey&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;API_KEY&amp;gt;&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">authDomain&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;PROJECT_ID&amp;gt;.firebaseapp.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">databaseURL&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;https://&amp;lt;DATABASE_NAME&amp;gt;.firebaseio.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">projectId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;PROJECT_ID&amp;gt;&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">storageBucket&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;BUCKET&amp;gt;.appspot.com&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">messagingSenderId&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;lt;SENDER_ID&amp;gt;&amp;#39;&lt;/span>
}
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, go ahead and setup your angular project with firebase using &lt;a href="https://github.com/angular/angularfire2">AngularFire2&lt;/a>.&lt;/p>
&lt;p>First install both &lt;code>AngularFire2&lt;/code> and &lt;code>Firebase&lt;/code> into your Angular project if you haven’t yet.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm install @angular/fire firebase
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ yarn add @angular/fire firebase
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then import &lt;code>AngularFireModule&lt;/code> in your app module. (If you are using lazy loading, import it to a feature/shared module instead).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#75715e">// imports
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">AngularFireModule&lt;/span>.&lt;span style="color:#a6e22e">initializeApp&lt;/span>(&lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">firebase&lt;/span>)
],
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s setup firebase inside our project so that we can use both of our projects together.&lt;/p>
&lt;h3 id="setting-up-firebase-for-our-project">Setting up Firebase for our Project&lt;/h3>
&lt;p>First, we are going to initialize firebase project. Make sure you have &lt;code>Firebase CLI&lt;/code> installed globally. If you haven’t, you can do so by following the instructions &lt;a href="https://firebase.google.com/docs/cli/#install_the_firebase_cli">here&lt;/a>.&lt;/p>
&lt;p>Then, initialize firebase for the Angular project by running &lt;code>firebase init&lt;/code> at the root of our angular workspace.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-powershell" data-lang="powershell">$ firebase init
&lt;/code>&lt;/pre>&lt;/div>&lt;p>When prompted for the firebase project to use, select the development/staging one. Then, answer the next prompts that follow up appropriately. The project that you selected above is known has an alias of &lt;code>default&lt;/code>. This will become clear once we add a second firebase project.&lt;/p>
&lt;p>Then, we need to add a second project, on top of the project which we added during initialization. Fortunately, Firebase CLI provides a way of doing that, using the firebase use commands. We can add a second firebase project by using the &lt;code>firebase use --add&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-powershell" data-lang="powershell">$ firebase use --add
&lt;/code>&lt;/pre>&lt;/div>&lt;p>When you run the above command, Firebase CLI will prompt you to select a second project. And then will prompt you to enter an ALIAS for the project. Select the project you created for production purpose and use &lt;code>prod&lt;/code> as the ALIAS of the second project.&lt;/p>
&lt;p>Please note that we have two firebase projects setup, one known as the default, for dev/staging and the other one prod for production. If you ran firebase deploy at this point, firebase will deploy to the default firebase project. To deploy to the production firebase project, there are two methods:&lt;/p>
&lt;p>The first method is to use the &lt;code>firebase use &amp;lt;alias&amp;gt;&lt;/code> command to switch the firebase project to deploy to, followed by the firebase deploy command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase use default
$ firebase use prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the second method is to use the &lt;code>-P&lt;/code> flag to specify the firebase project to deploy to when deploying:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase deploy -P default
$ firebase deploy -P prod
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: If you forget to specify the &lt;code>-P&lt;/code> flag, firebase CLI will deploy to the firebase project set using &lt;code>firebase use &amp;lt;alias&amp;gt;&lt;/code> command.&lt;/p>
&lt;/blockquote>
&lt;p>With that, you should be able to easily deploy your app to the appropriate firebase project, giving you a nice separation of deployment environments.&lt;/p>
&lt;h3 id="what-about-firebase-functions">What about Firebase Functions?&lt;/h3>
&lt;p>If you are using callable functions, no modifications are necessary as they are dictated by the firebase configs for your project. But, if you are using http firebase functions, the http endpoint for the functions is going to vary based on the firebase project you are targeting.&lt;/p>
&lt;p>The good thing is you can solve this by using angular environment variables. You can add the functions http endpoint for each firebase project, inside the appropriate environment file. I.e. For production firebase function, add the http endpoint to the &lt;code>environment.prod.ts&lt;/code> and the same goes for dev/staging.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#75715e">// other environment variabes
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#a6e22e">firebase&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#75715e">// other firebase configs
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">functions&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">Function1&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Function EndPoint&amp;#39;&lt;/span>;
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, you can use the above firebase function end point as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">firebase&lt;/span>.&lt;span style="color:#a6e22e">functions&lt;/span>.&lt;span style="color:#a6e22e">Function1&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="hosting-multiple-sites-per-project">Hosting Multiple Sites Per Project&lt;/h3>
&lt;p>You might also want to use multi-site hosting in Firebase. This is quite useful if you wanted to have a client and admin site for your app. The best way to achieve this in Angular is using &lt;a href="https://codinglatte.com/posts/angular/angular-6-angular-cli-workspaces/">Angular Workspaces&lt;/a>, which enables you to have more than one app in your angular project. You can learn more about Angular workspaces &lt;a href="https://codinglatte.com/posts/angular/angular-6-angular-cli-workspaces/">here&lt;/a>.&lt;/p>
&lt;p>Assuming you have your second site ready, go ahead and add a second hosting site for each of your firebase projects – &lt;code>dev&lt;/code>/&lt;code>staging&lt;/code> and &lt;code>production&lt;/code>. You can follow the instructions &lt;a href="https://firebase.googleblog.com/2018/08/one-project-multiple-sites-plus-boost.html">here&lt;/a> which explain everything in &lt;a href="https://firebase.googleblog.com/2018/08/one-project-multiple-sites-plus-boost.html">details&lt;/a>. Please note that you will have to switch to a paid firebase plan for you to be able to do this, I suggest using pay as you go. Proceed at your own discretion.&lt;/p>
&lt;p>Please note that, each firebase site is unique across all firebase account, since the site subdomain, is accessible over the internet. As such, the name of your sites can not be re-used across your firebase projects. Therefore, to identify which site to deploy to, Firebase CLI uses targets, which are a lot like aliases for firebase projects above.&lt;/p>
&lt;p>By using targets, we can deploy to the correct site on firebase hosting despite their unique name, in each of our firebase project. First, switch to the firebase project you want to setup, using the &lt;code>firebase use &amp;lt;alias&amp;gt;&lt;/code> command.&lt;/p>
&lt;p>And then, use the command below, to link a target name to a site name. The site name is the subdomain of the site, a unique identify across all firebase projects.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase target:apply hosting target-name site-name
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For instance, if you had a client and admin sites, then it would look something like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase use default
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase target:apply hosting client client-dev-site-name
$ firebase target:apply hosting admin admin-dev-site-name
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You will also have to do the same for the second firebase project, switch to it and repeat the above process. Ensuring that you change the name of the site appropriately.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase use prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase target:apply hosting client client-prod-site-name
$ firebase target:apply hosting admin admin-prod-site-name
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: As of the writing this post, site and target names with hyphen (-) case do not work as expected, please avoid that for now.&lt;/p>
&lt;/blockquote>
&lt;p>In a nutshell, we are telling Firebase CLI to use targets client and admin, to target the corresponding site inside the firebase project we are using. For instance, when deploying to production, Firebase CLI will use the target to identify the subdomain of the site to deploy to. The same also applies when deploying to dev/staging firebase project.&lt;/p>
&lt;p>You can now deploy your angular app as shown earlier, by using the &lt;code>-P&lt;/code> flag or switching between the firebase projects:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase deploy -P default
$ firebase deploy -P prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>or&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ firebase use default
$ firebase deploy
$ firebase use prod
$ firebase deploy
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: You can use all the firebase deploy flags like &lt;code>--only&lt;/code> or &lt;code>--except&lt;/code> as you normally would in any other firebase project.&lt;/p>
&lt;/blockquote>
&lt;h4 id="tip">TIP&lt;/h4>
&lt;p>You can use NPM scripts to deploy to the appropriate firebase project smoothly.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">package.json&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;scripts&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;deploy:dev&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;firebase use staging &amp;amp;&amp;amp; ng build --aot &amp;amp;&amp;amp; firebase deploy&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;deploy:prod&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;firebase use default &amp;amp;&amp;amp; ng build --prod &amp;amp;&amp;amp; firebase deploy&amp;#34;&lt;/span>
}&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Each of the above script will change to the appropriate firebase project, build your angular app and deploy it, alongside all other firebase services you have setup.&lt;/p>
&lt;p>And then you can easily deploy using the following command:&lt;/p>
&lt;p>For production:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm run deploy:prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For development/staging:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm run deploy:dev
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Changing Angular Material Form Field Appearance</title><link>https://codinglatte.com/posts/angular/angular-material-form-field-appearance/</link><pubDate>Mon, 04 Feb 2019 01:20:33 +0300</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-material-form-field-appearance/</guid><description>&lt;p>Material design has been with us for the last few years. The material &lt;a href="https://material.io/design/introduction/#principles">guidelines&lt;/a> spec sheet, found &lt;a href="https://material.io/design/introduction/#principles">here&lt;/a>, has evolved since the original design, on release. This can be seen in various Google products, as they continue updating their products according to the updated spec sheet.&lt;/p>
&lt;p>Angular 2 Material may be slightly behind the latest material design specification, but it’s catching up. In this post, we are going to look at how you can change the default appearance of Angular Material Form Field Component.&lt;/p>
&lt;p>But first, let’s see where we are coming from.&lt;/p>
&lt;h3 id="some-history-of-material-form-field-text-field-appearance">Some History of Material Form Field (Text Field) Appearance&lt;/h3>
&lt;p>When the material design guidelines were initially released, the text field appearance looked something like this:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-material-form-field-appearance/legacy-appearance.jpg" alt="Legacy Form Field Appearance" width="600px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>This is known as legacy appearance, then, later it was given an update (mainly under the hood) in what is called as standard appearance. And that looks like this:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-material-form-field-appearance/standard-appearance.jpg" alt="Standard Form Field Appearance" width="600px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>I know, the two are largely indistinguishable. Then, latter, two more appearances were introduced - the outline and fill appearance. Here are some examples on what they look like:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-material-form-field-appearance/new-appearances.jpg" alt="Outline and Fill Form Field Appearance" width="600px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>And then they finally did away with the first two appearances – Legacy and Standard Appearance. So, as of today, we only have two appearances – outline and fill appearance.&lt;/p>
&lt;p>Enough with history, let’s go back to Angular Material. If you have updated to the latest version of Angular Material, you will note that nothing has changed in your material form field controls. Why? This is because, to use the new form field appearance, you have to specify which appearance to use.&lt;/p>
&lt;blockquote>
&lt;p>NB: By default, everything stays as it were in older versions of Angular Material. This may change in the future though.&lt;/p>
&lt;/blockquote>
&lt;p>There are two main approaches with this. The first is to define the appearance for each individual form field component. And the second option is to set a default appearance to apply to all material form field components in your app.&lt;/p>
&lt;p>Let’s look at the first method:&lt;/p>
&lt;h3 id="individual-material-form-field-component-appearance">Individual Material Form Field Component Appearance&lt;/h3>
&lt;p>This is quite simple to achieve, as all you have to do is specify the appearance property/attribute of the material form field component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&lt;span style="color:#75715e">&amp;lt;!-- setting outline form field appearance --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">mat-form-field&lt;/span> &lt;span style="color:#a6e22e">appearance&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;outline&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-label&lt;/span>&amp;gt;Input Label &amp;lt;/&lt;span style="color:#f92672">mat-label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">matInput&lt;/span> &lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Input placeholder&amp;#34;&lt;/span> /&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-form-field&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- setting fill form field appearance --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">mat-form-field&lt;/span> &lt;span style="color:#a6e22e">appearance&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;fill&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-label&lt;/span>&amp;gt;Input Label &amp;lt;/&lt;span style="color:#f92672">mat-label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">matInput&lt;/span> &lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Input placeholder&amp;#34;&lt;/span> /&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-form-field&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: You must specify the label of the material form field component. This is unlike the standard and legacy appearance which used the placeholder as a label when the label is not specified.&lt;/p>
&lt;/blockquote>
&lt;p>You can also set the appearance to either legacy and standard appearance, since Angular Material has not dropped support for both.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&lt;span style="color:#75715e">&amp;lt;!-- setting standard form field appearance --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">mat-form-field&lt;/span> &lt;span style="color:#a6e22e">appearance&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;standard&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-label&lt;/span>&amp;gt;Input Label &amp;lt;/&lt;span style="color:#f92672">mat-label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">matInput&lt;/span> &lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Input placeholder&amp;#34;&lt;/span> /&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-form-field&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="setting-the-default-appearance">Setting the Default Appearance&lt;/h3>
&lt;p>In the first step, we were setting form field appearance to individual form field components. This can be a lot of work, for instance, if you wanted to switch from one appearance to another for all your material form fields.&lt;/p>
&lt;p>Another option is to set the default form field component appearance, then use the above method to change individual form field to your preference. This way, whenever you don’t specify appearance attribute (property), then the default is used.
To achieve this, we are going to use token injection (&lt;code>MAT_FORM_FIELD_DEFAULT_OPTIONS&lt;/code>) to set the default form field appearance.&lt;/p>
&lt;p>First, let’s define our &lt;code>appearance&lt;/code> constant of type MatFormFieldDefaultOptions which will contain default appearance. In our case, we will be setting our form field appearance as outline.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">appearance&lt;/span>: &lt;span style="color:#66d9ef">MatFormFieldDefaultOptions&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">appearance&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;outline&amp;#39;&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, inside our array of providers, we need to provide &lt;code>MAT_FORM_FIELD_DEFAULT_OPTIONS&lt;/code> and set the value to &lt;code>appearance&lt;/code> constant we created above:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ... imports above
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">//... Components, Pipes, Directives etc
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>
&lt;span style="color:#75715e">// ... Imports like Material Form Fiel Module
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">MAT_FORM_FIELD_DEFAULT_OPTIONS&lt;/span>,
&lt;span style="color:#a6e22e">useValue&lt;/span>: &lt;span style="color:#66d9ef">appearance&lt;/span>
}
&lt;span style="color:#75715e">// ... other providers like services
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it, all your material form field components should be switched to outline form field appearance. You can now use the first method to set form field appearance for individual form field control.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-material-form-field-appearance/mixed-appearance.png" alt="Using Both Outline and Fill Appearances" width="600px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;blockquote>
&lt;p>NB: You can also use this token injection token method to set the default form field appearance on an individual component too, as illustrated &lt;a href="https://github.com/coding-latte/ng2-material-form-control-appearance/blob/477f538f24f1246c7b45b2bfe6be3302819f7b43/src/app/fill-appearance-default/fill-appearance-default.component.ts#L13">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ... imports
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">@Component&lt;/span>({
&lt;span style="color:#a6e22e">selector&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;app-fill-appearance-default&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">templateUrl&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./fill-appearance-default.component.html&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">styleUrls&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;./fill-appearance-default.component.css&amp;#39;&lt;/span>],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">MAT_FORM_FIELD_DEFAULT_OPTIONS&lt;/span>,
&lt;span style="color:#a6e22e">useValue&lt;/span>: &lt;span style="color:#66d9ef">appearance&lt;/span>
}
]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">FillAppearanceDefaultComponent&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">OnInit&lt;/span> {
&lt;span style="color:#75715e">// ... components methods and properties
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="source-code-and-demo">Source Code and Demo&lt;/h3>
&lt;p>You can find the above source code &lt;a href="https://github.com/coding-latte/ng2-material-form-control-appearance">here&lt;/a> and a demo of all supported material form field appearance &lt;a href="https://coding-latte.github.io/ng2-material-form-control-appearance/">here&lt;/a>.&lt;/p></description></item><item><title>Using OS Environment Variables in Angular (with Docker)</title><link>https://codinglatte.com/posts/angular/using-os-environment-variables-in-angular-with-docker/</link><pubDate>Sun, 13 Jan 2019 13:39:13 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/using-os-environment-variables-in-angular-with-docker/</guid><description>&lt;p>Angular has its way of handling different target environments, through angular environments files – which you can learn more about &lt;a href="https://codinglatte.com/tech/developers/angular/environment-variables-angular/">here&lt;/a>. The issue with this approach is that it requires you to commit keys and configuration to your version control. This is not a big problem since it’s not advisable have any sensitive data in your angular source code.&lt;/p>
&lt;p>However, I find it important to keep those keys and configurations outside the source control. This makes it easier to manage keys and configurations for different environments, without requiring you to modify the source code to make any changes. As you might have guessed from the title of this post, we will be using docker and OS Environment variables to pass some keys to Angular CLI, through webpack. Why OS Environment Variables? Mainly because they are platform agnostic, you can use them with the platforms of your choice. And also they are very easy to work with.&lt;/p>
&lt;h3 id="how-it-works">How it works?&lt;/h3>
&lt;p>The basic concept here is rather simple. For the purpose of this post, we are going to set a few environment variables, inside our dockerfile. Then, Webpack is going to read them, and pass them to our angular app during build time. Ideally though, you don’t want to set the variables in your dockerfile, but rather somewhere else like a .env file. Then, during docker build, retrieve the configurations and set them to environment variables.&lt;/p>
&lt;p>If they are stored somewhere else, like let’s say an S3 Bucket, then you can perform the extra step of fetching them and setting them up. This can be achieved easily via multi-stage build in dockerfile. To build our angular app for deployment using &lt;a href="https://codinglatte.com/tag/docker/">docker&lt;/a>, we are going to use docker &lt;a href="https://docs.docker.com/develop/develop-images/multistage-build/">multi-stage build&lt;/a>.&lt;/p>
&lt;p>This will result into an image which is smaller – which reduces our attack surface area. I won’t go into details about this, but I wrote another post explaining everything which you can find &lt;a href="https://codinglatte.com/tech/developers/angular/building-docker-images-angular/">here&lt;/a>. To make everything easy, we will use OS Environment Variables to configure production environment only – &lt;a href="https://github.com/coding-latte/using-angular-docker-environment-variables/blob/master/src/environments/environment.prod.ts">&lt;code>environment.prod.ts&lt;/code>&lt;/a>.&lt;/p>
&lt;p>This is because, for dev environment, I am assuming that you will be relying mainly on &lt;a href="https://angular.io/cli/serve">ng serve&lt;/a>, which is out of scope for this post. That will be covered in a different post latter this week. So, without further ado, let’s get started:&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>Assuming you already have your Angular project setup, First, we are going to install &lt;a href="https://github.com/meltedspark/angular-builders/tree/master/packages/custom-webpack">&lt;code>@angular-builders/custom-webpack&lt;/code>&lt;/a> as a dev dependency. In a nutshell, this allows us to customize build configuration without ejecting our angular project.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add --dev @angular-builders/custom-webpack
&lt;/code>&lt;/pre>&lt;/div>&lt;p>OR&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install -D @angular-builders/custom-webpack
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="configuring-angular">Configuring Angular&lt;/h3>
&lt;p>Next, we are going to modify our angular configurations – angular.json – to use the new builder(&lt;code>@angular-builders/custom-webpack:browser&lt;/code>) instead of the default angular one (&lt;code>@angular-devkit/build-angular:browser&lt;/code>). And then, under options, we are also going to add a &lt;code>customWebpackConfig&lt;/code> option with a path pointing to &lt;code>custom-webpack.config.js&lt;/code> file as shown below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;projects&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
    &lt;span style="color:#f92672">&amp;#34;name-of-the-project&amp;#34;&lt;/span>: {
      &lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
      &lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
        &lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
          &lt;span style="color:#f92672">&amp;#34;builder&amp;#34;&lt;/span>:&lt;span style="color:#e6db74">&amp;#34;@angular-builders/custom-webpack:browser&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">_&lt;/span>,
          &lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
            &lt;span style="color:#f92672">&amp;#34;customWebpackConfig&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;path&amp;#34;&lt;/span>:&lt;span style="color:#e6db74">&amp;#34;custom-webpack.config.js&amp;#34;&lt;/span>
},
            &lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
        &lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
    }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> We have changed the default angular builder from &lt;code>@angular-devkit/build-angular:browser&lt;/code> to &lt;code>@angular-builders/custom-webpack:browser&lt;/code>.&lt;/p>
&lt;/blockquote>
&lt;p>Then, we are going to create our custom-webpack.config.js file – which we referenced above – at the root of our &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">Angular Workspace&lt;/a>. And then add the following content, to retrieve OS Environment Variables and pass them to our builder.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-js" data-lang="js">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">webpack&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">require&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;webpack&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">module&lt;/span>.&lt;span style="color:#a6e22e">exports&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">plugins&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">webpack&lt;/span>.&lt;span style="color:#a6e22e">DefinePlugin&lt;/span>({
&lt;span style="color:#a6e22e">$ENV&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">ENVIRONMENT&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">JSON&lt;/span>.&lt;span style="color:#a6e22e">stringify&lt;/span>(&lt;span style="color:#a6e22e">process&lt;/span>.&lt;span style="color:#a6e22e">env&lt;/span>.&lt;span style="color:#a6e22e">ENVIRONMENT&lt;/span>),
&lt;span style="color:#a6e22e">SomeAPIKey&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">JSON&lt;/span>.&lt;span style="color:#a6e22e">stringify&lt;/span>(&lt;span style="color:#a6e22e">process&lt;/span>.&lt;span style="color:#a6e22e">env&lt;/span>.&lt;span style="color:#a6e22e">SomeAPIKey&lt;/span>),
&lt;span style="color:#a6e22e">SomeOtherAPIKey&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">JSON&lt;/span>.&lt;span style="color:#a6e22e">stringify&lt;/span>(&lt;span style="color:#a6e22e">process&lt;/span>.&lt;span style="color:#a6e22e">env&lt;/span>.&lt;span style="color:#a6e22e">SomeOtherAPIKey&lt;/span>)
}
})
]
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In a nutshell, we are creating a webpack plugin. And then, we are reading the OS environment variables and passing them to Angular, via webpack. We are grouping all our environment variables, under &lt;code>$ENV&lt;/code> variable, so that we can simply access them like this: &lt;code>$ENV.ENVIRONMENT&lt;/code> or &lt;code>$ENV.SomeAPIKey&lt;/code> inside our angular app. In this case, we have 3 environment variables: &lt;code>Environment&lt;/code>, &lt;code>SomeAPIKey&lt;/code> and &lt;code>SomeOtherAPIKey&lt;/code>.&lt;/p>
&lt;h3 id="using-os-environment-variables-in-angular">Using OS Environment Variables in Angular&lt;/h3>
&lt;p>First, we are going to add some typings, so that we can reference to our &lt;code>$ENV&lt;/code> variable from webpack above within our Angular app. First, let’s create a typing.d.ts file inside your &lt;code>src&lt;/code> directory at the root of your workspace and add the following content.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">declare&lt;/span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">$ENV&lt;/span>: &lt;span style="color:#66d9ef">Env&lt;/span>;
&lt;span style="color:#66d9ef">interface&lt;/span> &lt;span style="color:#a6e22e">Env&lt;/span> {
&lt;span style="color:#a6e22e">ENVIRONMENT&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">SomeAPIKey&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">SomeOtherAPIKey&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In a nutshell, we are declaring a &lt;a href="https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#global-variables">global variable&lt;/a> &lt;code>$ENV&lt;/code> of type Env interface. Inside the Env interface, we are adding fields that we expect to be passed by our webpack plugin that we created in the previous step.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can rename &lt;code>$ENV&lt;/code> to a variable of your choice. Make sure to change &lt;code>typings.d.ts&lt;/code> and &lt;code>custom-webpack.config.js&lt;/code> file appropriately.&lt;/p>
&lt;/blockquote>
&lt;p>Then, inside the our &lt;code>environment.prod.ts&lt;/code>, we need to read the OS environment variables passed to our application, into variables we can use, within our angular application. This can be done like this: &lt;code>$ENV.ENVIRONMENT&lt;/code> – so that our &lt;code>environment.prod.ts&lt;/code> would like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#a6e22e">environment&lt;/span>: &lt;span style="color:#66d9ef">$ENV.ENVIRONMENT&lt;/span>,
&lt;span style="color:#a6e22e">APIKeys&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">SomeAPIKey&lt;/span>: &lt;span style="color:#66d9ef">$ENV.SomeAPIKey&lt;/span>,
&lt;span style="color:#a6e22e">SomeOtherAPIKey&lt;/span>: &lt;span style="color:#66d9ef">$ENV.SomeOtherAPIKey&lt;/span>
}
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, inside our &lt;code>environment.ts&lt;/code> file – the one use when using ng serve or build without production – we need to add the same keys but with static variables.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#a6e22e">environment&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;development&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">APIKeys&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">SomeAPIKey&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;DEV API Key&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">SomeOtherAPIKey&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;DEV API Key 2&amp;#39;&lt;/span>
}
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, your OS Environment variables are accessible throughout your application. They can be used just like any other angular environment variables inside your application.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppComponent&lt;/span> {
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">environment&lt;/span>;
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">SomeAPIKey&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">APIKeys&lt;/span>.&lt;span style="color:#a6e22e">SomeAPIKey&lt;/span>;
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">SomeOtherAPIKey&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">APIKeys&lt;/span>.&lt;span style="color:#a6e22e">SomeOtherAPIKey&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="the-dockerfile">The Dockerfile&lt;/h3>
&lt;p>Inside our dockerfile, we are going to be setting environment variables which will be picked up by webpack. This environment variables need to be set at the builder stage of our docker multi-stage build.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#75715e"># STAGE 1&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> node:10.15.0 as builder&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#75715e"># SET ENVIRONMENT VARIABLES&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">ENV&lt;/span> ENVIRONMENT&lt;span style="color:#f92672">=&lt;/span>production1
&lt;span style="color:#66d9ef">ENV&lt;/span> SomeAPIKey&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;This is not an API Key&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">ENV&lt;/span> SomeOtherAPIKey&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;This is not another API Key&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> yarn global add @angular/cli@latest&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> yarn install&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> ng build --prod&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#75715e"># STAGE 2&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can find the complete dockerfile file &lt;a href="https://github.com/coding-latte/using-angular-docker-environment-variables/blob/master/dockerfile">here&lt;/a>, with comments on each step.&lt;/p>
&lt;/blockquote>
&lt;p>Like I said (wrote I guess) at the beginning, the values for this environment variables can come from a variety of sources. You can use docker-compose to pass a .env file, which you can learn more about &lt;a href="https://docs.docker.com/compose/env-file/">here&lt;/a>. This can also be retrieved from a cloud storage service AWS S3 or GCP Cloud Storage either in the builder stage or another stage prior to builder.&lt;/p>
&lt;h3 id="source-code">Source Code&lt;/h3>
&lt;p>You can find the source code for this post &lt;a href="https://github.com/coding-latte/using-angular-docker-environment-variables">here&lt;/a>.&lt;/p></description></item><item><title>Golang – Building Small Docker Images</title><link>https://codinglatte.com/posts/golang/golang-small-docker-images/</link><pubDate>Fri, 04 Jan 2019 17:33:38 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/golang/golang-small-docker-images/</guid><description>&lt;p>In this post, we are going to see how we can reduce the size of our final docker image size for our golang app. To achieve this, we are going to be using the scratch docker image. This is going to reduce the size of the final image by over 95%.&lt;/p>
&lt;p>Why? By reducing the size of our final docker image, we are reducing the attack surface area. This means that attackers have less libraries, tools to exploit in our &lt;a href="https://codinglatte.com/tag/docker/">docker&lt;/a> image. For this to be possible, we will need to statically compile our go application, so that it doesn’t need any external libraries.&lt;/p>
&lt;p>To achieve this, we are going to use two stages to build our final docker image. In the first stage, we are going to use the official image for Golang, to statically compile our go application. Then, in the second stage, we will copy our statically compiled binaries from the first stage. To get started, we are going to create a &lt;a href="https://docs.docker.com/engine/reference/builder/">Dockerfile&lt;/a> at the root of our project. We are going to name it scratch.dockerfile – feel free to change the filename, if you wish to.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> If you are new to docker and containers in general, I suggest you start by reading the following post &lt;a href="https://medium.freecodecamp.org/a-beginner-friendly-introduction-to-containers-vms-and-docker-79a9e3e119b">here&lt;/a> for the basics. You can also learn how to get started with docker &lt;a href="https://www.docker.com/get-started">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h3 id="demo-application">Demo Application&lt;/h3>
&lt;p>In order to make a meaningful demo, I needed a barebone Golang application. Therefore, I used the basic example from &lt;a href="https://github.com/gin-gonic/gin">Gin Web Framework&lt;/a> which can be found &lt;a href="https://github.com/gin-gonic/gin/tree/master/examples/basic">here&lt;/a>. I didn’t make any modification to the above code. I am confident enough you can replace it with your own custom code, without any modifications.&lt;/p>
&lt;h3 id="stage-1--building-the-golang-application">Stage  1 – Building the Golang Application&lt;/h3>
&lt;p>In this stage, we are going to compile our go application statically. But first things first, inside our dockerfile, we will start by setting the base image for docker. We will be using the latest available image for Golang; hence no tag. We will also name our stage as &lt;code>builder&lt;/code>, this makes it easier to refer to it in the next stage.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> golang as builder&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we are going to change our working directory, to the directory in which we will build our application. I recommend using the same structure as your dev environment, from the GOPATH. For the Golang images, the GOPATH is &lt;code>/go&lt;/code>. This will ensure that our go application behaves the same as it does in our dev environment.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /go/src/github.com/coding-latte/golang-docker-multistage-build-demo&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s copy our projects files, and install our projects dependencies and build our go application.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> . .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> go get .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> CGO_ENABLED&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span> GOOS&lt;span style="color:#f92672">=&lt;/span>linux go build -a -installsuffix cgo -o app .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>TIP:&lt;/strong> If you are using &lt;a href="https://github.com/golang/go/wiki/Modules">go modules&lt;/a>, I recommend copying the project code in a directory outside the GOPATH (&lt;code>/go/src&lt;/code>). This is because, once you put it inside the &lt;code>GOPATH&lt;/code>, go modules will be disabled. This may cause your application to break.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /app/project-name&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> . .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="stage-2--deployment-image">Stage 2 – Deployment Image&lt;/h3>
&lt;p>In this stage, we are going to build the image which we will be deploying. So, let’s set our base image as  scratch – &lt;code>FROM scratch&lt;/code>. Naming the stage is not necessary since it’s the last stage in our multi-stage build.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> scratch&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we are going to copy &lt;code>ca-certificates&lt;/code> and compiled Golang static binaries from stage one – builder. First, let’s copy the &lt;code>ca-certificates&lt;/code>, this is important if you will be using SSL/TLS to access your application. Otherwise you can skip this one if your app is not using SSL/TLS.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, change the working directory to bin (or any other name of your choice), and copy the compiled binaries to that directory:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /bin&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>builder /go/github.com/coding-latte/golang-docker-multistage-build-demo/app .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, set our go app to be executed when the container starts and expose port 8080.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">CMD&lt;/span> [&lt;span style="color:#e6db74">&amp;#34;./app&amp;#34;&lt;/span>]&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">EXPOSE&lt;/span>&lt;span style="color:#e6db74"> 8080&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>...&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If your app is using another port, replace port 8080 with that port. And if it’s using multiple ports, separate them with a single whitespace.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can find the complete dockerfile &lt;a href="https://github.com/coding-latte/golang-docker-multistage-build-demo/blob/master/scratch.dockerfile">here&lt;/a>. And if you would rather use &lt;a href="https://hub.docker.com/_alpine/">alpine linux&lt;/a> docker image instead of scratch, you can find the corresponding dockerfile &lt;a href="https://github.com/coding-latte/golang-docker-multistage-build-demo/blob/master/alpine.dockerfile">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h3 id="building-the-docker-image">Building the Docker Image&lt;/h3>
&lt;p>We can now go ahead and build our docker image:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">docker build --rm -f &lt;span style="color:#e6db74">&amp;#34;**scratch.dockerfile**&amp;#34;&lt;/span> -t demo:latest .
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> If you are not using scratch.dockerfile as the name of your dockerfile, replace that with correct name and path in the above command. You can learn more about building docker images &lt;a href="https://docs.docker.com/engine/reference/commandline/build/">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>So, our final docker image size when using scratch docker image is 15.5MB, as compared to 844MB when using official Golang docker image. If you used alpine image instead of scratch, you can add just an extra 5MB on top of the scratch final size, where you will get about 20MB. This is still a huge size reduction from the official docker image for golang.&lt;/p>
&lt;h3 id="source-code">Source Code&lt;/h3>
&lt;p>You can find the source code for this post &lt;a href="https://github.com/coding-latte/golang-docker-multistage-build-demo">here&lt;/a>.&lt;/p></description></item><item><title>Creating a Filter Method for Angular Async Pipe</title><link>https://codinglatte.com/posts/angular/filter-angular-async-pipe/</link><pubDate>Thu, 13 Dec 2018 16:43:10 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/filter-angular-async-pipe/</guid><description>&lt;p>In a previous &lt;a href="https://codinglatte.com/tech/developers/angular/angular-async-pipe-handle-errors/">post&lt;/a> earlier this week, we looked at how we can handle errors when using Angular &lt;a href="https://angular.io/api/common/AsyncPipe">Async Pipe&lt;/a>. In this post, we are going to build a simple filter method for Angular &lt;a href="https://angular.io/api/common/AsyncPipe">Async Pipe&lt;/a>.&lt;/p>
&lt;p>We are going to use a custom pipe to filter results, then pass an observable back to the async pipe for subscription and rendering of the results. We will be simulating a call to a backend, where you take a search term and put together a HTTP request.&lt;/p>
&lt;p>And then receive the results and return them to the caller. Since we don’t have a backend, we will be using a static list of countries, which we will filter and return matching countries. We will also be adding a delay of two seconds, to simulate calls to a backend. During the 2 seconds delay, we are going to show a loading animation or message.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>As always, we will start by creating a new Angular project using Angular CLI:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng new angular-pipe-filter
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For the &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI&lt;/a>, we will be using &lt;a href="https://getbootstrap.com/">bootstrap&lt;/a>, so let’s install it and set it up. Feel free to use the &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI Library&lt;/a> of your choice.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ yarn add bootstrap
// or with npm
$ npm install bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, import Bootstrap CSS into your angular project, under your app style section in &lt;code>angular.json&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
  &lt;span style="color:#e6db74">&amp;#34;src/styles.scss&amp;#34;&lt;/span>,
  &lt;span style="color:#e6db74">&amp;#34;node_modules/bootstrap/dist/css/bootstrap.min.css&amp;#34;&lt;/span>
]&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it for our project setup.&lt;/p>
&lt;h3 id="filter-service">Filter Service&lt;/h3>
&lt;p>In a nutshell, the service will take a countries object, convert it into an observable using the &lt;a href="https://www.learnrxjs.io/operators/creation/of.html">of RXJS operator&lt;/a>, filter the resulting object and return the filtered object. Let’s start by generating our service, using &lt;a href="https://github.com/angular/angular-cli/wiki/generate-service">Angular CLI&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng generate service filter
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will generate a filter service inside the root of our app directory. Then, let’s add a method to filter and return an observable of list of countries.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">filterCountries&lt;/span>(&lt;span style="color:#a6e22e">filter?&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">Country&lt;/span>[]&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;code>Country&lt;/code> is a &lt;a href="https://www.typescriptlang.org/docs/handbook/interfaces.html">typescript interface&lt;/a> that has country name and code fields. The method takes a &lt;code>filter&lt;/code> parameter, which is the phrase we will use to check if a country name has.&lt;/p>
&lt;/blockquote>
&lt;p>Then, inside the method, we need to start by converting the list of countries object, into an observable. And then we are going to pipe the resulting observable and add a delay of 200 seconds. After that, we shall then map the list of countries, and filter them by looping through each country and checking whether the country name contains the filter phrase.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#a6e22e">countries&lt;/span>).&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">delay&lt;/span>(&lt;span style="color:#ae81ff">2000&lt;/span>),
&lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// if filter is empty return all countries
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">filter&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">c&lt;/span>;
}
&lt;span style="color:#75715e">// search for specific countries_
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">filteredCountries&lt;/span>: &lt;span style="color:#66d9ef">Country&lt;/span>[] &lt;span style="color:#f92672">=&lt;/span> [];
&lt;span style="color:#a6e22e">c&lt;/span>.&lt;span style="color:#a6e22e">filter&lt;/span>(&lt;span style="color:#66d9ef">function&lt;/span>(&lt;span style="color:#a6e22e">country&lt;/span>) {
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">country&lt;/span>.&lt;span style="color:#a6e22e">name&lt;/span>.&lt;span style="color:#a6e22e">toLowerCase&lt;/span>().&lt;span style="color:#a6e22e">includes&lt;/span>(&lt;span style="color:#a6e22e">filter&lt;/span>.&lt;span style="color:#a6e22e">toLowerCase&lt;/span>())) {
&lt;span style="color:#a6e22e">filteredCountries&lt;/span>.&lt;span style="color:#a6e22e">push&lt;/span>(&lt;span style="color:#a6e22e">country&lt;/span>);
}
});
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">filteredCountries&lt;/span>;
})
);
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Ideally, all the filtering done in this method should be accomplished on the backend. The method should send a HTTP request query to and return the response as received or with minor modification.&lt;/p>
&lt;/blockquote>
&lt;p>You can find the complete code for the service &lt;a href="https://github.com/MainaWycliffe/angular-async-pipe-filter/blob/master/src/app/filter.service.ts">here&lt;/a>.&lt;/p>
&lt;h3 id="filter-pipe">Filter Pipe&lt;/h3>
&lt;p>The pipe in this case, will act as a conduit between the component and the service. It will take in a filter term argument and pass it to the service and return the resulting observable. First, let’s generate a filter pipe:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng generate pipe filter
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will generate a pipe – &lt;a href="https://github.com/MainaWycliffe/angular-async-pipe-filter/blob/master/src/app/filter.pipe.ts">filter.pipe.ts&lt;/a> – at the root of the app directory. Then, inside the constructor, we are going to inject the filter service we created above into our pipe.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">filterService&lt;/span>: &lt;span style="color:#66d9ef">FilterService&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then modify the transform method of our pipe, so that it returns an observable of our country. The transform method is also going to accept the current value to transform and the &lt;strong>searchTerm&lt;/strong> as the second parameter. Then inside the method, we are going to return an observable of countries object (filtered) from our service:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">transform&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">filterTerm&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">Country&lt;/span>[]&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">filterService&lt;/span>.&lt;span style="color:#a6e22e">filterCountries&lt;/span>(&lt;span style="color:#a6e22e">filterTerm&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it for our pipe. You can learn more about pipes &lt;a href="https://angular.io/guide/pipes">here&lt;/a>.&lt;/p>
&lt;h3 id="putting-everything-together">Putting Everything Together&lt;/h3>
&lt;h4 id="app-feature-module">App (Feature) Module&lt;/h4>
&lt;p>First, inside our app module (or feature module), we are going to import the &lt;a href="https://angular.io/api/forms/FormsModule">FormsModule&lt;/a>. This is because we will be using &lt;a href="https://angular.io/api/forms/NgModel">NgModel&lt;/a> for two-way binding with a filter input.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">/* ... */&lt;/span>
],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">/* ... */&lt;/span>
&lt;span style="color:#a6e22e">FormsModule&lt;/span>
],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">/* ... */&lt;/span>
]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="component-class">Component Class&lt;/h4>
&lt;p>Next, inside our component class, we are going to add two properties. The first property is for our sfilter field – &lt;code>filterField&lt;/code>. This is field where users will enter their search term. While the second property will be an observable for the list of countries - &lt;code>filterResults$&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">filterField&lt;/span>;
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">filterResults$&lt;/span>: &lt;span style="color:#66d9ef">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">Country&lt;/span>[]&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, we will add a method to check whether our filter results returned an empty list. This will enable us to show an error message when the country list is empty.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">dataLength&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>: &lt;span style="color:#66d9ef">Country&lt;/span>[]) {
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>.&lt;span style="color:#a6e22e">length&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>You can also check whether the list of countries is empty at the filter service and throw an error at that point instead.&lt;/em>&lt;/p>
&lt;h4 id="component-template">Component Template&lt;/h4>
&lt;p>And finally, to our template. First, we are going to need a container for our application:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;container-fluid p-2&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-md-12 col-lg-8 offset-lg-2 offset-md-0&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we are going to add a filter text input for users to enter the term to filter countries by:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-12 form-group&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>&amp;gt; Filter Countries &amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[(&lt;/span>&lt;span style="color:#a6e22e">ngModel&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">filterField&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-control&amp;#34;&lt;/span> /&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we are going to use chain our pipe and angular async pipe to subscribe to observable returned by our custom pipe. When the request is yet to be resolved, we are going to show a loading message or animation.&lt;/p>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>Please note, we are passing the &lt;code>filterField&lt;/code> ngModel when using our filter pipe.&lt;/em>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;(filterResults$ | filter: filterField) | async as data; else loading&amp;#34;&lt;/span>&amp;gt;
  &lt;span style="color:#75715e">&amp;lt;!-- code here --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-template&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">loading&lt;/span>&amp;gt;
  &amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-12 text-center&amp;#34;&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- Loading ... --&amp;gt;&lt;/span> 
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-template&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then inside the tags, we shall check whether the list of countries is empty. If it’s empty, we are going to show an error, otherwise we shall loop over the list of countries.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-12&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;dataLength(data); else error&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list-unstyled row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let x of data; let i = index&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list-item col-12 col-md-6 col-lg-4&amp;#34;&lt;/span>
&amp;gt;
{{ i + 1 }} . {{ x.name | titlecase }}
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-template&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">error&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-12&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;alert alert-danger&amp;#34;&lt;/span>&amp;gt;
I could not find a country matching your filter criteria!
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-template&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="source-code-and-demo">Source Code and Demo&lt;/h3>
&lt;p>You can find the demo for this post &lt;a href="https://mainawycliffe.github.io/angular-async-pipe-filter/">here&lt;/a> and the complete source code &lt;a href="https://github.com/MainaWycliffe/angular-async-pipe-filter">here&lt;/a>.&lt;/p></description></item><item><title>Angular Async Pipe – How to Handle Errors</title><link>https://codinglatte.com/posts/angular/angular-async-pipe-handle-errors/</link><pubDate>Tue, 11 Dec 2018 11:32:34 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-async-pipe-handle-errors/</guid><description>&lt;p>In this post, I am going to show you a very simple yet effective way of handling errors when using Async Pipe in Angular. If you are new to async pipe, it basically allows you to subscribe to observables and promises right inside your templates. Below is a simple example of how you can use Async Pipe in Angular.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;some_observable | async&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Async Pipe has two major advantages. First, since subscriptions are handled automatically, you don’t need to worry about unsubscribing to observables. That will also be handled automatically for you. And secondly, it works with OnPush &lt;a href="https://angular.io/api/core/ChangeDetectionStrategy">change detection&lt;/a> automatically out of the box. You can learn more about change detection in Angular &lt;a href="https://netbasal.com/a-comprehensive-guide-to-angular-onpush-change-detection-strategy-5bac493074a4">here&lt;/a> and about Async Pipe &lt;a href="https://angular.io/api/common/AsyncPipe">here&lt;/a>.&lt;/p>
&lt;p>In order to handle errors properly, we are going to use &lt;code>*ngIf&lt;/code> with async pipe. Even when using &lt;code>*ngFor&lt;/code>, we need to wrap it around an &lt;code>*ngIf&lt;/code> container. This is because &lt;code>*ngIf&lt;/code> provides &lt;code>else&lt;/code> statement, allowing us to provide a template if the operation fails or the request is still in progress. This not only allows us to display an error message but also to show a loading indicator. Once the async operation has been resolved successfully, then the data object can be passed to the &lt;code>*ngFor&lt;/code> loop for looping if it’s a list. Without further ado, let’s get started.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>As always, we will start by creating a new angular project, using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$  ng new ng-async-pipe-error-handling
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to install bootstrap for our &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">User Interface&lt;/a>, feel free to use your favorite package manager.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$  yarn add bootstrap
$ npm install bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, import Bootstrap CSS into your angular project, under your app style section in angular.json.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
  &lt;span style="color:#e6db74">&amp;#34;src/styles.scss&amp;#34;&lt;/span>,
  &lt;span style="color:#e6db74">&amp;#34;node_modules/bootstrap/dist/css/bootstrap.min.css&amp;#34;&lt;/span>
]&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>That’s it for our project setup.&lt;/p>
&lt;h3 id="catching-async-errors">Catching Async Errors&lt;/h3>
&lt;p>First, we need to be able to determine when our async requests returns an error. To do this, in our component, we are going to have an error property, and set it to null.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">errorObject&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The type of the error object may vary depending on the type of request. For instance, if you are running a HTTP request, you might want to use &lt;a href="https://angular.io/api/common/http/HttpErrorResponse">HttpErrorResponse&lt;/a> instead of any. Then, we will use the &lt;a href="https://www.learnrxjs.io/operators/error_handling/catch.html">catchError&lt;/a> &lt;a href="https://www.learnrxjs.io/">RXJS&lt;/a> operator, to tap into the observable. Then, we will set the &lt;code>errorObject&lt;/code> to error we catch inside &lt;code>catchError&lt;/code> operator.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">errorObject&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">asyncOps$&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">asyncService&lt;/span>.&lt;span style="color:#a6e22e">listOfCountries&lt;/span>().&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">catchError&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">errorObject&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>;
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">throwError&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>);
})
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In simple terms, we are tapping into the response of the async request, then checking if there is any error. If an error is caught, we are setting a property of the component class with the error object. Then, inside our template, we will check whether this property is set. If set, we shall parse and display error, otherwise we shall just show a loading animation.&lt;/p>
&lt;h3 id="displaying-a-loading-animation-or-error-message">Displaying a Loading Animation or Error Message&lt;/h3>
&lt;p>Next, inside our template we are going to use async pipe to subscribe to the observable. But, we will use else statement, to show a different template, when the async request is in progress or fails.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;asyncOps$ | async as data; else loadingOrError&amp;#34;&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- code here --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>loadingOrError(ID)&lt;/code> refers to a template which shall have a template for a loading animation or an error message.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-template&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">loadingOrError&lt;/span>&amp;gt; &lt;span style="color:#75715e">&amp;lt;!-- some code here --&amp;gt;&lt;/span> &amp;lt;/&lt;span style="color:#f92672">ng-template&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Inside the &lt;strong>loadingOrError&lt;/strong> template, two possible messages can be displayed. The first one is a loading animation, indicating async request is in progress. And the second option shall display an error, in cases where async request is completed but with error. First, we shall check whether the error object is set. If it’s not set show a loading message or animation, otherwise show the error message.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">ng&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">container&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;errorObject; else loading&amp;#34;&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>
  &lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">div&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-12 text-center&amp;#34;&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>
    &lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">div&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;alert alert-danger&amp;#34;&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>
      {{ &lt;span style="color:#a6e22e">errorObject&lt;/span> }}
    &lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">/div&amp;gt;&lt;/span>
  &lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">/div&amp;gt;&lt;/span>
&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">/ng-container&amp;gt;&lt;/span>
&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">ng&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">template&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">loading&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>
  &lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">div&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-12 text-center&amp;#34;&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>
    &lt;span style="color:#a6e22e">Loading&lt;/span> ...
  &lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">/div&amp;gt;&lt;/span>
&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">/ng-template&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="source-code">Source Code&lt;/h3>
&lt;p>You can find the source code of this post &lt;a href="https://github.com/MainaWycliffe/ng-async-pipe-error-handling">here&lt;/a>.&lt;/p></description></item><item><title>Entry Components in Angular - What are they?</title><link>https://codinglatte.com/posts/angular/entry-components-angular/</link><pubDate>Fri, 07 Dec 2018 12:14:59 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/entry-components-angular/</guid><description>&lt;p>In this post, we are going to look at Entry Components in Angular, what they are and why they even exist. In the simplest terms possible, an entry component in Angular is any component that is loaded by its class, not selector.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Component&lt;/span>({
&lt;span style="color:#a6e22e">selector&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;app-some-component&amp;#39;&lt;/span>, &lt;span style="color:#75715e">// &amp;lt;== component select tags
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">templateUrl&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app.component.html&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">styleUrls&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;./app.component.css&amp;#39;&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppSomeComponent&lt;/span> {
&lt;span style="color:#75715e">// &amp;lt;== Component Class
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Normally, in angular, when loading a component, you use the component selector, inside the template. In the case of the above component, the selector is &lt;code>app-some-component&lt;/code> and the class is &lt;code>AppSomeComponent&lt;/code>. So, normally the above component would be loaded like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-some-component&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-some-component&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This sort of components are declared components and are added as an array inside the declarations section of the app or &lt;a href="https://angular.io/guide/feature-modules">feature module&lt;/a>. But from time to time, you may need to reference to a component by its class. A good example of this is when adding a component to your app router. You refer to the component by the class and not the selector.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">routes&lt;/span>: &lt;span style="color:#66d9ef">Routes&lt;/span> &lt;span style="color:#f92672">=&lt;/span> [
  {
    &lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>,
    &lt;span style="color:#a6e22e">component&lt;/span>: &lt;span style="color:#66d9ef">ComponentClassName&lt;/span>,
    &lt;span style="color:#a6e22e">children&lt;/span>&lt;span style="color:#f92672">:&lt;/span> []
  }
]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Entry components must be registered inside the app or feature module, under entryComponents section. But this does not apply to all components, Angular automatically registers some entry components for you. For instance, any component found in your routes will be registered by Angular CLI during compilation. Therefore, most developer deal with entry components without even realizing so.&lt;/p>
&lt;h2 id="why-do-i-need-to-register-entry-components">Why do I need to register Entry Components&lt;/h2>
&lt;p>Normally, all components are declared inside the app or &lt;a href="https://angular.io/guide/feature-modules">feature module&lt;/a> under declarations. This applies to all components inside your project, whether they have been used or not. This is even before you consider components declared by third party libraries that you might not need in your project.&lt;/p>
&lt;p>If all these unused components were to end up in the final app bundle, they would considerably increase its size. And remember, our goal is to have as small final bundle as possible. To work around this, Angular CLI tree shakes your app during build time. It removes all components that have not been referenced (declared) in your template.&lt;/p>
&lt;p>Now, remember that an entry component is used or referenced by its class and not inside some other components template (at least most of the time). Without a list of entry components, Angular CLI would fail to include these components in the final bundle, hence breaking your application. Therefore, for most entry components, you need to register them under &lt;strong>entryComponents&lt;/strong> array, in your app or &lt;a href="https://angular.io/guide/feature-modules">feature module&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">...
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    &lt;span style="color:#a6e22e">AppComponent&lt;/span>
  ],
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    ...
  ],
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
  &lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
  &lt;span style="color:#a6e22e">entryComponents&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    &lt;span style="color:#a6e22e">SomeEntryComponent&lt;/span>
  ]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> { }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> Commonly used entry components like routing and bootstrap components are automatically registered for us. It would be very painful if you had to keep track and (un)register them manually. If you forget to add an entry component, angular will show the an error message similar or close to this.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/entry-components-angular/images/image1.jpg" alt="Entry Components in Angular" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>So, the next time you encounter such an error, just add it to the list of entry components to your module.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>As you have seen in this post, entry components are overall a good thing. They make it possible to tree shake your app and reduce the final bundle size, without needing any &lt;a href="https://codinglatte.com/tech/developers/angular/optimizing-your-angular-app-using-lazy-loading/">optimization&lt;/a> from the developer. Most developers rarely encounter them, because third party library register their own entry components, although not in all situations. For instance, dialog or modal libraries like &lt;a href="https://material.angular.io/components/dialog/overview">Angular Material Dialog&lt;/a> or &lt;a href="https://ng-bootstrap.github.io/#/components/modal/examples">ng-bootstrap modal&lt;/a>, you are required to register referenced components as entry components. Hope this post helped you understand entry components much better. If you have a topic you would like to see me to cover, leave it in the comment section below.&lt;/p></description></item><item><title>Building a Simple Responsive App with Angular Flex Layout</title><link>https://codinglatte.com/posts/angular/responsive-app-angular-flex-layout/</link><pubDate>Wed, 05 Dec 2018 04:48:36 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/responsive-app-angular-flex-layout/</guid><description>&lt;p>In the last &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-layout-introduction/">post&lt;/a>, which you can find &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-layout-introduction/">here&lt;/a>, we introduced Angular Flex Layout. We looked at the APIs/Directives available to you as a developer and how you can use them. In this post, we are going to build on that foundation.&lt;/p>
&lt;p>Our goal here is very simple, building a simple responsive card list, that will respond to different viewports. In this post, we are going to be using &lt;a href="https://material.angular.io/">Angular 2 Material&lt;/a> for the UI, but feel free to use a &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI Library&lt;/a> of your choice. Without further ado, let’s get started.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>We will start by creating a new Angular Project, using Angular CLI &lt;a href="https://github.com/angular/angular-cli/wiki/new">&lt;code>ng new command&lt;/code>&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng new angular-flex-layout-demo
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we need to install Angular Flex Layout, Material and &lt;a href="https://material.angular.io/cdk/categories">CDK&lt;/a> (Content Development Kit) for this demo.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng add @angular/material @angular/cdk
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;a href="https://angular.io/cli/add">&lt;code>ng add&lt;/code>&lt;/a> will install and setup Angular Material and CDK automatically.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ yarn add @angular/flex-layout
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After that, we are going to import &lt;code>FlexLayoutModule&lt;/code> from Angular Flex Layout and &lt;code>MatCardModule&lt;/code>, &lt;code>MatButtonModule&lt;/code> from Angular Material inside our App Module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/flex-layout&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MatButtonModule&lt;/span>, &lt;span style="color:#a6e22e">MatCardModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/material&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">/* ... */&lt;/span>
],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span>,
&lt;span style="color:#a6e22e">MatButtonModule&lt;/span>,
&lt;span style="color:#a6e22e">MatCardModule&lt;/span> &lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now that we have set up our project, let’s move on to the next part, building a responsive card list UI.&lt;/p>
&lt;h3 id="container-for-our-angular-app">Container for our Angular App&lt;/h3>
&lt;p>First, we are going to define the root container of our application. We are going to set the width to 100%, using &lt;code>fxFlex&lt;/code> and then set the flex layout to column, using &lt;code>fxLayout&lt;/code>. You can set the width to 100% by just adding &lt;code>fxFlex&lt;/code> or by assigning it a value of 100% i.e. &lt;code>fxFlex=&amp;quot;100%&amp;quot;&lt;/code>.&lt;/p>
&lt;p>The column layout, set using &lt;code>fxLayout&lt;/code>, forces all the children to be stacked vertically while inheriting the parent container width. We are also going to add a gap between our child elements of 10px using &lt;code>fxLayoutGap&lt;/code>, so they don’t get too close to each other. Feel free to refer to the previous post &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-layout-introduction/">here&lt;/a> for what individual directives do.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayoutGap&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;10px&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;height:100vh&amp;#34;&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- content here --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="building-a-responsive-card-user-interface">Building a Responsive Card User Interface&lt;/h3>
&lt;p>We will start by setting up a container for our cards. This is where we will define the relationship between the cards (child elements of the container) like the flow of the card – horizontally or vertically. Here, we need our elements to flow horizontally but wrap when they get to the end. So, in this case, we will use &lt;code>fxLayout=&amp;quot;row wrap&amp;quot;&lt;/code> instead of just &lt;code>row&lt;/code> alone.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row wrap&amp;#34;&lt;/span>&amp;gt;&lt;span style="color:#75715e">&amp;lt;!-- card list here --&amp;gt;&lt;/span>&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please note, we did not set the width because it will automatically inherit the width from the parent container which has a flex layout of column, so by default it is 100%. Next, let’s add some responsive cards. We can add the cards directly, but since we want a uniform padding of 5px around the card, and since there is no way of doing so with material cards component, we will wrap it around a container.&lt;/p>
&lt;p>The card container will carry all the responsive properties. First, we need to set the width of the card based on the browser&amp;rsquo;s viewport, we will use &lt;code>fxFlex&lt;/code> directive, followed by the breakpoint of the device viewport we are targeting, separated by a &lt;code>dot(.)&lt;/code>. For instance, for extra small devices (xs) &lt;code>fxFlex.xs=&amp;quot;100&amp;quot;&lt;/code> or for medium devices(md) &lt;code>fxFlex=&amp;quot;33.3&amp;quot;&lt;/code>. And then, we need to set the layout (&lt;code>fxLayout&lt;/code>) to column, ensuring the material card will fill the width.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let card of cardList&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;25&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">md&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;33&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;50&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">xs&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;padding: 5px;&amp;#34;&lt;/span>
&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- material card here --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For breakpoints, you can refer to the table below:&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/11/angular-flex-layout-breakpoints.jpg" alt="Angular Flex Layout – Introduction &amp; Getting Started">&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;code>cardList&lt;/code> is a property of our component, will a list of 10 cards, created &lt;a href="https://angular.io/guide/lifecycle-hooks">&lt;code>ngOnInit&lt;/code>&lt;/a> method.&lt;/p>
&lt;/blockquote>
&lt;p>You can view the components class &lt;a href="https://github.com/MainaWycliffe/angular-flex-layout-responsive-demo/blob/master/src/app/app.component.ts">here&lt;/a> for more details. This allows us to use &lt;a href="https://angular.io/guide/displaying-data">&lt;code>*ngFor&lt;/code>&lt;/a> to loop over it creating 10 cards, or any number we wish to. Angular Material Card Component For our &lt;a href="https://material.angular.io/components/card/overview">&lt;code>card&lt;/code>&lt;/a>, it will be just a normal card, nothing special about it, you can easily replace it with anything:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-card&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">img&lt;/span> &lt;span style="color:#a6e22e">mat-card-image&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">src&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">card&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">imgSrc&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> /&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-card-title&lt;/span>&amp;gt; {{ card.title }} &amp;lt;/&lt;span style="color:#f92672">mat-card-title&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-card-content&lt;/span>&amp;gt; {{ card.description }} &amp;lt;/&lt;span style="color:#f92672">mat-card-content&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-card-footer&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span> &lt;span style="color:#a6e22e">mat-flat-button&lt;/span> &lt;span style="color:#a6e22e">color&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;primary&amp;#34;&lt;/span>&amp;gt;Do Something Button&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-card-footer&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-card&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="final-code">Final Code&lt;/h3>
&lt;p>You can find the code for this post &lt;a href="https://github.com/MainaWycliffe/angular-flex-layout-responsive-demo">here&lt;/a>.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>In this post, we saw how we can build simple responsive layout using Angular Flex Layout. Hopefully, this gave you an idea on how you can integrate angular flex layout in your projects. In a future post, we are going to cover adaptive layouts design using Angular Flex Layout. If you have any topic suggestions or questions, feel free to leave them in the comment section below.&lt;/p></description></item><item><title>Angular Flex Layout – Introduction &amp; Getting Started</title><link>https://codinglatte.com/posts/angular/angular-flex-layout-introduction/</link><pubDate>Mon, 19 Nov 2018 02:10:07 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-flex-layout-introduction/</guid><description>&lt;p>In this post, I am going introduce and look at how you can get started with Angular Flex Layout. We will briefly introduce the APIs for Angular Flex Layout and look at how to add it to your project. Angular Flex Layout is a stand-alone library developed by the Angular Team for designing sophisticated layouts. If you have used &lt;a href="https://getbootstrap.com/docs/4.1/getting-started/introduction/">Bootstrap&lt;/a> before, this provides only the &lt;a href="https://getbootstrap.com/docs/4.1/layout/overview/">Layout (Grid) Component&lt;/a> only.&lt;/p>
&lt;p>This means that you can use it in combination with other UI frameworks not just Angular 2 Material. Unlike bootstrap though, it uses &lt;a href="https://angular.io/guide/attribute-directives">directives&lt;/a> based API instead of CSS Classes. I find this to be more powerful and flexible compared to Bootstrap. Before we get started, please note that, this library is still in beta. Don’t let that stop you from using it though since it’s pretty stable and have used it in production before.&lt;/p>
&lt;p>One more thing to note, browser support can be an issue, if your users are using older browsers such as IE. But, as it currently stands over 90% of users currently have browsers that supports CSS flexbox. Please note, this also affects &lt;a href="https://getbootstrap.com/docs/4.0/getting-started/browsers-devices/">Bootstrap 4&lt;/a> as both use &lt;a href="https://www.w3schools.com/css/css3_flexbox.asp">CSS Flexbox&lt;/a>. For older browser support, I would recommend older versions of Bootstrap.&lt;/p>
&lt;div class="column">
&lt;amp-img sizes="(min-width: 35em) 1200px, 100vw" srcset='
https://codinglatte.com/posts/angular/angular-flex-layout-introduction/CSS-Flexbox-Support-1024x656_hu267b5a4ec0b938499b2cbf6e4ea75c84_194775_500x0_resize_q75_box.jpg 500w
, https://codinglatte.com/posts/angular/angular-flex-layout-introduction/CSS-Flexbox-Support-1024x656_hu267b5a4ec0b938499b2cbf6e4ea75c84_194775_800x0_resize_q75_box.jpg 800w
, /posts/angular/angular-flex-layout-introduction/CSS-Flexbox-Support-1024x656_hu267b5a4ec0b938499b2cbf6e4ea75c84_194775_1200x0_resize_q75_box.jpg 1200w
' alt="Angular Flex Layout - Browser Support" class="contain" layout="fill">
&lt;/div>
&lt;h3 id="static-design-apis-directives">Static Design APIs (Directives)&lt;/h3>
&lt;p>First, let’s walk over the essential APIs you need to be aware of to get started. This APIs are also known as static APIs. I am going to try and keep things simple and straight forward. We are going to divide this APIs into 3 groups, based on where and how they are used: The first group will cover APIs for containers – parent containers i.e. DIVs. While the second will cover APIs for container elements – html elements inside the container from the first group. And the third will cover APIs that can be applied on any element regardless of whether it’s a container or a container element.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>The Angular Flex Layout APIs are accessed through &lt;a href="https://angular.io/guide/attribute-directives">Angular directives&lt;/a>.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;h4 id="parent-containers">Parent Containers&lt;/h4>
&lt;h5 id="fxlayout">fxLayout&lt;/h5>
&lt;p>This directive allows you to determine how the child elements within the parent container relate to each other. There are 5 possible values: &lt;code>row&lt;/code>, &lt;code>column&lt;/code>, &lt;code>row-reverse&lt;/code>, &lt;code>column-reverse&lt;/code> and &lt;code>row wrap&lt;/code>. Row dictates that all child elements are in a single row, doesn’t matter if they fit or don’t fit inside the parent container. And this is why we have &lt;code>row wrap&lt;/code>, which allows elements to overwrap to the next line if they don’t fit in the current container. Column on the other hand, sets one item per row and that’s it. The default value is &lt;code>row&lt;/code>.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row wrap&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="fxlayoutalign">fxLayoutAlign&lt;/h5>
&lt;p>As the name suggests, this directive will define the alignment of the child elements within the container. It accepts one or two values, with the first value defining the main-axis alignment and second value cross-axis alignment. Possible values for main-axis alignment are: start, center, end, space-around, space-between. While possible values for cross-axis alignment are: start, center, end and stretch. Example:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">fxLayoutAlign=&amp;#34;center center&amp;#34;
&lt;span style="color:#75715e">&amp;lt;!--align center bother horizontally and
&lt;/span>&lt;span style="color:#75715e">vertically. --&amp;gt;&lt;/span>
fxLayoutAlign=&amp;#34;center end&amp;#34;
&lt;span style="color:#75715e">&amp;lt;!-- align center horizontally and bottom
&lt;/span>&lt;span style="color:#75715e">vertically. --&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>Main-axis and cross-axis vary based on the layout used. For instance, when using row for the layout, cross-axis is the vertical alignment and when using column for the layout, it becomes the horizontal alignment. You can learn more about cross-axis alignment &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Cross_Axis">here&lt;/a> and main-axis alignment &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Main_Axis">here&lt;/a>.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;h5 id="fxlayoutgap">fxLayoutGap&lt;/h5>
&lt;p>This directive defines the space between child elements within the container. The value can be given in &lt;code>px, % , vh or vw&lt;/code>. There isn’t a lot to say about this specific directive.&lt;/p>
&lt;h4 id="containers-elementschildren">Containers Elements/Children&lt;/h4>
&lt;h5 id="fxflex">fxFlex&lt;/h5>
&lt;p>This directive allows you to set the width of an element. You can use percentage, pixel or any other acceptable measurement unit. If you add it without any value (just fxFlex), it will fill the remaining width of the parent html element. This means that, if you had two elements within the same container, with the first having a fixed width of 100px, then the second element will occupy the remaining width. This means that, the width of the second container will always be 100% - 100px. The order of the elements doesn’t matter at all. And if you had multiple elements, with fxFlex only without a specific value, then the width is divided equally between the elements. This only applies to elements inside a container with a flex layout of row (or row wrap) not column. For columns, the default width of the elements within is 100% unless otherwise provided using this directive.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>if you don’t specify the unit of measure (i.e. px, vh, vw or %) it defaults to percentage point, so leaving it as 70, it will be translated as 70%.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;h5 id="fxflexoffset">fxFlexOffset&lt;/h5>
&lt;p>This sets the margin between the current html element and the last element within a fxLayout container. If it’s the first element, then it sets the distance between the border of the parent container and the start of the element. It accepts %, px, vh or vh for its values.&lt;/p>
&lt;h5 id="fxfill-or-fxflexfill">fxFill or fxFlexFill&lt;/h5>
&lt;p>This directive instructs a child html element to fill the height and the width of the parent contains.&lt;/p>
&lt;h5 id="fxflexorder">fxFlexOrder&lt;/h5>
&lt;p>Defines the position of the current elements within a fxLayout container. It accepts only integers indicating the position of the current element among the other elements.&lt;/p>
&lt;h5 id="fxflexalign">fxFlexAlign&lt;/h5>
&lt;p>This overrides the parents cross-axis alignment, set using fxLayoutAlign above, for an element within an fxLayout container. Something to note here, it doesn’t affect the main-axis alignment, it only affects the cross-axis alignment.&lt;/p>
&lt;h4 id="general-usage-apis-directives">General usage APIs (Directives)&lt;/h4>
&lt;p>The following directives (APIs) can be use on any html element regardless of whether its container, container element or none.&lt;/p>
&lt;ol>
&lt;li>&lt;code>fxHide&lt;/code> and &lt;code>fxShow&lt;/code> – These two directives basically allow you to hide or show the current html elements and all its children.&lt;/li>
&lt;li>&lt;code>ngClass&lt;/code> and &lt;code>ngStyles&lt;/code> – These two directives allows you to set classes and styles to a html element. They are an extension of angular directives with the same names.&lt;/li>
&lt;li>&lt;code>imgSrc&lt;/code> – This directive is an extension of the native html &lt;code>src&lt;/code> attribute for setting the source of the image html element.&lt;/li>
&lt;/ol>
&lt;h3 id="what-about-responsive-design">What about Responsive Design?&lt;/h3>
&lt;p>In summary, the above directives (APIs) help you to define how elements behave and look like. In this section we are going to look at how you can use the above statics APIs together with Angular Flex Layout responsive APIs. Angular Flex Layout has a set of breakpoints predefined for responsive design, each of this breakpoint has name, known as alias and defines the minimum and maximum width of the breakpoint alias. It uses media Query to determine the width of the current &lt;a href="https://www.w3schools.com/css/css_rwd_viewport.asp">viewport&lt;/a>.&lt;/p>
&lt;p>Here is a list of available breakpoints for Angular Flex Layout. Layout&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-flex-layout-introduction/angular-flex-layout-breakpoints.jpg" alt="Angular Flex Layout - Media Breakpoints" width="400" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>To use the above breakpoints, you combine a static API with an alias, separated by a &lt;code>. (dot)&lt;/code> as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">fxLayout.md=&amp;#34;row&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">fxFlex.lt-lg=&amp;#34;100%&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">ngClass.xs=&amp;#34;some-css-class&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">imgSrc.gt-md=&amp;#34;url-to-large-image&amp;#34; imgSrc=&amp;#34;url-to-normal-size-image&amp;#34;
imgSrc.xs=&amp;#34;url-to-very-small-img&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: That last example allows you to set the appropriate image based on the screen size. It uses &lt;code>gt-md&lt;/code> alias to set a large image src for devices larger than medium, &lt;code>xs&lt;/code> to set a small image src for extra small devices. For other devices that don’t fall in to the two categories, it uses the image source that is set without an alias. In this case, the image being used by the img element will vary based on the device viewport. This approach can be applied with any angular flex layout static API directive, not just the examples given above.&lt;/p>
&lt;/blockquote>
&lt;p>As shown above, this approach provides a very flexible and powerful to responsive design, allowing you to change flexbox layout, classes, styles, image src depending on the size of the viewport. This also has the advantage of being close to your component logic, you can use properties for some of these values instead of just static values. Or this is without touching any CSS at all. On top of that, it provides an opportunity for Adaptive Design, an improvement to responsive design, that I have discussed previously &lt;a href="https://codinglatte.com/tech/developers/angular/adaptive-layout-design-angular-flex-layout/">here&lt;/a>.&lt;/p>
&lt;h3 id="adding-angular-flex-layout-to-your-project">Adding Angular Flex Layout to your Project&lt;/h3>
&lt;p>First, install Angular Flex Layout using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">
$ yarn add @angular/flex-layout
$ npm install @angular/flex-layout
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then import it to your app module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/flex-layout&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span> &lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, you can go ahead and start using the angular flex layout APIs inside your templates.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>This post was just an introduction to Angular Flex Layout. In a follow up post in the future, we will cover comprehensive examples on using Angular Flex Layout for building a responsive web app. For the time being, you can go over the official documentation &lt;a href="https://github.com/angular/flex-layout/wiki">here&lt;/a> for more material and examples on Angular Flex Layout.&lt;/p></description></item><item><title>Building a Wrapper for Responsive Design for Angular Flex Layout</title><link>https://codinglatte.com/posts/angular/wrapper-responsive-design-angular-flex-layouts/</link><pubDate>Sun, 11 Nov 2018 15:05:16 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/wrapper-responsive-design-angular-flex-layouts/</guid><description>&lt;p>Angular Flex Layout is designed to provide a comprehensive layout design using CSS Flexbox and Media Query. Unlike most other libraries, it doesn’t use CSS Classes but rather uses directives. It also makes it easy to manipulate DOM. On top of that, you can inject it into the component class, if you wanted to change code behavior based on the device width. You can learn more about Angular Flex Layout &lt;a href="https://github.com/angular/flex-layout/wiki">here&lt;/a>.&lt;/p>
&lt;p>While working with Angular Flex Layout, while powerful, your templates can get messy very quickly. This also leads a lot of copy-pasting. Let’s take a simple example, to build a responsive layout with 100% height, 70% width on large devices and 100% on small devices, and the content centered, you need the following code:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;height: 100vh&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;70&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlexOffset&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;15&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxLayoutAlign&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;center center&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">lt-lg&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlexOffset&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">lt-lg&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;0&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;border: solid thin #000000;&amp;#34;&lt;/span>
&amp;gt;
content here
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For a small project, this is manageable, but as your project grows, it can escalate to messy and unmanageable very quickly. Imagine yourself in a situation where you need that exact same responsive design in multiple places. You can reduce the occurrences by nesting your project routes wisely, but that will only take you so far. And God forbid, you want to make some adjustment.&lt;/p>
&lt;h3 id="our-goal">Our Goal&lt;/h3>
&lt;p>In this post, we are going to build a wrapper that will reduce the repetition of the above code to manageable level. The goal is simple, have a few wrappers for various responsive layouts scenarios inside your project. You could have a wrapper for forms, tables, cards etc. So, instead of writing all the above code every time, you can simplify it to the following:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-flex-layout-wrapper&lt;/span>&amp;gt; &lt;span style="color:#75715e">&amp;lt;!-- HTML Content Here --&amp;gt;&lt;/span> &amp;lt;/&lt;span style="color:#f92672">app-flex-layout-wrapper&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is easier to read, and the code is cleaner.  But more importantly, it is very easy to adjust your layouts without going over a torn of code. On top of that, it allows you to maintain the format of your template. This builds on top of the concept of &lt;a href="https://codinglatte.com/tech/developers/angular/reusable-components-angular/">re-usable components&lt;/a> in Angular. This is because these wrappers can be re-used across your project and without limitation.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>We will start by building a &lt;a href="https://github.com/angular/angular-cli/wiki/new">new project&lt;/a> in Angular, using &lt;a href="https://github.com/angular/angular-cli/wiki">Angular CLI&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng new angular-flex-layout-wrapper-demo
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we are going to install Angular Flex Layout and Angular CDK.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ yarn add @angular/flex-layout @angular/cdk
$ npm install @angular/flex-layout @angular/cdk
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then inside our app module, we are going to import &lt;code>FlexLayoutModule&lt;/code> from Angular Flex Layout.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/flex-layout&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    &lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span>
   
  ]
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
  &lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it for our project setup. Let’s now build our wrapper.&lt;/p>
&lt;h3 id="wrapper-component-for-our-responsive-layouts">Wrapper Component for our Responsive Layouts&lt;/h3>
&lt;p>If you look at our wrapper, you will notice we are using it just like a normal HTML element (DIVs, Ps). But if you have worked with Angular before, you know by default component don’t work like that. The content in between the component tags, is usually replaced by the component content once rendered. But in our case, we want this to feel like native html elements that we are already used to.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-flex-layout-wrapper&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- we want to be able to any html content here --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">app-flex-layout-wrapper&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To achieve this, we are going to use &lt;code>ng-content&lt;/code> to define a slot within our wrapper component content to add content dynamically. The content in between the component tags, is then dynamically added in the defined location. Let’s build this now. First, let’s we need to generate a &lt;a href="https://github.com/angular/angular-cli/wiki/generate-component">new component&lt;/a> using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng generate component flex-layout-wrapper
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then inside our component template, we just need to define our responsive layout and then, a slot to dynamically project our content using &lt;code>ng-content&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;height: 100vh&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;70&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlexOffset&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;15&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxLayoutAlign&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;center center&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">lt-lg&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlexOffset&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">lt-lg&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;0&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;border: solid thin #000000;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-content&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">ng-content&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- Content will be projected here --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, any content that we add in between our component selector tags, will be added in the section defined by &lt;code>ng-content&lt;/code> inside our wrapper template. When this content is projected inside the template, it follows the constraints defined by the div containers which will act as its parent.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>The above methods allows you to pre-define a set of wrappers or containers for your different layouts. This reduces code duplication and makes it easy to make changes and adjustments. On top of that, this leads to consistency in your project design. Inside the component tags, you can build your template just as you would in any other situation. And formatting by your text editor should not affected at all. Thank you for getting this far, if you are interested here are a few more posts covering Angular Flex Layout.&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/building-adaptive-layouts-using-angular-flex-layout/">How to Build Adaptive Layout Designs using Angular Flex Layout&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/adaptive-layout-design-angular-flex-layout/">Adaptive Layout Design – Angular Flex Layout&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/responsive-navbar-angular-flex-layout/">Responsive Navbar with Angular Flex Layout&lt;/a>&lt;/li>
&lt;/ol></description></item><item><title>How to Build Custom Pipes in Angular</title><link>https://codinglatte.com/posts/angular/custom-pipes-angular/</link><pubDate>Tue, 06 Nov 2018 13:17:04 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/custom-pipes-angular/</guid><description>&lt;p>In simple terms, pipes allow us to write display value transformation right inside the template. Angular comes with stock or built in pipes to transform your values to what you want the user to see. For instance, the Date Pipe, allows you to change the date format and other aspects related to the date. To use a pipe inside the template, you use the pipe operator (&lt;code>|&lt;/code>), the pipe on the right and the value on the left.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">{{ dateValue | date }}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And you can pass arguments, such as the date format you wish to use or how you want a currency to be formatted.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">{{ dateValue | date: format }}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And, you can chain multiple pipes if you wish, you just need to add the pipe operator after every pipe.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">{{ value | pipe1 | pipe2 }}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The great thing about pipes is that they are applied to variables right before display and doesn’t require you to change the original value. Pipes make you code readable and &lt;a href="//tech/developers/angular/reusable-components-angular/">re-usable&lt;/a>, as compared to using components methods to transform method. This also makes it easier to track bugs and update if need arises. The built-in pipes are great, but can take you so far, now let’s see how we can build our own pipe.&lt;/p>
&lt;h3 id="overview">Overview&lt;/h3>
&lt;p>Before we can get into the thick of it, let’s first go over what we are trying to achieve in this post. Let’s say you have a country code (ISO Standard) and wanted to transform that to either country name or currency used by the said country. This is a very simple pipe, but most pipes are mostly like this. Your list of countries is in this format:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">CA&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
  &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Canada&amp;#39;&lt;/span>,
  &lt;span style="color:#66d9ef">native&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Canada&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">phone&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">continent&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;NA&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">capital&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Ottawa&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">currency&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;CAD&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">languages&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;en&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;fr&amp;#39;&lt;/span>]
},
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Given the country code, you might want to get the country name, currency or official language. One way to achieve this, is to build a service, then inject it into the component controller. And then create a method to call it from your template. This requires you to add at least several lines of code to both your template and component controller (class). But with a pipe, it’s a matter of calling the pipe and passing an argument of the field you want:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">{{ &amp;#39;CA&amp;#39; | countries:&amp;#39;currency&amp;#39; }}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>With a single line of code, you can transform your country code to the country name, currency or capital city of the country you want.&lt;/p>
&lt;h3 id="building-our-custom-pipe">Building our Custom Pipe&lt;/h3>
&lt;p>We will start by creating a new angular project using Angular CLI (Angular 7, but this will work with Angular 6, 5 and I am guessing 4). If you already have a project, you can skip this part out.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng new pipes-demo
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> If you are using Angular 7, you will be prompted to add routing and which style sheet to use, select no and CSS in each case. This is because of &lt;a href="//tech/developers/angular/angular-7-news-updates/">CLI Prompts&lt;/a> introduced in Angular 7.&lt;/p>
&lt;/blockquote>
&lt;p>Next, let’s use Angular CLI to &lt;a href="https://github.com/angular/angular-cli/wiki/generate-pipe">generate&lt;/a> a pipe, we shall call the pipe countries.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng generate pipe countries
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you open the newly created pipe, it will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">...
&lt;span style="color:#66d9ef">@Pipe&lt;/span>({
  &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;countries&amp;#39;&lt;/span>
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CountriesPipe&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">PipeTransform&lt;/span> {
  &lt;span style="color:#a6e22e">transform&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>, &lt;span style="color:#a6e22e">args?&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span> {
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Inside the transform method of the class &lt;strong>Countries Pipe&lt;/strong>, is where our logic will end up. We will start by renaming the methods parameters, from &lt;code>value&lt;/code> and &lt;code>args&lt;/code> to &lt;code>code&lt;/code> and &lt;code>field&lt;/code>. Then, we can simply get the country through the by code (Our list is keyed using &lt;code>country code&lt;/code>) and the field we want just like any other array.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">transform&lt;/span>(&lt;span style="color:#a6e22e">code&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">field&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span> {
  &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">code&lt;/span>) {
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">CountriesList&lt;/span>[&lt;span style="color:#a6e22e">code&lt;/span>][&lt;span style="color:#a6e22e">field&lt;/span>];
  }
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>&lt;em>NB:&lt;/em>&lt;/strong> &lt;code>CountriesList&lt;/code> is an object containing list of countries.&lt;/p>
&lt;/blockquote>
&lt;p>You can add any amount of logic inside the transform method, that you would add inside components controller. For instance, you can filter an array that is not keyed:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">country&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">CountriesList&lt;/span>.&lt;span style="color:#a6e22e">filter&lt;/span>(&lt;span style="color:#a6e22e">country&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">country&lt;/span>.&lt;span style="color:#a6e22e">code&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">country&lt;/span>;
}
});
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">country&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>][&lt;span style="color:#a6e22e">field&lt;/span>];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Unlike component methods, a pipe can be used through your project without a lot of extra effort.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>TIP:&lt;/strong> &lt;em>You can also inject services and other dependencies in your pipe to use them to transform your data, if need arises.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;h3 id="using-pipes-with-lazy-loading">Using Pipes with Lazy Loading&lt;/h3>
&lt;p>If you are using &lt;a href="//tech/developers/angular/optimizing-your-angular-app-using-lazy-loading/">lazy loading&lt;/a>, the same limitation that apply to components apply to pipes. For instance, you cannot declare a custom pipe in more than one module. And a pipe must be declared in the module closest to the component you are using. To work around this, you need a shared module. This is where you will declare and export your pipe or pipes, among other directives and components. You can generate a module inside the project using the &lt;a href="https://github.com/angular/angular-cli/wiki/generate-module">ng generate module&lt;/a> command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng generate module pipes-module
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then declare your pipe and export it inside the module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">CountriesPipe&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">CommonModule&lt;/span>],
&lt;span style="color:#a6e22e">exports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">CountriesPipe&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">PipesModuleModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, you can just import the module in any lazy loaded module you want to use the pipes in.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">BrowserModule&lt;/span>, &lt;span style="color:#a6e22e">PipesModuleModule&lt;/span>],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about lazy loading in Angular &lt;a href="//tech/developers/angular/optimizing-your-angular-app-using-lazy-loading/">here&lt;/a>.&lt;/p></description></item><item><title>Angular Reactive Forms - Dynamic Form Fields using FormArray</title><link>https://codinglatte.com/posts/angular/angular-dynamic-form-fields-using-formarray/</link><pubDate>Sat, 27 Oct 2018 12:06:28 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-dynamic-form-fields-using-formarray/</guid><description>&lt;p>In most cases, forms have constant form controls  – remaining static throughout the lifetime of the form. But from time to time, you can find yourself in a situation where you would like to dynamically add or remove form controls. These form controls are added dynamically as result of user interaction. On top of that, you might also want to be able to validate data of the newly created forms. Therefore, having optional fields might not be an option.&lt;/p>
&lt;p>In this post, we are going to look at how we can do this in Angular, in Reactive Forms using FormArray. We will be creating a simple angular app, for adding user profile. The user profile form will have the following fields: name, organization (optional) and variable contact information.&lt;/p>
&lt;amp-youtube data-videoid="CnOC8gXBvj0" layout="responsive" width="480" height="270">&lt;/amp-youtube>
&lt;p>The contact information group will have a type of contact (email or phone number), label for the contact and the contact value. We also want to give our users the ability to add more contacts, so that a single profile can have multiple contacts. On top of that, since the type of contact can vary, we also want to change the validator of the contact value based on the selected type.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>We will start by creating a new project using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng new angular-dynamic-form-fields-reactive-forms
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to install our dependencies. In this case, we will be using bootstrap, the only dependency we need.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ npm install bootstrap
$ yarn add bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After installing bootstrap, import it to your angular project inside &lt;code>angular.json&lt;/code>, in the style section.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
  &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
  &lt;span style="color:#e6db74">&amp;#34;node_modules/bootstrap/scss/bootstrap.scss&amp;#34;&lt;/span>
]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, in your app module, import &lt;code>ReactiveFormsModule&lt;/code>, which is the only import we need for this post.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">BrowserModule&lt;/span>, &lt;span style="color:#a6e22e">ReactiveFormsModule&lt;/span>],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now that we have setup our project, let’s build our demo application.&lt;/p>
&lt;h3 id="building-a-model-for-our-reactive-form">Building a Model for our Reactive Form&lt;/h3>
&lt;p>We will start by defining a base form group that defines our three form controls – name, organization and contacts. The name and organization form controls won’t change anything dynamically. On the other hand, the contacts form controls will be composed of an array of form groups, with individual form group having 3 form controls. To achieve this, we will be using FormArray, which accepts an array of Form Groups or Form Controls. We will be grouping the form controls for a single contact, under a single form group. Then this multiple form groups will be added into the  FormArray. Each form group will contain three form controls: Contact Type, Label and Value. The value of the contact can either be a phone number or an email based on the contact type. First, import the necessary modules we require: FormBuilder, FormArray, FormGroup and Validators.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">FormArray&lt;/span>, &lt;span style="color:#a6e22e">FormBuilder&lt;/span>, &lt;span style="color:#a6e22e">FormGroup&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/forms&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, let’s define two properties in our component class: form and contacts properties. The first holds our form model and the second holds our contacts forms array:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">form&lt;/span>: &lt;span style="color:#66d9ef">FormGroup&lt;/span>;
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">contactList&lt;/span>: &lt;span style="color:#66d9ef">FormArray&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s define a method to create our contacts form group. The method will return the three form controls, inside a form group.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">createContact&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">FormGroup&lt;/span> {
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({
    &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;email&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])],
    &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])],
    &lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>])]
  });
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, let’s initialize our form, with a single contact as the initial contact. Then users can add more contacts as they wish.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">form&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({
    &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])],
    &lt;span style="color:#a6e22e">organization&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>],
    &lt;span style="color:#a6e22e">contacts&lt;/span>: &lt;span style="color:#66d9ef">this.fb.array&lt;/span>([&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">createContact&lt;/span>()])
  });
&lt;span style="color:#75715e">// set contactlist to the form control containing contacts
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contactList&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">form&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;contacts&amp;#39;&lt;/span>) &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">FormArray&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="addingremoving-form-controls-dynamically-using-formarray">Adding/Removing Form Controls Dynamically using FormArray&lt;/h3>
&lt;p>Since contact list is an array, it’s a simple matter of pushing new items to the array, just like a normal array. It doesn’t matter whether you are adding a form group, as is our case, or adding a form control, the process is the same.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// add a contact form group
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#a6e22e">addContact() {&lt;/span>
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contactList&lt;/span>.&lt;span style="color:#a6e22e">push&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">createContact&lt;/span>());
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The same goes for removing contacts from the contacts FormArray, it’s a normal array and all you need is the index. We will pass the index of the item we are removing as a parameter for the &lt;strong>removeContact&lt;/strong>() method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">
&lt;span style="color:#75715e">// remove contact from group
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#a6e22e">removeContact&lt;/span>(&lt;span style="color:#a6e22e">index&lt;/span>) {
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contactList&lt;/span>.&lt;span style="color:#a6e22e">removeAt&lt;/span>(&lt;span style="color:#a6e22e">index&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="changing-form-control-validators-dynamically">Changing Form Control Validators Dynamically&lt;/h3>
&lt;p>If you recall from the beginning, we also wanted to change the &lt;a href="//tech/developers/angular/angular-building-custom-validators/">validation&lt;/a> of the contact in the contacts group based on the type of contact. If it is an email, we validate against email only and if its phone, only against phone numbers. We are trying to avoid a situation where the type of value of the contact and the type of contact are not the same. But, first we need to create a method to get the form group we want, mainly to make our code more readable. We will call our method &lt;strong>getContactsFormGroup(index)&lt;/strong> method and returns a form group.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">getContactsFormGroup&lt;/span>(&lt;span style="color:#a6e22e">index&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">FormGroup&lt;/span> {
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contactList&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">form&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;contacts&amp;#39;&lt;/span>) &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">FormArray&lt;/span>;
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">formGroup&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contactList&lt;/span>.&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">FormGroup&lt;/span>;
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">formGroup&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>With the above method, instead of writing this in our code to get a contact form group controls value.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">formGroup&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">contactList&lt;/span>.&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">FormGroup&lt;/span>;
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">formGroup&lt;/span>.&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;value&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">value&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We only need to write only this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">getContactsFormGroup&lt;/span>(&lt;span style="color:#a6e22e">index&lt;/span>).&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;value&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">value&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This makes our code a lot easier to read and follow, and we are using the same method inside the template for checking validation errors. Next, we need to add a method to change the validator for the value of the contact, when the type of the contact changes. We will call the method &lt;strong>changedContactType(index)&lt;/strong> and will be triggered by the change event of the form control.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">changedContactType&lt;/span>(&lt;span style="color:#a6e22e">index&lt;/span>) {
  &lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">validators&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">getContactsFormGroup&lt;/span>(&lt;span style="color:#a6e22e">index&lt;/span>).&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;type&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#e6db74">&amp;#39;email&amp;#39;&lt;/span>) {
    &lt;span style="color:#a6e22e">validators&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>]);
  } &lt;span style="color:#66d9ef">else&lt;/span> {
    &lt;span style="color:#a6e22e">validators&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([
      &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>,
      &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">pattern&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> RegExp(&lt;span style="color:#e6db74">&amp;#39;^\\\+[0-9]?()[0-9](\d[0-9]{9})\$&amp;#39;&lt;/span>)) &lt;span style="color:#75715e">// pattern for validating international phone number
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    ]);
  }
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">getContactsFormGroup&lt;/span>(&lt;span style="color:#a6e22e">index&lt;/span>).&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;value&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">setValidators&lt;/span>(&lt;span style="color:#a6e22e">validators&lt;/span>);
&lt;span style="color:#75715e">// re-validate the inputs of the form control based on new validation
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">getContactsFormGroup&lt;/span>(&lt;span style="color:#a6e22e">index&lt;/span>).&lt;span style="color:#a6e22e">controls&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;value&amp;#39;&lt;/span>].&lt;span style="color:#a6e22e">updateValueAndValidity&lt;/span>();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="building-the-template-for-our-form">Building the Template for Our Form&lt;/h3>
&lt;p>In most parts, this will be a normal form until you get to rendering the FormArray section. Here, we are going to loop over the contacts FormArray, and render the form groups into a form for user to interact with. We start by defining a FormArray, the same way you define a form group or a form control inside the template. We will be using the &lt;strong>formArrayName&lt;/strong> directive to indicate we are now rendering a FormArray in our template.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">formArrayName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;contacts&amp;#34;&lt;/span>&amp;gt;&lt;span style="color:#75715e">&amp;lt;!-- Loop Here --&amp;gt;&lt;/span>&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, let’s go ahead and loop over our contacts FormArray. To do that, we are going to first define a get method, inside our class to fetch the contact FormArray from the form group and typecast it, into a FormArray.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">get&lt;/span> &lt;span style="color:#a6e22e">contactFormGroup() {&lt;/span>
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">form&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;contacts&amp;#39;&lt;/span>) &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">FormArray&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we are going to simply loop over the contact FormArray returned by the above get method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-6&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let contact of contactFormGroup.controls; let i = index;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">formGroupName&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- Contacts Form controls Here --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: We are using index as the name of the form group. Also, do not use track by method for this loop, as index changes when an item that’s not at the end gets removed. We want to the whole list to be re-rendered when an item is removed or added. This is because, when an item is removed in the middle, the indexes change, and so does our form groups names in the process.&lt;/p>
&lt;/blockquote>
&lt;h3 id="changing-the-type-of-contact">Changing the Type of Contact&lt;/h3>
&lt;p>In the type of contact field, we are going to have a drop down where the user either selects email or phone. Then, we are going to listen to the changes to this drop down and trigger the method to change form control validation above:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-group col-6&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>&amp;gt;Type of Contact&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">select&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">change&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">changedContactType&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-control&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;type&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">option&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span>&amp;gt;Email&amp;lt;/&lt;span style="color:#f92672">option&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">option&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;phone&amp;#34;&lt;/span>&amp;gt;Phone&amp;lt;/&lt;span style="color:#f92672">option&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">select&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, below our value of contact form control, we are going to check whether the form has all possible errors. Using the &lt;a href="https://angular.io/guide/form-validation">hasError&lt;/a>() method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-group col-12&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>&amp;gt;Email/Phone No.&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-control&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;value&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text&amp;#34;&lt;/span> /&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-danger&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;getContactsFormGroup(i).controls[&amp;#39;value&amp;#39;].touched &amp;amp;&amp;amp; getContactsFormGroup(i).controls[&amp;#39;value&amp;#39;].hasError(&amp;#39;required&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
Email/Phone no is required!
&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-danger&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;getContactsFormGroup(i).controls[&amp;#39;value&amp;#39;].touched &amp;amp;&amp;amp; getContactsFormGroup(i).controls[&amp;#39;value&amp;#39;].hasError(&amp;#39;email&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
Email is not valid!
&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-danger&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;getContactsFormGroup(i).controls[&amp;#39;value&amp;#39;].touched &amp;amp;&amp;amp; getContactsFormGroup(i).controls[&amp;#39;value&amp;#39;].hasError(&amp;#39;pattern&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
Phone no. is not valid!
&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="source-code-and-demo">Source Code and Demo&lt;/h3>
&lt;p>You can find the code for this project &lt;a href="https://github.com/MainaWycliffe/angular-dynamic-form-fields-in-reactive-forms">here&lt;/a> and the demo &lt;a href="https://mainawycliffe.github.io/angular-dynamic-form-fields-in-reactive-forms/">here&lt;/a>.&lt;/p></description></item><item><title>How to Modify the UI Based on User Role in Angular</title><link>https://codinglatte.com/posts/angular/ui-basedon-user-role-angular/</link><pubDate>Wed, 24 Oct 2018 21:29:15 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/ui-basedon-user-role-angular/</guid><description>&lt;p>In today’s post, we are going to see how to modify the User Interface (UI) based their user role. This is useful if you wish to display different UI Elements/Components based on the user role. While this is not a security measure, it has the potential to greatly enhance the User Experience (UX).&lt;/p>
&lt;p>To achieve this, we will be using NGXS – a state management library which was built as an easy to user alternative to the popular &lt;a href="https://github.com/ngrx/platform">NGRX&lt;/a>. You can learn more about NGXS &lt;a href="https://ngxs.gitbook.io/ngxs/concepts/store">here&lt;/a>. It will act as a single source of truth, where we can subscribe to changes to the user role and make changes to the UI Accordingly.&lt;/p>
&lt;p>Ideally, you will want to read the user role from an authentication token – JWT or some other alternative. To keep things simple for this demo, we are going to just use a form, to allow us to change the user role quickly. I will also show you how to decode JWT tokens just in case you need to.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>First, we will start by creating a new angular project.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng new ngxs-role-based-authorization
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we are going install the packages we need for our project.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ yarn add @ngxs/store @ngxs/storage-plugin
// or using npm
$ npm install @ngxs/store @ngxs/storage-plugin
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We also need to install bootstrap for our UI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm install bootstrap
// or using yarn
$ yarn add bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to import NGXS and the NGSX storage plugin into our app module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgxsStoragePluginModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@ngxs/storage-plugin&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgxsModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@ngxs/store&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">NgxsModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>([&lt;span style="color:#a6e22e">UserRoleState&lt;/span>]),
&lt;span style="color:#a6e22e">NgxsStoragePluginModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>()
],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And lastly, import bootstrap into our project, using the style section of the &lt;code>/angular.json&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
  &lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
  &lt;span style="color:#e6db74">&amp;#34;node_modules/bootstrap/scss/bootstrap.scss&amp;#34;&lt;/span>
]
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="building-an-ngxs-state">Building an NGXS State&lt;/h3>
&lt;p>The easiest way to do this is to use NGXS CLI, which will scaffold a state for you, you can learn more about &lt;a href="https://ngxs.gitbook.io/ngxs/plugins/cli">here&lt;/a>. I wish they could use &lt;a href="https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2">angular schematics&lt;/a> though. But in this case, we will do this manually.&lt;/p>
&lt;p>First, we need to create an action for our role, which we will use to change the role of our state. This is where we will pass the role of the current user. You might also want to pass other information to store regarding the user such as the name, email etc.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ChangeUserRoleAction&lt;/span> {
&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">readonly&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[UserRole] Add role&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">role&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;guest&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;moderator&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;admin&amp;#39;&lt;/span>) {}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s create a model for our state. This is where we will add all fields we are going to store in our state. In our case, we just have role, but you can basically add any sort of data such name, email etc.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">UserRoleStateModel&lt;/span> {
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">role&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;guest&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;moderator&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;admin&amp;#39;&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, let’s define our state.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@State&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">UserRoleStateModel&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>({
&lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;userRole&amp;#39;&lt;/span>
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">UserRoleState&lt;/span> {
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, inside our state class, let’s add a Selector method to get the role of the current user. We are going to pass the state model, so that we can access to values stored in the state.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Selector&lt;/span>()
&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">getCurrentUserRole&lt;/span>(&lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">UserRoleStateModel&lt;/span>) {
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">state&lt;/span>.&lt;span style="color:#a6e22e">role&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, let’s add a method to set the current user role, passing the action class and state context:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Action&lt;/span>(&lt;span style="color:#a6e22e">ChangeUserRoleAction&lt;/span>)
&lt;span style="color:#a6e22e">ChangeRole&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>: &lt;span style="color:#66d9ef">StateContext&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">UserRoleStateModel&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>, &lt;span style="color:#a6e22e">action&lt;/span>: &lt;span style="color:#66d9ef">ChangeUserRoleAction&lt;/span>) {
  &lt;span style="color:#a6e22e">ctx&lt;/span>.&lt;span style="color:#a6e22e">setState&lt;/span>({ &lt;span style="color:#a6e22e">role&lt;/span>: &lt;span style="color:#66d9ef">action.role&lt;/span> });
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can put all the above inside a single file or divide it into multiple files – your choice.&lt;/p>
&lt;h3 id="setting-the-current-user-role">Setting the Current User Role&lt;/h3>
&lt;p>Now that we have a state, let’s set our current user role. For our simple demo, you can set the current role of the user with a single line of code.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">store&lt;/span>.&lt;span style="color:#a6e22e">dispatch&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ChangeUserRoleAction&lt;/span>(&lt;span style="color:#a6e22e">role&lt;/span>));
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> In the above line of code, we are dispatching an action, in this case to change the user role, to our store. You can learn more about NGXS Stores &lt;a href="https://ngxs.gitbook.io/ngxs/concepts/store">here&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>If a user has to login to set the user role, you can decode the &lt;a href="https://jwt.io/">JWT&lt;/a> to read the user role setting it up. First, we are going to install &lt;a href="https://github.com/auth0/angular2-jwt">angular-jwt library&lt;/a> using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm install @auth0/angular-jwt
// or use yarn
$ yarn add @auth0/angular-jwt
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And add it to your list of imports in the app module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">JwtModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>({})
];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then in your service, import the &lt;code>jwtHelperService&lt;/code> from the library we just installed above.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">jwtHelperService&lt;/span>: &lt;span style="color:#66d9ef">JwtHelperService&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, in your method, decode the JWT Token and return the user role:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">getUserRole&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> {
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">decodeToken&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">jwtHelperService&lt;/span>.&lt;span style="color:#a6e22e">decodeToken&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>);
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">decodeToken&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;role&amp;#39;&lt;/span>];
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, you can store the new role as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">store&lt;/span>.&lt;span style="color:#a6e22e">dispatch&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">ChangeUserRoleAction&lt;/span>(&lt;span style="color:#a6e22e">role&lt;/span>));
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="subscribing-to-changes-to-the-user-role">Subscribing to Changes to the User Role&lt;/h3>
&lt;p>Reading the current user roles is a straight forward matter. You can use the selectSnapshot method, which you can learn more about &lt;a href="https://ngxs.gitbook.io/ngxs/concepts/select#snapshot-selects">here&lt;/a>. The method returns a raw value for use without subscribing.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">store&lt;/span>.&lt;span style="color:#a6e22e">selectSnapshot&lt;/span>(&lt;span style="color:#a6e22e">UserRoleState&lt;/span>.&lt;span style="color:#a6e22e">getCurrentUserRole&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>But for this demo, we are going to subscribe to the changes that will occur. Take for instance, if you show a user a popup to sign in, you would like the UI to update accordingly based on the new user role without reloading the page.&lt;/p>
&lt;p>We are going to use &lt;a href="https://angular.io/api/common/AsyncPipe">async pipe&lt;/a> to subscribe to the user role and display and hide UI elements accordingly. First, inside our component class, we need an observable &lt;code>GetUserRole$&lt;/code> property. And then on component initialization, set the property to the observable that returns the current user role.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">GetUserRole$&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">store&lt;/span>.&lt;span style="color:#a6e22e">select&lt;/span>(&lt;span style="color:#a6e22e">UserRoleState&lt;/span>.&lt;span style="color:#a6e22e">getCurrentUserRole&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then inside the template, subscribe to &lt;code>checkUserRole$&lt;/code> observable using &lt;a href="https://angular.io/api/common/AsyncPipe">async pipe&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;checkUserRole$ | async as role&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Your role is accessible by the role variable from the template. You can use it any how you want to manipulate the UI of your app. For instance, you can use &lt;a href="https://angular.io/api/common/NgSwitch">ngSwitch&lt;/a> to show a role message like our demo project does.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngSwitch&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">role&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchCase&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#39;moderator&amp;#39;&amp;#34;&lt;/span>&amp;gt;Moderator Template&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchCase&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#39;admin&amp;#39;&amp;#34;&lt;/span>&amp;gt;Admin Template&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngSwitchDefault&lt;/span>&amp;gt;Guest Template (Default)&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can pass the role to your components to avoid subscribing to the state on multiple instances.&lt;/p>
&lt;/blockquote>
&lt;h3 id="source-code">Source Code&lt;/h3>
&lt;p>You can find the source code of this demo &lt;a href="https://github.com/MainaWycliffe/ngxs-role-based-authorization">here&lt;/a>.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>In this post, we saw how we can use NGXS to keep track of user role and manipulate the UI accordingly. I will be covering more topics related to NGXS in the future.  Thank you for getting this far on this post. Here is another post you might be interested in - &lt;a href="https://codinglatte.com/tech/developers/angular/role-based-authorization-in-angular-route-guards/">Role Based Authorization in Angular using Routes Guard&lt;/a>.&lt;/p></description></item><item><title>Deploying Angular 6 and Above Apps to GitHub Pages</title><link>https://codinglatte.com/posts/angular/deploying-angular-apps-github-pages/</link><pubDate>Sun, 21 Oct 2018 19:26:03 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/deploying-angular-apps-github-pages/</guid><description>&lt;p>In this post, I am going to show you how to deploy angular apps to GitHub pages. You can think of GitHub pages as a free hosting platform that you can use to host client-based apps. You can host things like demos, portfolios, documentations etc. You can use it to host any client-side app as long as you comply to GitHub terms and conditions. You can Learn more about limitations of GitHub Pages &lt;a href="https://help.github.com/articles/what-is-github-pages/">here&lt;/a>.&lt;/p>
&lt;p>I am going to assume you already have an angular repository you wish to deploy to GitHub Pages. And are also familiar with the basics of Angular, Git and GitHub. You will need to clone the repository to your PC if you don’t have a local copy of the repository. There are two approaches for achieving this. In the first approach, we are going to do everything manually, while in the second approach we will rely on an NPM Package. Without further ado:&lt;/p>
&lt;h3 id="deploying-to-github-pages-manually">Deploying to GitHub Pages Manually&lt;/h3>
&lt;p>First, we need to build our angular app, but instead of using the usual build output path (dist/project-name), we want the output path at the root of &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">angular cli workspace&lt;/a>, in a directory called &lt;code>docs&lt;/code>. We also need to specify the base URL for our angular app. The base URL will look something like this: &lt;a href="https://USERNAME.github.io/REPOSITORY_NAME/">https://USERNAME.github.io/REPOSITORY_NAME/&lt;/a>, be sure to replace both the USERNAME and REPOSITORY_NAME with the appropriate names. So, our build command will now look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng build --prod --base-href https://USERNAME.github.io/REPOSITORY_NAME/ --output-path docs
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you look at the root of the angular workspace, there is a new directory, called docs, with the built application. The reason for not using the default build location (dist/project-name) is because GitHub Pages only allows you to set the source as either the root of your repo or the docs directory in the root of your repository.&lt;/p>
&lt;p>And since we don’t want to mix up the project files and our build files, we chose the latter. Next, go ahead and commit the docs folder and its content and push the changes to your repository.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">git push origin
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then head over to your repository on GitHub, and then to the Settings tabs and then scroll down to GitHub Pages section. Then under &lt;code>source&lt;/code>, select &amp;ldquo;&lt;code>master branch /docs folder&lt;/code>&amp;rdquo; as the source for your GitHub pages. And finally save the changes.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/deploying-angular-apps-github-pages/images/GitHub-Pages-Doc.png" alt="Deploying Angular 6 and Above Apps to GitHub Pages" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>And that’s it. To view your GitHub Page, navigate to the URL for your GitHub Page which will look something like this: &lt;code>https://USERNAME.github.io/REPOSITORY_NAME/&lt;/code>. Or just click on the new link that has been placed just above &lt;code>source&lt;/code>.&lt;/p>
&lt;h3 id="using-an-npm-package-to-deploy-github-pages">Using an NPM Package to Deploy Github Pages&lt;/h3>
&lt;p>If you found the above process, a little bit hard to remember, you are not alone. Thank fully, there is a library that can automate most the steps above. This library is known as &lt;a href="https://www.npmjs.com/package/angular-cli-ghpages">angular-cli-ghpages&lt;/a>. This is a command line to help deploy angular project to GitHub Pages. The first step obviously is to install the library as a dev dependency, using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm i angular-cli-ghpages --save-dev
yarn add --dev angular-cli-ghpages
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, build your project. This time there is no need to change the output directory, but you need to set the base URL. The base URL will look like this: &lt;a href="https://USERNAME.github.io/REPOSITORY_NAME/">https://USERNAME.github.io/REPOSITORY_NAME/&lt;/a>, be sure to change both the username and REPOSITORY_NAME appropriately. So, your build command will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng build --prod --base-href &lt;span style="color:#f92672">[&lt;/span>https://USERNAME.github.io/REPOSITORY_NAME/&lt;span style="color:#f92672">](&lt;/span>https://USERNAME.github.io/REPOSITORY_NAME/&lt;span style="color:#f92672">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After build completes, you just need to run the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npx ngh --dir&lt;span style="color:#f92672">=&lt;/span>dist/&lt;span style="color:#f92672">[&lt;/span>PROJECT-NAME&lt;span style="color:#f92672">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Where PROJECT-NAME is the name of angular project you are deploying. If you are using Angular 5 and below, run the command without the project-name:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npx ngh --dir&lt;span style="color:#f92672">=&lt;/span>dist
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it, the library will do everything including configuring the page option for you on GitHub. You can now visit your GitHub page url: &lt;code>https://USERNAME.github.io/REPOSITORY_NAME/&lt;/code> to see your deployed angular app.&lt;/p>
&lt;h4 id="tip">Tip&lt;/h4>
&lt;p>You can shorten the build and deploy command using NPM scripts. Open your package.json and then, in your script section add the following script.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;scripts&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
    &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
    &lt;span style="color:#f92672">&amp;#34;deploy&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;ng b --prod --base-href https://mainawycliffe.github.io/angular-images-lazy-loading-demo/ &amp;amp;&amp;amp; npx ngh --dir=dist/angular-images-lazy-loading-demo&amp;#34;&lt;/span>
}&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And now, you can build and deploy to GitHub Pages with a single command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm run deploy
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>There are other methods you can deploy your angular project on GitHub Pages. But this two are once am comfortable recommending. Personally, I prefer the second option as it easier and can be heavily automated as compared the first one. If you have a topic suggestion you would like me to cover, you can suggest in the comment section below or get in touch with me on Twitter: &lt;a href="https://twitter.com/mwycliffe_dev">@mwycliffe_dev&lt;/a>.&lt;/p></description></item><item><title>Angular CLI v7 – CLI Prompts and Generating Barebone Angular Project</title><link>https://codinglatte.com/posts/angular/angular-cli-7/</link><pubDate>Fri, 19 Oct 2018 18:15:07 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-cli-7/</guid><description>&lt;p>Angular 7 was officially released this week, with lots of new features. Apart from being officially released, nothing else (feature wise) has changed since my last &lt;a href="https://codinglatte.com/tech/developers/angular/angular-7-news-updates/">post&lt;/a> on Angular 7. In this post, we will look at CLI Prompts and Generating a Minimal Project, some of the new features for Angular CLI 7. The first feature is, in my opinion, the most important feature for Angular CLI 7. The second one is kind of interesting. Of course, the new version of Angular CLI, has more than these two new features. Like it now supports Node JS 10 and Typescript 3.1, lots of bugs fixes and performance improvements. But today, let’s just focus on these two. So, without further ado:&lt;/p>
&lt;h2 id="cli-prompts">CLI Prompts&lt;/h2>
&lt;p>Basically, when a user is performing common tasks, they get asked questions to help change the default options of the task. Before CLI Prompts, to change the default options, you needed to use command line flags to specify options. But with CLI Prompts, Angular CLI will prompt you with questions and options for you to answer. Of course, command line flags are still available for more advanced options and CLI Prompts are not meant to replace them. For instance, when creating a new app, using ng new, will prompt you with two options. The first option will prompt you on whether you want to add routing support. While the second option will ask you which stylesheet (CSS, SCSS, SASS etc.) you would like to use.&lt;/p>
&lt;p>&lt;img src="//wp-content/uploads/2018/10/screencast-blog.angular.io-2018.10.19-19-12-09-1024x576.gif" alt="Angular CLI v7 – CLI Prompts and Minimal Flag">&lt;/p>
&lt;p>As of the release of Angular 7, this works with Angular Material, and am guessing other first party libraries and partners will support it too. The good news though, is that CLI Prompts are part of Angular Schematics. This means any library that supports Schematics, can integrate with CLI prompts.&lt;/p>
&lt;p>&lt;img src="//wp-content/uploads/2018/10/screencast-ezgif.com-2018.10.19-19-37-31.gif" alt="Angular CLI v7 – CLI Prompts and Minimal Flag">&lt;/p>
&lt;p>CLI Prompts are useful to developers, as they help them discover features and configuration options organically. It reduces the number of ng command line flags you need to remember when performing simple tasks. For instance, I always forget to set default style sheet and to enable routing, when starting a new project. But with CLI Prompts, it’s refreshing that I don’t have to worry about forgetting to set those two options anymore.&lt;/p>
&lt;h2 id="generating-a-barebone-angular-project">Generating a Barebone Angular Project&lt;/h2>
&lt;p>This is one interesting feature, that kind of went under the radar. Basically, when creating a new angular application, when you add the &amp;ndash;minimal, it will generate a barebone project. This means that, all testing NPM libraries will not be included in your project. The goal of the &amp;ndash;minimal flag is to reduce the size of the initial angular project. This is important for students and developers who are tight on disk space. The feature is also controversial, since industry best practices recommend writing of tests, yet there is a sizable developer population that don’t write tests or see the need to. You can find the discussion for this feature &lt;a href="https://github.com/angular/angular-cli/issues/11904">here&lt;/a>. Basically, to most of those developers, those packages are just getting in the way. Here is an example of what &lt;code>package.json&lt;/code> looks like for a new project generated with the minimal flag.&lt;/p>
&lt;p>&lt;img src="//wp-content/uploads/2018/10/ng7-minimal-1024x685.png" alt="Angular CLI v7 – CLI Prompts and Minimal Flag">&lt;/p></description></item><item><title>Progressive Web Apps (PWAs) in Angular – Part 2</title><link>https://codinglatte.com/posts/angular/pwas-in-angular/</link><pubDate>Thu, 18 Oct 2018 01:23:47 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/pwas-in-angular/</guid><description>&lt;p>Google Chrome version 70 was released earlier this week. Among other features, it added support Progressive Web Apps (PWAs) on desktops. This give me an idea for this post where we are going to dive a little bit deeper into PWAs. If you are new to PWAs, please check my introduction to PWAs &lt;a href="https://codinglatte.com/tech/developers/angular/introduction-to-progressive-web-apps/">here&lt;/a>. We will focus on two things:&lt;/p>
&lt;ol>
&lt;li>How to check for new versions of your PWAs and&lt;/li>
&lt;li>Prompting users to install your PWA&lt;/li>
&lt;/ol>
&lt;p>Without further ado:&lt;/p>
&lt;h3 id="checking-for-new-versions">Checking for New Versions&lt;/h3>
&lt;p>With PWAs, a lot of the static resources are cached on the client device. So, when you deploy a new version of your app, the users don’t see changes instantly like most web apps. It is therefore important to check for updates manually, download them and then prompt the user when there is a new version.&lt;/p>
&lt;p>This would could display a button that when the user reloads the app, it reloads with the new version. If you have used some Google Webs Services such as &lt;a href="https://messages.android.com/">Android Messages&lt;/a>, you might have come across this. This allows you to download the newer version on the background, without interfering with the user experience. Once downloaded, it’s a matter of reloading the browser which will load the latest version. This is simple and almost instant, since all assets and resources have been downloaded and cached locally.&lt;/p>
&lt;h4 id="how-to-check-for-new-updates">How to Check for New Updates&lt;/h4>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/10/ezgif.com-video-to-gif-3.gif" alt="Progressive Web Apps (PWAs) in Angular – Part 2">&lt;/p>
&lt;p>PWAs uses a Service Worker to cache most of the static resources, therefore you must use a service worker to check for updates. Service Worker provides a service that you can use to communicate between your app and the service worker. The service is called &lt;a href="https://angular.io/api/service-worker/SwUpdate">SwUpdate&lt;/a>, and is used just like any other service.&lt;/p>
&lt;p>To check for new updates, you first need to inject the SwUpdate service into your component or service:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">swUpdate&lt;/span>: &lt;span style="color:#66d9ef">SwUpdate&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, you can check for new updates as follows.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">checkForUpdates() {&lt;/span>
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">swUpdate&lt;/span>.&lt;span style="color:#a6e22e">available&lt;/span>.&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">event&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
    &lt;span style="color:#75715e">// prompt the user to reload the app now
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">updateAvailable&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>;
  });
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>updateAvailable&lt;/code> property, just display a button informing the user there is an update. You can also forcefully reload the browser at this point, which loads the new version. You probably don’t want to do this, because it could ruin the User experience.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">reload() {&lt;/span>
  window.&lt;span style="color:#a6e22e">location&lt;/span>.&lt;span style="color:#a6e22e">reload&lt;/span>();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="periodically-checking-for-new-updates">Periodically Checking for New Updates&lt;/h4>
&lt;p>The above method checks for update once and is triggered by a button click (in this case). You don’t really want the user to be manually checking for updates, but you might want to periodically check for new updates.  This can be achieved using the &lt;a href="http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-interval">RXJS Interval&lt;/a> method which will tell the service worker to check for new updates on interval.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">interval&lt;/span>(&lt;span style="color:#ae81ff">1000&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">60&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">60&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>).&lt;span style="color:#a6e22e">subscribe&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">swUpdate&lt;/span>.&lt;span style="color:#a6e22e">checkForUpdate&lt;/span>());
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> The above method uses &lt;a href="http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-interval">RXJS Interval method&lt;/a> to periodically check for updates every 2 hours. Time is provided to the interval method in milliseconds by default.&lt;/p>
&lt;/blockquote>
&lt;p>The &lt;code>checkForUpdate&lt;/code> is strange though, it returns a promise but doesn’t indicate whether there is an update or not. So, to be safe, don’t reload when the method is resolved successfully. The good thing though is that, if there is an update available, the next time the user reloads the app, they will load the latest version.&lt;/p>
&lt;h4 id="prompting-users-to-install-pwas">Prompting Users to Install PWAs&lt;/h4>
&lt;p>Let’s get this out of the way first, browsers have the liberty on how to handle PWAs installs. That said, Google Chrome offers developers the ability to control how to handle PWAs installation. I did some research and experimentation and I could not find how to achieve the same in other browsers.&lt;/p>
&lt;blockquote>
&lt;p>I will update this post as soon as the situation changes.&lt;/p>
&lt;/blockquote>
&lt;p>If you want to prompt users to install your PWA, you need to listen to &lt;code>beforeinstallprompt&lt;/code> event. This event is triggered on every page reload, if the user has not installed your app. This works even after the user has uninstalled the application.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">window.&lt;span style="color:#a6e22e">addEventListener&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;beforeinstallprompt&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">event&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">promptUserInstall&lt;/span>();
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For older version of Chrome (Chrome 67 and lower), you need to add &lt;code>preventDefault()&lt;/code> to prevent chrome from showing the default install prompt, before users clicks on your custom install button.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">preventDefault&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, you need to show a custom UI that will prompt the user to install the app.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">promptUserInstall() {&lt;/span>
  &lt;span style="color:#75715e">// show prompt here
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And once the user clicks on the install button, you can then trigger Chrome to show Add App dialog.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">deferedPrompt&lt;/span>.&lt;span style="color:#a6e22e">userChoice&lt;/span>.&lt;span style="color:#a6e22e">then&lt;/span>(&lt;span style="color:#a6e22e">choiceResult&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">choiceResult&lt;/span>.&lt;span style="color:#a6e22e">outcome&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#e6db74">&amp;#39;accepted&amp;#39;&lt;/span>) {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;User accepted to install PWA&amp;#39;&lt;/span>);
} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;User chose not to install PWA&amp;#39;&lt;/span>);
}
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">deferedPrompt&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>As of the time of writing this, this doesn’t trigger the install dialog on Chrome for Desktop. I tested it on current, beta and canary versions of Chrome without success. As a work around, you will have to provide instructions to install the PWA on the desktop version of Chrome. Fortunately, it is not hidden very far, and can easily be located on the menu, so a simple Gif would do.&lt;/em>&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/10/ezgif.com-crop-2.gif" alt="Progressive Web Apps (PWAs) in Angular – Part 2">&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>As time passes, more and more browsers will continue offering standardized PWAs APIs. Hopefully, more and more browsers will support the &lt;code>BeforeInstallPromptEvent&lt;/code> so that you can customize the prompt install button.&lt;/p>
&lt;p>Thank you for getting this far on this post, I will update it as more information continues to get available for different browser support. If you are interested to learn how to  use Service Workers to Optimize performance of your angular PWA &lt;a href="https://codinglatte.com/tech/developers/angular/service-worker-angular-performance/">here&lt;/a>.&lt;/p></description></item><item><title>APP_INITIALIZER – Tapping into Initialization Process in Angular</title><link>https://codinglatte.com/posts/angular/app_initializer-in-angular/</link><pubDate>Sun, 14 Oct 2018 11:09:20 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/app_initializer-in-angular/</guid><description>&lt;p>In this post, we are going to look at how we can use APP_INITIALIZER in Angular. So, what exactly does APP_INITIALIZER do? The best way to answer that is by looking at my previous &lt;a href="https://codinglatte.com/tech/developers/angular/better-approach-environment-variables-angular/">post&lt;/a>, which can be found &lt;a href="https://codinglatte.com/tech/developers/angular/better-approach-environment-variables-angular/">here&lt;/a>. It was about angular environment variables being loaded remotely, instead of environment files which are built into the app. So, in this scenario, you might need to have access to those variables immediately the app starts. That’s what APP_INITIALIZER allows you to do, provide a function that will be executed during app initialization stage.&lt;/p>
&lt;p>Angular will allow the functions to be executed to completion before rendering anything. It even gets better, if it encounters an error, the whole application will not load. This ensure that your remotely loaded configuration are available right from the start. You can use this to load anything you want to during the initialization stage, so it’s available right after the app starts. To show you how to tap into the initialization process, we are going to use a demo. In this demo, we will look at loading our configurations from the previous &lt;a href="https://codinglatte.com/tech/developers/angular/better-approach-environment-variables-angular/">post&lt;/a> to our angular application. So, without further ado, let’s get started:&lt;/p>
&lt;h3 id="create-a-new-application">Create a New Application&lt;/h3>
&lt;p>First, Let’s create a brand-new application using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng new angular-app-initializer-demo-app
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then generate a service to load our configurations:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$  ng generate service config
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s work on our newly created service to fetch and load our configurations.&lt;/p>
&lt;h3 id="fetching-configurations">Fetching Configurations&lt;/h3>
&lt;p>One thing to keep in mind before we can go any further, APP_INITIALIZER expects a promise not an observable. Don’t worry, we will still be able to use observables, but our return value must be a promise, otherwise it won’t work. Fortunately for us, RXJS provides a &lt;a href="https://www.learnrxjs.io/operators/utility/topromise.html">toPromise&lt;/a> method to convert that observable to promise. So, our service is going to need one method for getting configurations:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">getConfigs&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>Object&lt;span style="color:#f92672">&amp;gt;&lt;/span> { }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And one property for holding our configurations.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">configurations&lt;/span>: &lt;span style="color:#66d9ef">object&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Since we don’t have a backend, we will use &lt;a href="http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-of">RXJS of&lt;/a> method to convert a simple array into an observable stream. You can easily fetch data using &lt;a href="https://angular.io/guide/http">HTTP Client&lt;/a> in Angular, just you normally would under any other service. Next, we are going to pipe to our observable and &lt;a href="https://www.learnrxjs.io/operators/utility/do.html">tap&lt;/a> into the observable stream to set the configurations property to the returned value. Then convert the observable stream to a promise and return it.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">getConfigs&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>Object&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#a6e22e">dummyConfigs&lt;/span>) &lt;span style="color:#75715e">// &amp;lt;== this could be a http request here
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    .&lt;span style="color:#a6e22e">pipe&lt;/span>(
      &lt;span style="color:#a6e22e">tap&lt;/span>(&lt;span style="color:#a6e22e">config&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
        &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">configurations&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">config&lt;/span>;
      })
    )
    .&lt;span style="color:#a6e22e">toPromise&lt;/span>();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="configuring-app_initializer">Configuring APP_INITIALIZER&lt;/h3>
&lt;p>We are going to provide APP_INITIALIZER inside App Module, but this can be done in any other module like CoreModule. Before we can do that, we need to create a function to the method for getting our configuration. The function will accept our config service above, which we shall inject when providing APP_INITIALIZER. It will then call the method to get config and return the resulting promise.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#a6e22e">loadConfigurations&lt;/span>(&lt;span style="color:#a6e22e">configService&lt;/span>: &lt;span style="color:#66d9ef">ConfigServiceService&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">configService&lt;/span>.&lt;span style="color:#a6e22e">getConfigs&lt;/span>();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s add our config service and provide APP&lt;em>INITIALIZER to our list of providers in the App Module. For the APP_INITIALIZER, first we have the provide property, where we indicated we are providing APP&lt;/em>INITIALIZER. Then we indicate we are using factory (&lt;code>_useFactory&lt;/code> property) and injecting our config service as a dependency for our factory (&lt;code>_deps&lt;/code> property). We have also added a multi property, which indicates we can have multiple APP_INITIALIZERS and not just the one.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    &lt;span style="color:#a6e22e">ConfigServiceService&lt;/span>,
    {
      &lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">APP_INITIALIZER&lt;/span>,
      &lt;span style="color:#a6e22e">useFactory&lt;/span>: &lt;span style="color:#66d9ef">loadConfigurations&lt;/span>
      &lt;span style="color:#a6e22e">deps&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">ConfigServiceService&lt;/span>], &lt;span style="color:#75715e">// dependancy
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
    }
  ],
  &lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [ &lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>]
})
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And basically, that’s it. If the promise is resolved successfully, your app should go ahead and load successfully, otherwise it will fail to initialize.&lt;/p>
&lt;h3 id="word-of-caution">Word of Caution&lt;/h3>
&lt;p>You can do more complicated stuff but remember that your app won’t start until all sent promises are resolved. So, if you are doing to many things at once, you might impact the performance of your app negatively.&lt;/p>
&lt;h3 id="source-code">Source Code&lt;/h3>
&lt;p>You can find the complete source code for this post &lt;a href="https://github.com/MainaWycliffe/angular-app-initializer-demo-app">here&lt;/a>.&lt;/p></description></item><item><title>A Better Approach to Environment Variables in Angular</title><link>https://codinglatte.com/posts/angular/better-approach-environment-variables-angular/</link><pubDate>Fri, 12 Oct 2018 10:43:43 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/better-approach-environment-variables-angular/</guid><description>&lt;p>Angular provides a default way to configure environment variables, which you can learn more about &lt;a href="//tech/developers/angular/environment-variables-angular/">here&lt;/a>. But in a nutshell, you have different environment files, where you store environment variables and during the build process, angular compiler will use the correct environment file to replace and the default environment variables.&lt;/p>
&lt;p>So, if you are targeting production environment, angular will replace the default environment file with the production when you use the &lt;code>--prod&lt;/code> flag. This works but has some shortcoming. Like for instance to change any of those configurations, you must rebuild and deploy the whole application. Would it be better if you could change some variables, such as API Keys dynamically without need to go through that process?&lt;/p>
&lt;h1 id="a-better-approach">A Better Approach&lt;/h1>
&lt;p>The approach is rather simple, and it involves storing the data on the backend on an environment folder. Then during app initial stage or even initialization, you can load the configuration file (JSON) using a service. In this scenario, we will have different JSON files for different environments. We will then let the app load the appropriate configuration based on the environment it has been deployed in. To distinguish between different environment configurations, we are going to add a new environment name property under each of environment. If we have three environments, then we are going to have 3 environments files: &lt;code>environment.ts&lt;/code>, &lt;code>environment.prod.ts&lt;/code> and &lt;code>environment.staging.ts&lt;/code> for each of our environments.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
  &lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
  &lt;span style="color:#a6e22e">wpEndpoint&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Some Endpoint&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">environment&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;staging&amp;#39;&lt;/span>, &lt;span style="color:#75715e">// environment name property
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  ...
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The same needs to be done for each of our other environment names:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Production
&lt;/span>&lt;span style="color:#75715e">&lt;/span>...
&lt;span style="color:#a6e22e">environment&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;staging&amp;#39;&lt;/span>, &lt;span style="color:#75715e">// environment name property
&lt;/span>&lt;span style="color:#75715e">&lt;/span>...
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Development
&lt;/span>&lt;span style="color:#75715e">&lt;/span>...
&lt;span style="color:#a6e22e">environment&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;development&amp;#39;&lt;/span>, &lt;span style="color:#75715e">// environment name property
&lt;/span>&lt;span style="color:#75715e">&lt;/span>...
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, we can call a http service to retrieve the json files containing  that environments configurations, which we are storing in a directory on a server or &lt;a href="https://aws.amazon.com/s3/">AWS S3 bucket&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Any sensitive API Keys should not be stored inside the frontend app. Instead have your backend call those APIs on behalf of the frontend. This ensures they remain private, out of reach from the public.&lt;/p>
&lt;/blockquote>
&lt;h2 id="loading-the-configurations">Loading the Configurations&lt;/h2>
&lt;p>With the environment name property, you can stitch together the URL to the correct configurations file.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;some-server-url&amp;#39;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.json&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then you can call the API Endpoint as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#a6e22e">url&lt;/span>).&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">map&lt;/span>((&lt;span style="color:#a6e22e">res&lt;/span>: &lt;span style="color:#66d9ef">Response&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">body&lt;/span>;
})
);
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can strongly type cast the results. This allows you to have easy access to the variables inside the JSON File just like a normal environment file. Allowing for intellisense when using  Angular Language Service.&lt;/p>
&lt;/blockquote>
&lt;p>Now anytime you want to change configurations, you simply edit the JSON file containing the configuration of your environment. No need to build and deploy a new version of your application just for simple change. When to fetch this configuration is up to you. You can load them in the first component, just before anything else.&lt;/p>
&lt;p>Another option is during app initialization, just before the app has started off. I prefer the last option as it means the configurations will be available to the app as when starts. You can learn more about this &lt;a href="//tech/developers/angular/app_initializer-in-angular/">here&lt;/a>.&lt;/p>
&lt;h1 id="caching">Caching&lt;/h1>
&lt;p>While storing some of the configurations on the backend is a good idea. On the hand, retrieving them each time the app is loaded or reloaded is not a very good idea. You will need to implement some sort of local caching, I suggest using a &lt;a href="//tech/developers/angular/service-worker-angular-performance/">Service Worker&lt;/a>.&lt;/p>
&lt;p>A local cache will do two things, first store a local record of the configuration for a specified period – an hour, 30 minutes etc. And secondly speed up your app as it eliminates network latency required while fetching the configurations. The good thing about using a service worker is you can use performance configuration.&lt;/p>
&lt;p>This basically means that, it will only check for fresh content from the server after the specified cache period has expired. You can also use freshness settings, in this case it just checks whether there is new content and if not just loads from local cache. You can learn more about Service Workers &lt;a href="//tech/developers/angular/service-worker-angular-performance/">here&lt;/a>. And all without the need to implement your own caching system, just a few configurations. The only downside is browser support, which you can learn more about &lt;a href="https://caniuse.com/#feat=serviceworkers">here&lt;/a>.&lt;/p>
&lt;h1 id="final-thoughts">Final Thoughts&lt;/h1>
&lt;p>This method is not perfect, but it provides a much better approach to environment variables. Of course, not every app is going to benefit from this and for a lot of apps out there, the default approach is still a better alternative.&lt;/p>
&lt;p>It all depends with what your application does, if it relies with a lot of API keys to third party service, then dynamically changing them is not a bad idea. If your environment variables rarely change, and when they do change have to be tested before deployment, then the default approach works just fine.&lt;/p></description></item><item><title>Creating Reusable Components in Angular</title><link>https://codinglatte.com/posts/angular/reusable-components-angular/</link><pubDate>Tue, 09 Oct 2018 11:41:22 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/reusable-components-angular/</guid><description>&lt;p>In this post, we are going to look at tips you can use to make your components more reusable. Reusing components allows developers to avoid code duplication, which can introduce errors and bugs and are also hard to troubleshoot. Take for instance a shopping site, the product display component, whether the product is electronic or beverage, can be displayed using the same component.&lt;/p>
&lt;p>So, it would make sense to make sure that this component can be re-used in multiple situations such as the homepage recommendation, product category listing, search listing and cart. Making it more aware of where it is being use and altering the behavior accordingly.&lt;/p>
&lt;p>In such a case, any bug or error detected within the product itself becomes very easy to fix. This is because it’s a single component, rather than multiple components. In case of multiple components, each would have to be updated. For a small project, that might not be a problem but as the project grows, it becomes a nightmare to manage.&lt;/p>
&lt;h3 id="avoid-creating-large-components">Avoid Creating Large Components&lt;/h3>
&lt;p>Having a single large component has several disadvantages, such as: It makes code hard to read, code can become very messy and they are not very re-usable. One way to know that your component is large is if the it has over 400 lines of code.&lt;/p>
&lt;p>Another way, which I find mostly useful, is if you find yourself trying to replicate (copy - pasting) some section of the component into another component. This is when you should evaluate whether to break down a component. So that each component, ideally performs a single function.&lt;/p>
&lt;p>For our shopping site above, this would be having one component for search, another for looping through the individual products and another for displaying individual products. The last two can be reused in the search section and to display checkout cart.&lt;/p>
&lt;p>Another important thing to do, is to ask whether the logic inside the component class, can benefit by moving it either to a class or a service. Things like HTTP calls to API should be in their own services, making them available to more components that may need them in the future. Basically, any logic that might be used by more than one component, doesn’t belong inside the component.&lt;/p>
&lt;h3 id="passing-data-between-components">Passing Data Between Components&lt;/h3>
&lt;p>When breaking down components into smaller components, you find that you will need to pass data between components. One such scenarios is when want to pass data such as product information to product display component from parent.&lt;/p>
&lt;p>You might also want to be able pass back data and events to parent component for action. The easiest way to achieve this is using Output and Input Bindings for parent-child components and using a service for unrelated components. I won’t go into details of this in this post, but here are some useful learning resources you can use:&lt;/p>
&lt;ol>
&lt;li>Component Interaction – &lt;a href="https://angular.io/guide/component-interaction">angular.io&lt;/a>&lt;/li>
&lt;li>3 ways to communicate between Angular components - &lt;a href="https://medium.com/dailyjs/3-ways-to-communicate-between-angular-components-a1e3f3304ecb">Miro Koczka&lt;/a>&lt;/li>
&lt;li>Sharing Data Between Angular Components - Four Methods – &lt;a href="https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/">AngularFirebase.com&lt;/a>&lt;/li>
&lt;/ol>
&lt;h3 id="directives-and-pipes">Directives and Pipes&lt;/h3>
&lt;p>You can also use directives and pipes to extract some functionality from components. Then the directives and pipes can be used in multiple components. You can have a directive to modify the behavior of a single button, in such a way that it behaves differently based on the situation.&lt;/p>
&lt;p>For instance, when a product is being displayed inside the checkout cart, you need a remove button and not a buy button. With inbuild &lt;a href="https://angular.io/guide/structural-directives#inside-ngswitch-directives">&lt;code>directives&lt;/code>&lt;/a> such as &lt;a href="https://angular.io/api/common/NgIf">&lt;code>NgIf&lt;/code>&lt;/a> and &lt;a href="https://angular.io/api/common/NgSwitch">&lt;code>NgSwitch&lt;/code>&lt;/a>, you can easily achieve this. You can also build your own directive to achieve different functionality for different scenarios.&lt;/p>
&lt;p>Pipes on the other hand are great for transforming values for display. Angular has inbuilt pipes to alter &lt;a href="https://angular.io/guide/pipes">text case&lt;/a>, &lt;a href="https://angular.io/api/common/DatePipe">format dates&lt;/a>, &lt;a href="https://angular.io/api/common/AsyncPipe">subscribe to observables&lt;/a> etc. You can build your own pipes to do more than that.&lt;/p>
&lt;p>A good example where a pipe might be very useful is when you have country or currency codes but want to transform into known recognizable names. You can either create a method in your component to do this, but I find it better to use pipes in such circumstances. This way, anytime you wish to transform a value inside a template, you just add the pipe.&lt;/p>
&lt;h3 id="sharing-components-in-lazy-loaded-projects">Sharing components in lazy loaded projects&lt;/h3>
&lt;p>Lazy loading or deferred loading is a technique where you break up your application into smaller sections to improve performance. You can learn more about it &lt;a href="https://codinglatte.com/tech/developers/angular/optimizing-your-angular-app-using-lazy-loading/">here&lt;/a>.&lt;/p>
&lt;p>Normally, components (directive and pipes too) are registered in a single module. In an angular app without lazy loading, this is not a problem, because there is only one app module. If you try to register one of this three items in multiple modules, you will get an error that they cannot be registered in more than one module. Also, to use two components in a parent child relationship, they need to be registered in the same component.&lt;/p>
&lt;p>To work around this, you need to create a shared module, where you declare and export the components, pipes and directives you want to share. Then, you can simply import the shared module into any of your lazy loaded modules and all exported items will be available. You can learn more about shared modules in Angular &lt;a href="https://angular.io/guide/sharing-ngmodules">here&lt;/a>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>When using shared modules, remember to import the required modules required by the components&lt;/em>.&lt;/p>
&lt;/blockquote>
&lt;h3 id="what-about-reusing-components-in-multiple-projects">What about Reusing Components in Multiple Projects?&lt;/h3>
&lt;p>As of Angular 6, they introduced &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">Angular CLI Workspaces&lt;/a>, allowing you to house more than one project in a single workspace. This means that if you have more than one project, you might want to share components across your projects. Angular 6 also introduced the ability to develop libraries within the same workspace.&lt;/p>
&lt;p>And Angular CLI will register the library build directory (dist/library-name) in the tsconfig. This makes the library available to any project within the workspace after building it. This means that you can extract the components you want to share into a library. This library can then be privately used them within the project. There is no need to publish them anywhere, public or privately. You can learn more about building libraries in Angular &lt;a href="https://codinglatte.com/tech/developers/angular/building-angular-6-libraries/">here&lt;/a>.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>These are some of the techniques that I have come up with to make my components more reusable. They also have the added advantage of making my code cleaner and easily readable. This is important to me, since I don’t just want to develop web apps, but also enjoy the &lt;a href="https://codinglatte.com/tech/developers/angular/angular-development-tips/">experience&lt;/a>. If you have a suggestion on how to improve this, please leave it in the comment section below. Thank you for getting this far. If you have a topic suggestion you can also leave it the comment section below.&lt;/p></description></item><item><title>Angular Material 7 and CDK News and Updates</title><link>https://codinglatte.com/posts/angular/angular-material-7-cdk-news/</link><pubDate>Fri, 05 Oct 2018 01:27:32 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-material-7-cdk-news/</guid><description>&lt;p>In this post, we are going to take a closer look at changes we expect on both Angular Material 7 and &lt;a href="https://material.angular.io/cdk/categories">Content Development Kit&lt;/a>(CDK). While this two are separate packages, they often go hand in hand, as Angular Material relies on some packages found in Angular CDK. But you can use Angular CDK independent of Angular Material and with a &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI framework&lt;/a> of your choice.&lt;/p>
&lt;p>We expect Angular Material 7 to be released alongside Angular 7 in the next few weeks. Since I last covered &lt;a href="https://codinglatte.com/tech/developers/angular/angular-7-news-updates/">news&lt;/a> on Angular 7, there have been new features added to both Material 7 and CDK. On top of features, more of Angular Material Components have been slightly redesigned to conform to the latest standards of Material Design Specification, released earlier this year. So, without Further Ado&lt;/p>
&lt;h3 id="scrolling-enhancement">Scrolling Enhancement&lt;/h3>
&lt;p>The scrolling package is not new in Angular Material, but it has been greatly enhanced in Angular 7. This package is meant to provides helper directives that react to scrolling events and is part of Angular CDK. Here are some of the features that have been added:&lt;/p>
&lt;h4 id="virtual-scrolling">Virtual Scrolling&lt;/h4>
&lt;p>This is the most popular feature by far. This is meant to display large list of elements (normally rendered with &lt;a href="https://angular.io/guide/displaying-data">&lt;code>*ngFor&lt;/code>&lt;/a>) with improved performance, by only rendering elements on display. If you had hundreds of elements to display, there is no point to show all of them. Especially if they are not on user’s viewport. So, to improve performance, it will display only elements on display and switch them for new ones, while removing old once as the user scrolls down or up. This provides a huge performance gain, as only a section of the list is being rendered.&lt;/p>
&lt;h4 id="viewportruler">ViewportRuler&lt;/h4>
&lt;p>This is a simple service that provides you with the ability to measure the bound of the browser viewport. A browser&amp;rsquo;s viewport is the visible area of the browser’s webpage. You can learn more about this feature &lt;a href="https://beta-angular-material-io.firebaseapp.com/cdk/scrolling/overview">here&lt;/a>.&lt;/p>
&lt;h3 id="ripples-angular-material">Ripples (Angular Material)&lt;/h3>
&lt;p>This is a new Angular Material 7 Component, that allows you to visually indicate to the user when they touch or click on an HTML element like a button. It uses ripples to indicate the point of contact on the element with this feature enabled. It can be used to provide feedback to the user, indicating that their input was received or detected. To use this feature, simply import the MatRippleModule from angular material:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MatRippleModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/material/core&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, add the &lt;code>matRipple&lt;/code> directive to the element you want to add the ripple effect feedback:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">matRipple&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;my-ripple-container&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about this feature &lt;a href="https://beta-angular-material-io.firebaseapp.com/components/ripple/examples">here&lt;/a> and find a demo &lt;a href="https://beta-angular-material-io.firebaseapp.com/components/ripple/examples">here&lt;/a>.&lt;/p>
&lt;h3 id="text-field">Text Field&lt;/h3>
&lt;p>Text Field package is part of Angular CDK and provides a set of utilities for both text and text area inputs. As of the time of writing this, it includes utilities to monitor autofill state and resize text field to fit content. With monitor autofill state, you can easily monitor whether the user has used autofill in your forms or individual form controls and react accordingly. The package provides a &lt;code>cdkAutofill&lt;/code> directive to trigger a method when the autofill status has changed. To use this feature, you just need to import &lt;code>TextFieldModule&lt;/code> from CDK:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">TextFieldModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/cdk/text-field&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, add the cdkAutofill directive to your input control, passing the method to be triggered.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">matInput&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">cdkAutofill&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">firstNameAutofilled &lt;/span>&lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">$event.isAutofilled&amp;#34;&lt;/span> /&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The second feature allows you to create text areas that automatically resize with content. To use this feature, simply import the &lt;code>TextFieldModule&lt;/code> from CDK:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">TextFieldModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/cdk/text-field&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then add the directive to your text area input control:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">textarea&lt;/span>
&lt;span style="color:#a6e22e">matInput&lt;/span>
&lt;span style="color:#a6e22e">cdkTextareaAutosize&lt;/span>
&lt;span style="color:#a6e22e">cdkAutosizeMinRows&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;2&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">cdkAutosizeMaxRows&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;5&amp;#34;&lt;/span>
&amp;gt;&amp;lt;/&lt;span style="color:#f92672">textarea&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about this feature &lt;a href="https://beta-angular-material-io.firebaseapp.com/cdk/text-field/overview">here&lt;/a>.&lt;/p>
&lt;h3 id="platform">Platform&lt;/h3>
&lt;p>This is an Angular CDK Service that helps you determine the platform the angular app is running on. The service provides properties and methods to help you determine the Operating System, Browser and capabilities of the platform the angular app is running on. For instance, it provides you with a &lt;code>getSupportedInputTypes&lt;/code> method that helps you determine the supported input controls by the browser. You can also check whether the operating system (IOS) is Android or IOS using the &lt;code>ANDROID&lt;/code> and &lt;code>IOS&lt;/code> Boolean properties respectively. You can learn more about this feature &lt;a href="https://beta-angular-material-io.firebaseapp.com/cdk/platform/api">here&lt;/a>.&lt;/p>
&lt;h3 id="drag-and-drop">Drag and Drop&lt;/h3>
&lt;p>This is one of the most exciting features coming to Angular 7, it provides you with an easy way to create drag and drop interfaces in Angular. You can use it to allow users to drag and place a UI element anywhere in the browser tab. The only reason this is not at the top is because I have covered it before, twice in fact. One practical application is reordering lists or moving items between lists.&lt;/p>
&lt;p>(&lt;em>In fact,&lt;/em> &lt;em>if you can think more practical application of this feature, feel free to drop them in the comment section below&lt;/em>). I created a working demo (using bootstrap as the UI framework) of this feature earlier this week. You can find the demo &lt;a href="https://mainawycliffe.github.io/ng-material7-drag-and-drop-demo/">here&lt;/a> and the accompanying post &lt;a href="https://codinglatte.com/tech/developers/angular/drag-and-drop-feature-angular-7-cdk/">here&lt;/a>. You can learn more about this feature &lt;a href="https://beta-angular-material-io.firebaseapp.com/cdk/drag-drop/overview">here&lt;/a>.&lt;/p></description></item><item><title>A Closer Look at the Drag and Drop Feature for Angular 7 CDK</title><link>https://codinglatte.com/posts/angular/drag-and-drop-feature-angular-7-cdk/</link><pubDate>Wed, 03 Oct 2018 12:29:22 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/drag-and-drop-feature-angular-7-cdk/</guid><description>&lt;p>In this post, we are going to take a close look at the drag and drop feature coming to Angular 7 &lt;a href="https://material.angular.io/">Content Development Kit&lt;/a> (CDK). We are getting closer to the release of Angular 7, so it is only fair to see what is in store for us. You can learn more about angular 7 &lt;a href="https://codinglatte.com/tech/developers/angular/angular-7-news-updates/">here&lt;/a>.&lt;/p>
&lt;p>So, to checkout this feature, we will be creating a barebone to-do application. We will use the drag and drop, to move items from our to-do list to the done or cancelled lists. Our to-do application will have three lists, to-do items, done items and cancelled items. To cancel an item, you move it from either of the other two lists to the cancelled items.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/10/screencast-localhost-4200-2018.10.03-13-28-09-1024x653.gif" alt="Drag and Drop Demo">&lt;/p>
&lt;p>The same process is applied when moving an item from to-do item to done or cancelled list. You can also move items back and forth. You should also be able to re-arrange the list as you see fit by moving items up or down easily. For this app, we won’t persist items to keep thing simple, so everything will be lost when you reload. For the UI we will use bootstrap, but you can use any UI library or framework you want to.&lt;/p>
&lt;p>So, without further ado:&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>For this project, we will be using the release candidate (RC) version of Angular 7. This is latest version of Angular 7 as of the time am writing this. This means, we also need the same version of Angular CLI to generate an Angular 7 application. You can upgrade your global version of Angular CLI or install it in a directory and generate your new angular project from that directory. Since the local version of Angular CLI supersedes the global version, then any new project generated in that directory will use Angular 7. To learn more about how to install pre-release version of Angular 7, check the last section of the following &lt;a href="https://codinglatte.com/tech/developers/angular/angular-7-news-updates/">article&lt;/a>.&lt;/p>
&lt;p>First, let’s create and navigate to a new directory to test out angular 7 using terminal or PowerShell. Then install a local version of pre-release version of Angular CLI using your favorite package manager Yarn:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ yarn add @angular/cli@7.0.0-rc.0
// or with npm
$ npm install @angular/cli@7.0.0-rc.0
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, generate a new project using Angular CLI just you normally would:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng new ng-material7-drag-and-drop-demo
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then change directory to that directory and add dependencies we require for this project: Yarn&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ yarn add @angular/cdk@7.0.0-beta.2 bootstrap
// or with npm
$ npm install @angular/cdk@7.0.0-beta.2 bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, let’s create our to-do application:&lt;/p>
&lt;h3 id="building-to-do-app">Building to-do App&lt;/h3>
&lt;p>First, we need import the &lt;code>DragDropModule&lt;/code> from Angular CDK  into our app module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">...
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">DragDropModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/cdk/drag-drop&amp;#39;&lt;/span>;
...
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    &lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#a6e22e">DragDropModule&lt;/span>,
    &lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  ],
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
  &lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s create an interface for our to-do list. Generate the interface using &lt;a href="https://github.com/angular/angular-cli/wiki/generate-interface">Angular CLI&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng generate interface todo
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, open the newly created typescript file and add the following content:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span> &lt;span style="color:#a6e22e">Todo&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> This is a simple to-do application, so no need to make it too complicated, hence it has the title of the to-do and the date it was added only.&lt;/p>
&lt;/blockquote>
&lt;h3 id="adding-drag-and-drop-into-our-component">Adding Drag and Drop into Our Component&lt;/h3>
&lt;h4 id="component-class">Component Class&lt;/h4>
&lt;p>First, we need three lists, which we shall add as properties of the class: todo, done and cancelled. We shall initialize the first to with some initial to-do and done items:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">todo&lt;/span>: &lt;span style="color:#66d9ef">Todo&lt;/span>[] &lt;span style="color:#f92672">=&lt;/span> [
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Get to work&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() },
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Pick up groceries&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() },
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Go home&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() },
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Fall asleep&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() }
];
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">done&lt;/span>: &lt;span style="color:#66d9ef">Todo&lt;/span>[] &lt;span style="color:#f92672">=&lt;/span> [
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Get up&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() },
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Brush teeth&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() },
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Take a shower&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() },
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Check e-mail&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() },
  { &lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Walk dog&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() }
];
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">cancelled&lt;/span>: &lt;span style="color:#66d9ef">Todo&lt;/span>[] &lt;span style="color:#f92672">=&lt;/span> [];
&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="adding-new-to-do-items">Adding new To-Do Items&lt;/h5>
&lt;p>Next, we need a method to add new items to either the to-do or done lists:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">addItem&lt;/span>(&lt;span style="color:#a6e22e">list&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">todo&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) {
  &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">list&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#e6db74">&amp;#39;todo&amp;#39;&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">todo&lt;/span>.&lt;span style="color:#a6e22e">push&lt;/span>({ &lt;span style="color:#a6e22e">title&lt;/span>: &lt;span style="color:#66d9ef">todo&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() });
  } &lt;span style="color:#66d9ef">else&lt;/span> {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">done&lt;/span>.&lt;span style="color:#a6e22e">push&lt;/span>({ &lt;span style="color:#a6e22e">title&lt;/span>: &lt;span style="color:#66d9ef">todo&lt;/span>, &lt;span style="color:#a6e22e">dateAdded&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">toString&lt;/span>() });
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="moving-items-within-the-same-list-or-to-another-lists">Moving Items within the same list or to another Lists&lt;/h5>
&lt;p>And finally, a method that will be triggered when you drag and drop an item from one list to another.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">drop&lt;/span>(&lt;span style="color:#a6e22e">event&lt;/span>: &lt;span style="color:#66d9ef">CdkDragDrop&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">Todo&lt;/span>[]&lt;span style="color:#f92672">&amp;gt;&lt;/span>) {
  &lt;span style="color:#75715e">// first check if it was moved within the same list or moved to a different list
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">previousContainer&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">container&lt;/span>) {
    &lt;span style="color:#75715e">// change the items index if it was moved within the same list
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#a6e22e">moveItemInArray&lt;/span>(&lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">container&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">previousIndex&lt;/span>, &lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">currentIndex&lt;/span>);
  } &lt;span style="color:#66d9ef">else&lt;/span> {
    &lt;span style="color:#75715e">// remove item from the previous list and add it to the new array
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#a6e22e">transferArrayItem&lt;/span>(&lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">previousContainer&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">container&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">previousIndex&lt;/span>, &lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">currentIndex&lt;/span>);
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> The above method, either transfers an item between two arrays (lists) or moves a to-do item up or down in the array. First, you need to determine whether the user moved the content to another list, let’s say from to-do to done or they just re-arranged the items by moving an item up or down within the array. It uses the previousContainer and currentContainer properties to determine that. If the two are the same, then the user just re-arranged the list and not moving them. Then you use the &lt;code>transferArrayItem&lt;/code> to move items to a different array, and &lt;code>moveItemInArray&lt;/code> to move items within the same array.&lt;/p>
&lt;/blockquote>
&lt;h3 id="component-template">Component Template&lt;/h3>
&lt;p>We are using &lt;a href="https://getbootstrap.com/docs/4.1/getting-started/introduction/">Bootstrap&lt;/a> for the UI but feel free to use any &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI Framework&lt;/a> you are comfortable with. So, first we need to add some input controls to add new items to our to-do list:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-6&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-group&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>&amp;gt;New Task&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt; &amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">todoitem&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-control&amp;#34;&lt;/span> /&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-6&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-group&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>&amp;gt;List&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">select&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">todolist&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-control&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">option&lt;/span> &lt;span style="color:#a6e22e">selected&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;todo&amp;#34;&lt;/span>&amp;gt;To Do&amp;lt;/&lt;span style="color:#f92672">option&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">option&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;done&amp;#34;&lt;/span>&amp;gt;Done&amp;lt;/&lt;span style="color:#f92672">option&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">select&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-12 text-right&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">addItem&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">todolist&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span> &lt;span style="color:#a6e22e">todoitem&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;btn  btn-primary&amp;#34;&lt;/span>
&amp;gt;
Add Item
&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s add drag and drop list to our template. For this, we will be using the &lt;strong>cdk-drop&lt;/strong> to wrap around each of our lists (to-do, done and cancelled list). We will pass the following properties:&lt;/p>
&lt;ol>
&lt;li>Id (&lt;code>#todoList&lt;/code>) – the id of the drag and drop list&lt;/li>
&lt;li>Data source (&lt;code>[data]&lt;/code>) – the data source of the list i.e. to-do, cancelled and done arrays,&lt;/li>
&lt;li>Drag and Drop lists its connected to (&lt;code>[ConnectedTo]&lt;/code>) – This sets limits to which lists the user can drag and drop items to.&lt;/li>
&lt;li>And finally, the event that is called when a user drops an item &lt;code>(dropped)&lt;/code> .&lt;/li>
&lt;/ol>
&lt;p>So, our first list for to-do items will look like this. We are using &lt;code>*ngFor&lt;/code> directive to display the actual list inside the drag and drop list.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&lt;span style="color:#75715e">&amp;lt;!-- to-do items list --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">cdk-drop&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list-group list-group-flush&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">todoList&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">todo&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">connectedTo&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;[&lt;/span>&lt;span style="color:#a6e22e">doneList&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span> &lt;span style="color:#a6e22e">cancelledList&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">dropped&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">drop&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list-group-item list-group-item-primary&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let item of todo&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">cdkDrag&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">p&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;mb-1&amp;#34;&lt;/span>&amp;gt;{{ item.title | titlecase }}&amp;lt;/&lt;span style="color:#f92672">p&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">small&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-muted&amp;#34;&lt;/span>&amp;gt; {{ item.dateAdded | date:&amp;#39;short&amp;#39; }}&amp;lt;/&lt;span style="color:#f92672">small&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">cdk-drop&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the same goes for done and cancelled lists:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&lt;span style="color:#75715e">&amp;lt;!-- Done to-do items list --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">cdk-drop&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">doneList&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">done&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">connectedTo&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;[&lt;/span>&lt;span style="color:#a6e22e">todoList&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span> &lt;span style="color:#a6e22e">cancelledList&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list-group list-group-flush&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">dropped&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">drop&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list-group-item list-group-item-success&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let item of done&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">cdkDrag&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">p&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;mb-1&amp;#34;&lt;/span>&amp;gt;{{ item.title | titlecase }}&amp;lt;/&lt;span style="color:#f92672">p&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">small&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-muted&amp;#34;&lt;/span>&amp;gt; {{ item.dateAdded | date:&amp;#39;short&amp;#39; }} &amp;lt;/&lt;span style="color:#f92672">small&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">cdk-drop&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- Cancelled to-do items list --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">cdk-drop&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">cancelledList&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">cancelled&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">connectedTo&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;[&lt;/span>&lt;span style="color:#a6e22e">todoList&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span> &lt;span style="color:#a6e22e">doneList&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list-group list-group-flush&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">dropped&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">drop&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list-group-item list-group-item-warning&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let item of cancelled&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">cdkDrag&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">p&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;mb-1&amp;#34;&lt;/span>&amp;gt;{{ item.title | titlecase }}&amp;lt;/&lt;span style="color:#f92672">p&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">small&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-muted&amp;#34;&lt;/span>&amp;gt; {{ item.dateAdded | date:&amp;#39;short&amp;#39; }} &amp;lt;/&lt;span style="color:#f92672">small&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">cdk-drop&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, you can now wrap each of those drag and drop lists with a bootstrap card component:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;card bg-warning&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;card-header text-white&amp;#34;&lt;/span>&amp;gt;&amp;lt;&lt;span style="color:#f92672">h2&lt;/span>&amp;gt;Cancelled&amp;lt;/&lt;span style="color:#f92672">h2&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- Lists Here --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can find the complete template &lt;a href="https://github.com/MainaWycliffe/ng-material7-drag-and-drop-demo/blob/master/src/app/app.component.html">here&lt;/a>.&lt;/p>
&lt;h3 id="source-code-and-demo">Source Code and Demo&lt;/h3>
&lt;p>You can find the demo for the above project &lt;a href="https://mainawycliffe.github.io/ng-material7-drag-and-drop-demo/">here&lt;/a> and the source code &lt;a href="https://github.com/MainaWycliffe/ng-material7-drag-and-drop-demo">here&lt;/a>.&lt;/p></description></item><item><title>Using App Shell to Improve Performance – Angular 6</title><link>https://codinglatte.com/posts/angular/app-shell-improve-performance-angular-6/</link><pubDate>Mon, 01 Oct 2018 12:07:46 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/app-shell-improve-performance-angular-6/</guid><description>&lt;p>Angular apps take time to show meaningful content to the user. This time is mainly after loading the index.html page and bootstrapping the app. This is especially worse on lower end devices or slower networks, where it takes longer to get the all files required to bootstrap the app. It is therefore important to show some animation or an app shell, to indicate to the user that your web app is not broken. When it takes longer to paint something on the web page, most users will likely leave your app, most likely for a competitor. And we all want to avoid that.&lt;/p>
&lt;p>There are several ways around this, the first one, is using a simple loading animation, indicating to the user something is happening on the background. And the second option, is loading the app shell – title bar, navigation etc. of the app, then some animation where the data will be placed after bootstrapping. Let’s first look at the loading animation, and then the app shell option:&lt;/p>
&lt;h1 id="using-a-simple-loading-animationmessage">Using a Simple Loading Animation/Message&lt;/h1>
&lt;p>This is the easiest option, it involves using CSS and html to create an animation or print a message to the user, as they wait for the app to load and bootstrap. This is important, as it indicates to them, that something is happening in the background instead of a blank page. Achieving this is rather straightforward, open the &lt;code>index.html&lt;/code> file, under the &lt;code>src&lt;/code> directory in the root of your &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">angular workspace&lt;/a>. Add the animation code in between &lt;code>&amp;lt;app-root&amp;gt; &amp;lt;/app-root&amp;gt;&lt;/code> tags. Why here? This is because, after the app has successfully bootstrapped, it will replace the content in between with the application itself. So, our animation code will look something like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-root&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-center bg-primary p-2&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;height: 100vh;&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;container align-middle p-5&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;fa fa-spinner fa-spin fa-3x&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt;&amp;lt;&lt;span style="color:#f92672">br&lt;/span> /&amp;gt;Loading ...
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">app-root&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>I am using font-awesome and bootstrap for this demo, so remember to add the minified CSS imports at the header section.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">link&lt;/span>
&lt;span style="color:#a6e22e">rel&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;stylesheet&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">integrity&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">crossorigin&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;anonymous&amp;#34;&lt;/span>
/&amp;gt;
&amp;lt;&lt;span style="color:#f92672">link&lt;/span>
&lt;span style="color:#a6e22e">rel&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;stylesheet&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;https://use.fontawesome.com/releases/v5.3.1/css/all.css&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">integrity&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">crossorigin&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;anonymous&amp;#34;&lt;/span>
/&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And this is what it looks like: &lt;img src="//wp-content/uploads/2018/10/Sequence-1-1-.gif" alt="Using App Shell to Improve Performance – Angular 6"> &lt;strong>NB:&lt;/strong> &lt;em>You  can make it lighter and easier to load by using pure CSS to load the animation, instead of using &lt;a href="https://getbootstrap.com/">Bootstrap&lt;/a> and &lt;a href="https://fontawesome.com/">Font Awesome&lt;/a>, which is overkill for a simple animation. But if you are using both of these libraries somewhere else, this is a great way to load them and keep them outside your final angular bundle.&lt;/em>&lt;/p>
&lt;h1 id="using-an-app-shell">Using an App Shell&lt;/h1>
&lt;p>Now, let’s take the above process a step further. We can use angular cli to generate an app shell for a specific route. An app shell is the skeleton of an app – navigation, title bar, menu etc. In angular, you can prerender a specific route, to create an app shell which will be show to the user as they wait for the to bootstrap. This will include all components, in between the app-root and the router outlet of the prerendered route. The component to be loaded in the router-outlet is then replaced by the app shell component, this component is where you would add a loading animation or message.&lt;/p>
&lt;blockquote>
&lt;p>NB: &lt;em>Unfortunately, as far as I can tell from my own research, you can only create for one route in an angular project.&lt;/em> So, let’s first generate an app shell for our application, using the &lt;a href="https://github.com/angular/angular-cli/wiki/generate-app-shell">ng generate&lt;/a> app-shell command:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$  ng generate app-shell --client-project angular-app-shell-demo --universal-project angular-app-shell-demo-rendered
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Where: &lt;code>client-project&lt;/code> is the project you want to generate the app shell for. And &lt;code>--universal-project&lt;/code> is the name of server app or universal app, the option we will use to prerender our app shell. You may also want to include a &lt;code>--route&lt;/code>, if you don’t want to create an app shell for the default route.&lt;/p>
&lt;h2 id="changes-to-your-angular-project">Changes to your Angular Project&lt;/h2>
&lt;p>When you run the above command, it makes some changes to your angular application. If you look at &lt;code>angular.json&lt;/code>, you will see a few modifications:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;server&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
  &lt;span style="color:#f92672">&amp;#34;builder&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;@angular-devkit/build-angular:server&amp;#34;&lt;/span>,
    &lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
      &lt;span style="color:#f92672">&amp;#34;outputPath&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;dist/angular-app-shell-demo-server&amp;#34;&lt;/span>,
      &lt;span style="color:#f92672">&amp;#34;main&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/main.server.ts&amp;#34;&lt;/span>,
      &lt;span style="color:#f92672">&amp;#34;tsConfig&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/tsconfig.server.json&amp;#34;&lt;/span>
      }
    }&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;app-shell&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
   &lt;span style="color:#f92672">&amp;#34;builder&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;@angular-devkit/build-angular:app-shell&amp;#34;&lt;/span>,
   &lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
     &lt;span style="color:#f92672">&amp;#34;browserTarget&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;angular-app-shell-demo:build&amp;#34;&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;serverTarget&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;angular-app-shell-demo:server&amp;#34;&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;route&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;shell&amp;#34;&lt;/span>
   },
  &lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: {
    &lt;span style="color:#f92672">&amp;#34;production&amp;#34;&lt;/span>: {
      &lt;span style="color:#f92672">&amp;#34;browserTarget&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;angular-app-shell-demo:build:production&amp;#34;&lt;/span>
    }
  }
}
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Another key change to take note of, is the component generated - &lt;strong>AppShellComponent&lt;/strong>. This is a normal component, apart from the fact that it is registered with Server Module instead of the App Module. The Server Module was also generated by the generate app-shell command and can be found in the same directory as the app module.&lt;/p>
&lt;h2 id="building-your-angular-application">Building your Angular Application&lt;/h2>
&lt;p>To build our application with an app shell, all you have to do is run the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng run angular-app-shell-demo:&amp;lt;app-shell-name&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Replace the &lt;code>&amp;lt;app-shell-name&amp;gt;&lt;/code> with the name of the app shell name, you specified when generating the app shell. This will first prerender the path, and then build your angular app just as normal. But, if you look at your final index.html, you will notice it has extra content, unlike a normal one:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-root&lt;/span> &lt;span style="color:#a6e22e">_nghost-sc0&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">ng-version&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;6.1.9&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">_ngcontent-sc0&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;container&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">nav&lt;/span> &lt;span style="color:#a6e22e">_ngcontent-sc0&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;navbar navbar-light bg-light&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">_ngcontent-sc0&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;navbar-brand&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span>
&amp;gt;&amp;lt;&lt;span style="color:#f92672">img&lt;/span>
&lt;span style="color:#a6e22e">_ngcontent-sc0&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">alt&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;d-inline-block align-top&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">height&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;30&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">src&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/docs/4.1/assets/brand/bootstrap-solid.svg&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">width&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;30&amp;#34;&lt;/span>
/&amp;gt;
My Application
&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">nav&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">router-outlet&lt;/span> &lt;span style="color:#a6e22e">_ngcontent-sc0&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">router-outlet&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-app-shell&lt;/span> &lt;span style="color:#a6e22e">_nghost-sc1&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">_ngcontent-sc1&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">_ngcontent-sc1&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-12 text-center&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">_ngcontent-sc1&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;fas fa-spinner fa-spin&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt; Loading
application
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">app-app-shell&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">app-root&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>All the above content is pulled from all components content right up to the router-outlet of the path. So, any modification you make to the components, will be reflected to the app shell when you build the application. This is certainly better than the first option of adding a loading animator directly to the index.html. To view the app shell, all you have to do is navigate to the route you generated for the app shell. In our case it was the default route, so navigating to it, you will see loading message from the app shell component, before being replaced by the actual content from the message. &lt;img src="//wp-content/uploads/2018/10/demo-2.gif" alt="Using App Shell to Improve Performance – Angular 6">&lt;/p>
&lt;h1 id="source-code">Source Code&lt;/h1>
&lt;p>You can find the source code of the app shell &lt;a href="https://github.com/MainaWycliffe/angular-app-shell-demo">here&lt;/a>.&lt;/p></description></item><item><title>Role Based Authorization in Angular – Route Guards</title><link>https://codinglatte.com/posts/angular/role-based-authorization-in-angular-route-guards/</link><pubDate>Fri, 28 Sep 2018 14:46:17 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/role-based-authorization-in-angular-route-guards/</guid><description>&lt;p>In this post, we are going to use Route Guards to determine which user can and can not access certain pages. It is common to have multiple user roles such as guest, author, editor, admin for a blogging site such as this one. Therefore, it is important to determine who has access to what routes, so as to provide a good user experience (UX). NB:&lt;/p>
&lt;p>For security purpose, this should not be used as the only solution, similar security measures needs to be implemented at the backend server. This is because, other developers and hackers can be able to manipulate the frontend app to gain access. This should be used mainly to provide a consistent and good user experience to the end user.&lt;/p>
&lt;p>In this post, we shall use JSON Web Tokens (JWTs), which will contain the user role of the current user. The JWT token, shall have a user role added to it on the server, after signing in together with other user details such as email, username, full name etc. This post assumes that you have a backend ready and working.&lt;/p>
&lt;h3 id="why-jwts">Why JWTs?&lt;/h3>
&lt;p>JSON Web Tokens, has three sections, the header, payload and signature. The header contains information about the token and hashing algorithm used, while the payload contains information such as user information, expiry time and any information you wish to add.&lt;/p>
&lt;p>The Signature part is why we are using JWTs. It secures the token, ensuring that if someone – say a frontend user – tampers with it, you will know. It is a hash of the encoded header and payload, along with a secret which only you should know. This makes it perfect, for &lt;a href="https://codinglatte.com/tech/developers/angular/attaching-authorization-token-angular-6/">authentication&lt;/a> and authorization purposes, passing information to the client that is tamper proof.&lt;/p>
&lt;p>This ensures that, if someone were to change the token on the frontend to beat the Route guard, the server would know if they tried to act using the token they modified, to change something. This of course relies on the fact that the secret key or password used to sign the token remains secret. You can learn more about JWTs &lt;a href="https://jwt.io/introduction/">here&lt;/a>.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>We will start by creating a new project in angular, with support for routing.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng new angular-role-based-authorization --routing true
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we need a library to read JWT Tokens in Angular. For that, we will use &lt;a href="https://github.com/auth0/angular2-jwt">&lt;code>angular2-jwt&lt;/code>&lt;/a> by &lt;a href="https://auth0.com/">Auth0&lt;/a>.&lt;/p>
&lt;p>Let’s add it in our app and add it to our list of imports in our app module. So, first install it using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">// Using NPM:
$ npm install @auth0/angular-jwt
// or using Yarn:
$ yarn add @auth0/angular-jwt
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, add it to the list of imported modules in our app module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">JwtModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@auth0/angular-jwt&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">JwtModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>({})
],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="routes">Routes&lt;/h3>
&lt;p>Our first action will be to create routes for our demo app. We shall embed the roles required by each of the routes on the route object. This way, each route shall be aware of the roles it will allow access to it and you can just check the user role against allowed roles:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">{
  &lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;author&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">component&lt;/span>: &lt;span style="color:#66d9ef">AuthorComponent&lt;/span>,
  &lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
    &lt;span style="color:#a6e22e">allowedRoles&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;admin&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;author&amp;#39;&lt;/span>]
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>So, in the case of author route, we shall allow users with author and admin role. The same would go for writer route, where we shall allow admin, writer and author.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">{
  &lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;writer&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">component&lt;/span>: &lt;span style="color:#66d9ef">WriterComponent&lt;/span>,
  &lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
    &lt;span style="color:#a6e22e">allowedRoles&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;admin&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;writer&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;author&amp;#39;&lt;/span>]
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The reason for embedding roles on the routes, is to enable us to use a single route guard for all our routes. Removing the need for repetition.&lt;/p>
&lt;h3 id="authorization-service">Authorization Service&lt;/h3>
&lt;p>Next, we need to create a service to determine whether a user role is allowed to access a route. We shall read the user role from the JWT Token, then check whether the role is in the list of allowed Roles, contained in the data. If the list of allowed roles is empty, we shall grant user access but only deny them access if their role is not listed in the allowed list. First, let’s create a new service:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng generate service authorization
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then inject the JwtHelperService service into our service, so we can decode tokens:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">jwtHelperService&lt;/span>: &lt;span style="color:#66d9ef">JwtHelperService&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, add a method to check if the user is authorized. It will accept allowed roles string array and check whether current user role is among the roles that are allowed:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">isAuthorized&lt;/span>(&lt;span style="color:#a6e22e">allowedRoles&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>[])&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">boolean&lt;/span> {
  &lt;span style="color:#75715e">// check if the list of allowed roles is empty, if empty, authorize the user to access the page
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">allowedRoles&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span> &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#a6e22e">allowedRoles&lt;/span>.&lt;span style="color:#a6e22e">length&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>) {
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>;
  }
&lt;span style="color:#75715e">// get token from local storage or state management
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">getItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>);
&lt;span style="color:#75715e">// decode token to read the payload details
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">decodeToken&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">jwtHelperService&lt;/span>.&lt;span style="color:#a6e22e">decodeToken&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>);
&lt;span style="color:#75715e">// check if it was decoded successfully, if not the token is not valid, deny access
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">decodeToken&lt;/span>) {
    &lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;Invalid token&amp;#39;&lt;/span>);
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>;
  }
&lt;span style="color:#75715e">// check if the user roles is in the list of allowed roles, return true if allowed and false if not allowed
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">allowedRoles&lt;/span>.&lt;span style="color:#a6e22e">includes&lt;/span>(&lt;span style="color:#a6e22e">decodeToken&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;role&amp;#39;&lt;/span>]);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, add the service to the list of providers in the app module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AuthorizationService&lt;/span>],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="route-guard">Route Guard&lt;/h3>
&lt;p>Next, let’s add a route guard to our app.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate guard authorization
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, let’s inject our authorization service into the route guard.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">authorizationService&lt;/span>: &lt;span style="color:#66d9ef">AuthorizationService&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">router&lt;/span>: &lt;span style="color:#66d9ef">Router&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We also need to implement the &lt;a href="https://angular.io/api/router/CanActivate">&lt;code>CanActivate&lt;/code>&lt;/a> and &lt;a href="https://angular.io/api/router/CanActivateChild">&lt;code>CanActivateChild&lt;/code>&lt;/a> interfaces, which will check whether a user is authorized.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AuthorizationGuard&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">CanActivate&lt;/span>, &lt;span style="color:#a6e22e">CanActivateChild&lt;/span> {
&lt;span style="color:#a6e22e">canActivate&lt;/span>(
&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRouteSnapshot&lt;/span>,
&lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">RouterStateSnapshot&lt;/span>
)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#66d9ef">boolean&lt;/span> {}
&lt;span style="color:#a6e22e">canActivateChild&lt;/span>(
&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRouteSnapshot&lt;/span>,
&lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">RouterStateSnapshot&lt;/span>
)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#66d9ef">boolean&lt;/span> {}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, let’s add the two methods to our router guard. They will have similar content; the only difference is that, one checks if a route can be activated while the other checks if children routes can be activated. So, inside both two methods, we need to first get the allowed roles for that route:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">allowedRoles&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>.&lt;span style="color:#a6e22e">allowedRoles&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, check if the user is authorized to access the route:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">isAuthorized&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">authorizationService&lt;/span>.&lt;span style="color:#a6e22e">isAuthorized&lt;/span>(&lt;span style="color:#a6e22e">allowedRoles&lt;/span>);
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">isAuthorized&lt;/span>) {
&lt;span style="color:#75715e">// if not authorized, show access denied message
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#39;/accessdenied&amp;#39;&lt;/span>]);
}
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">isAuthorized&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>So, I our canActivate method will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">canActivate&lt;/span>(&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRouteSnapshot&lt;/span>, &lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">RouterStateSnapshot&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#66d9ef">boolean&lt;/span> {
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">allowedRoles&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>.&lt;span style="color:#a6e22e">allowedRoles&lt;/span>;
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">isAuthorized&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">authorizationService&lt;/span>.&lt;span style="color:#a6e22e">isAuthorized&lt;/span>(&lt;span style="color:#a6e22e">allowedRoles&lt;/span>);
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">isAuthorized&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#39;accessdenied&amp;#39;&lt;/span>]);
  }
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">isAuthorized&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And &lt;code>canActivateChildMethod&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">canActivateChild&lt;/span>(&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRouteSnapshot&lt;/span>, &lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">RouterStateSnapshot&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#66d9ef">boolean&lt;/span> {
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">allowedRoles&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>.&lt;span style="color:#a6e22e">allowedRoles&lt;/span>;
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">isAuthorized&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">authorizationService&lt;/span>.&lt;span style="color:#a6e22e">isAuthorized&lt;/span>(&lt;span style="color:#a6e22e">allowedRoles&lt;/span>);
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">isAuthorized&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#39;accessdenied&amp;#39;&lt;/span>]);
  }
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">isAuthorized&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, let’s add the guard to our parent route:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">routes&lt;/span>: &lt;span style="color:#66d9ef">Routes&lt;/span> &lt;span style="color:#f92672">=&lt;/span> [
{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">canActivateChild&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AuthorizationGuard&lt;/span>],
&lt;span style="color:#a6e22e">children&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// routes here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ]
}
];
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="demo-and-source-code">Demo and Source Code&lt;/h3>
&lt;p>And that’s it, we have a role-based authorization for our angular application. You can visit the following &lt;a href="https://mainawycliffe.github.io/angular-role-based-authorization/">link&lt;/a> to see and play with the demo. You can also find the source code &lt;a href="https://github.com/MainaWycliffe/angular-role-based-authorization">here&lt;/a>.&lt;/p></description></item><item><title>Docker Compose - Angular Multi Environment Deployments</title><link>https://codinglatte.com/posts/angular/docker-compose-angular-multi-environment-deployments/</link><pubDate>Wed, 26 Sep 2018 10:44:16 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/docker-compose-angular-multi-environment-deployments/</guid><description>&lt;p>In a previous &lt;a href="https://codinglatte.com/tech/developers/angular/building-docker-images-angular/">post&lt;/a>, we covered how to use multiple dockerfile to target different environments for an angular app. In this post, we are going to take things a bit further along using docker compose. We shall use multiple docker compose configuration files to override the defaults in the main configuration files when deploying to different environment.&lt;/p>
&lt;p>This means that, if we have 3 environment – development, staging and production environment, we shall have four docker-compose configurations file. The main docker-compose.yml, shall contain only base configuration common to all our environments. Then we shall have other 3 docker-compose configuration files for each of our environments: &lt;code>docker-compose.override.yml&lt;/code>, &lt;code>docker-compose.staging.yml&lt;/code> and &lt;code>docker-compose.prod.yml&lt;/code>.&lt;/p>
&lt;p>The 3 extra docker compose files shall be used to override base configuration contained in the main docker compose configuration file. This means, if you can launch an angular app on different ports depending on environment, use different dockerfiles and different images and container names etc. The last point is especially useful since it means you won’t accidentally deploy a staging image into production environment because they have similar names.&lt;/p>
&lt;p>Docker compose by default, will read both the main configuration file and &lt;em>docker-compose.override.yml&lt;/em> if it’s available. So, when deploying to the other two environments, you can specify the override file to use. You can learn more about using multiple docker compose files &lt;a href="https://docs.docker.com/compose/extends/">here&lt;/a>. And to make things easier, we shall add the docker compose build commands into our list of scripts in &lt;code>package.json&lt;/code>. Without further ado:&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>On the previous post, &lt;a href="https://codinglatte.com/tech/developers/angular/building-docker-images-angular/">here&lt;/a>, we covered how to build images and using multiple dockerfiles. In this post, we are going to be building on that and add docker compose to our project. If you can recall, all our docker files and related docker files, are in a directory at the root of our &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">angular workspace&lt;/a> called &lt;code>.docker&lt;/code>.&lt;/p>
&lt;p>We are now going to add 4 extra docker compose configuration files at the root of our angular workspace. The files will be name &lt;code>docker-compose.yml&lt;/code>, &lt;code>docker-compose.override.yml&lt;/code>, &lt;code>docker-compose.staging.yml&lt;/code> and &lt;code>docker-compose.prod.yml&lt;/code>.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/docker-compose-angular-multi-environment-deployments/images/folder-structure.png" alt="Docker Compose - Angular Multi Environment Deployments" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>Next, we are going to add docker configurations for each file specific to the environment we targeting:&lt;/p>
&lt;h3 id="base-confuguration--docker-composeyml">Base Confuguration – docker-compose.yml&lt;/h3>
&lt;p>This shall contain common configurations between our three environments. Although, any configurations you add here, can easily be overridden by the environment compose configuration files such as &lt;code>docker-compose.override.yml&lt;/code>. So, it is also possible to add default configurations here and override them when necessary. For this configuration, we shall only have a default docker file.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">version&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;3&amp;#39;&lt;/span>
&lt;span style="color:#66d9ef">services&lt;/span>:
  &lt;span style="color:#66d9ef">demongapp&lt;/span>:
    &lt;span style="color:#66d9ef">build&lt;/span>:
      &lt;span style="color:#66d9ef">context&lt;/span>: .
      &lt;span style="color:#66d9ef">dockerfile&lt;/span>: .docker/prod.dockerfile
  &lt;span style="color:#75715e"># other services here like API, Database ETC&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let’s extend or override this compose configurations for local development.&lt;/p>
&lt;h3 id="local-development-and-testing">Local Development and Testing&lt;/h3>
&lt;p>For Local Development, we shall use the &lt;code>docker-compose.override.yml&lt;/code> file to override default compose configurations. The good thing about using this file, is that you don’t need to specify it during docker compose build. It will automatically read it and override it if it is available.&lt;/p>
&lt;p>So, in our case, we need to provide a name for our image and container, launch it on port 8080 and use the development dockerfile instead of the production dockerfile. This is how our docker compose override will look like after we provide the above information:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">version&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;3&amp;#39;&lt;/span>
&lt;span style="color:#66d9ef">services&lt;/span>:
  &lt;span style="color:#66d9ef">demongapp&lt;/span>:
    &lt;span style="color:#66d9ef">build&lt;/span>:
      &lt;span style="color:#66d9ef">context&lt;/span>: .
      &lt;span style="color:#66d9ef">dockerfile&lt;/span>: .docker/dev.dockerfile
    &lt;span style="color:#66d9ef">image&lt;/span>: demongapp-dev
    &lt;span style="color:#66d9ef">container_name&lt;/span>: demongapp-dev
    &lt;span style="color:#66d9ef">ports&lt;/span>:
      - &lt;span style="color:#ae81ff">8080&lt;/span>:&lt;span style="color:#ae81ff">80&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You might want to mount your app distribution folder, to avoid building your container every time you build your app after making changes. When building your app, with a mounted app distribution directory, you must specify the &lt;code>--delete-output-path false&lt;/code> flag. This flag tells angular cli not to delete app distribution directory.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng build --delete-output-path false
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Remember your app distribution directory, is a directory whose name is the app name located inside the &lt;code>dist&lt;/code> directory at the root of your angular workspace.&lt;/p>
&lt;/blockquote>
&lt;p>Now, if you run docker-compose up –build, it will automatically read both the base compose configurations and override it automatically. No need to have complicated build commands for local development, unlike the other two environments. Now, let’s move on to the next two environments.&lt;/p>
&lt;h3 id="staging-and-production-deployments">Staging and Production Deployments&lt;/h3>
&lt;p>I am going to discuss this two together, as there is no difference in approach on how to implement both, unlike in local deployment. The only difference are the names for our images and containers. So, our staging compose configurations will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">version&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;3&amp;#39;&lt;/span>
&lt;span style="color:#66d9ef">services&lt;/span>:
  &lt;span style="color:#66d9ef">demongapp&lt;/span>:
    &lt;span style="color:#66d9ef">build&lt;/span>:
      &lt;span style="color:#66d9ef">context&lt;/span>: .
      &lt;span style="color:#66d9ef">dockerfile&lt;/span>: .docker/staging.dockerfile
    &lt;span style="color:#66d9ef">image&lt;/span>: demongapp-staging
    &lt;span style="color:#66d9ef">container_name&lt;/span>: demongapp-staging
    &lt;span style="color:#66d9ef">ports&lt;/span>:
      - &lt;span style="color:#ae81ff">80&lt;/span>:&lt;span style="color:#ae81ff">80&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And our production compose configurations will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">version&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;3&amp;#39;&lt;/span>
&lt;span style="color:#66d9ef">services&lt;/span>:
  &lt;span style="color:#66d9ef">demongapp&lt;/span>:
    &lt;span style="color:#66d9ef">build&lt;/span>:
      &lt;span style="color:#66d9ef">context&lt;/span>: .
      &lt;span style="color:#66d9ef">dockerfile&lt;/span>: .docker/prod.dockerfile
    &lt;span style="color:#66d9ef">image&lt;/span>: demongapp-prod
    &lt;span style="color:#66d9ef">container_name&lt;/span>: demongapp-prod
    &lt;span style="color:#66d9ef">ports&lt;/span>:
      - &lt;span style="color:#ae81ff">80&lt;/span>:&lt;span style="color:#ae81ff">80&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now to instruct docker compose to build and deploy our image for staging, we use the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">docker-compose -f docker-compose.yml -f docker-compose.staging.yml up -d –build
&lt;/code>&lt;/pre>&lt;/div>&lt;p>It is quite long and hard to remember. Please note, we are specifying two configuration files, the main docker-compose and an override for staging docker compose. And the same goes for production environment:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d –build
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="using-npm-scripts-to-shorten-the-commands">Using NPM Scripts to Shorten the Commands&lt;/h3>
&lt;p>Now, to make these commands to remember, you can use &lt;a href="https://docs.npmjs.com/misc/scripts">NPM scripts&lt;/a> to run these commands. Open package.json, at the root of your angular workspace, and add the two scripts, one for deploying in staging and another for deploying production environment.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;scripts&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
  &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
  &lt;span style="color:#f92672">&amp;#34;deploy-staging&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;docker-compose -f docker-compose.yml -f docker-compose.staging.yml up -d --build&amp;#34;&lt;/span>,
  &lt;span style="color:#f92672">&amp;#34;deploy-prod&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And now, you can run the above scripts as shown below:&lt;/p>
&lt;ol>
&lt;li>Staging:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm run deploy-staging
&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="2">
&lt;li>Production:&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm run deploy-staging
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="source-code">Source Code&lt;/h3>
&lt;p>You can find the whole code for this project &lt;a href="https://github.com/MainaWycliffe/angular-docker-deployment">here&lt;/a>.&lt;/p></description></item><item><title>Attaching Authorization Token Headers in Angular 6</title><link>https://codinglatte.com/posts/angular/attaching-authorization-token-angular-6/</link><pubDate>Sun, 23 Sep 2018 12:55:26 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/attaching-authorization-token-angular-6/</guid><description>&lt;p>In a previous post &lt;a href="https://codinglatte.com/tech/developers/angular/refreshing-authorization-tokens-angular-6/">here&lt;/a>, we looked at how to intercept HTTP unauthorized responses, and refresh authorization tokens and resend the original request, with the new authorization token. This had me thinking, what if you wanted to be more proactive. In this post, we want to get the authorization token, check if it’s expired and refresh it just before attaching it to the HTTP request. We also need to avoid sending multiple authorization token refresh requests, but rather queue the request behind a single request response and use the new authorization token when it is received.&lt;/p>
&lt;h1 id="how-it-works">How it Works&lt;/h1>
&lt;p>For our authorization token, we will be using &lt;a href="https://jwt.io/">JWT&lt;/a> (JSON Web Tokens) standard. We will need to check before every request whether it is expired (or close to expire) and send a request to refresh it. So, we need a library to read JWT Tokens, we will use &lt;a href="https://github.com/auth0/angular2-jwt">angular2-jwt&lt;/a> by &lt;a href="https://auth0.com/">Auth0&lt;/a>. We will also require a service – Auth Service, that will fetch and return the token to us as an observable.&lt;/p>
&lt;p>The service will also be checking whether the token is expired, and then send a refresh request. The observable returned by the service will be shared across multiple requests. On top of that, we of course need a HTTP Interceptor, to attach an authorization header to every outgoing request. To make things much easier, we will not start a new project this time. We are going to build on top of the previous post, which you can find &lt;a href="https://codinglatte.com/tech/developers/angular/refreshing-authorization-tokens-angular-6/">here&lt;/a>. It already has an Authentication Service and a HTTP Interceptor. So, without further ado:&lt;/p>
&lt;h1 id="getting-started">Getting Started&lt;/h1>
&lt;p>We already have a project, so in this case, we just need to add &lt;a href="https://github.com/auth0/angular2-jwt">angular2-jwt&lt;/a> library. You can use your favorite package manager to add it: Using NPM:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ npm install @auth0/angular-jwt
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Using Yarn Package Manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ yarn add @auth0/angular-jwt
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Feel free to use any other library you are comfortable with. Since, we are only interested with decoding JSON, and not the rest of functionality offered by the library, we are going to use only the &lt;code>JwtHelperService&lt;/code>. So, let’s register the service, to our list of providers in our app module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">JwtHelperService&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@auth0/angular-jwt&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [ ... ],
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [...],
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    {
      &lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">HTTP_INTERCEPTORS&lt;/span>,
      &lt;span style="color:#a6e22e">useClass&lt;/span>: &lt;span style="color:#66d9ef">HttpAuthInterceptor&lt;/span>,
      &lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
    },
    &lt;span style="color:#a6e22e">JwtHelperService&lt;/span>
  ],
  &lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to add the functionality to fetch the token and check if it’s expired. If it’s expired, we are going to refresh it and return the new token.&lt;/p>
&lt;h1 id="fetching-and-refreshing-tokens">Fetching and Refreshing Tokens&lt;/h1>
&lt;p>This task will be completed by our authentication service. We need to add a new method – &lt;code>getToken()&lt;/code> inside our service. On top of that, we also need to inject &lt;code>JwtHelperService&lt;/code> into our service, so we can use it within the method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">decoder&lt;/span>: &lt;span style="color:#66d9ef">JwtHelperService&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then create our new method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">getToken&lt;/span>() &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">string&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: Our method returns only an observable string, which is the token. Next, let’s add a method to fetch a token and check if it is expired. We will be storing our tokens in local-storage. Please note, you can also use state management libraries like &lt;a href="https://codinglatte.com/tech/developers/angular/ngxs-authentication-angular/">NGXS&lt;/a>/NGRX/Akita to store tokens. First, let’s get the token from local storage:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">getItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, check if its expired using &lt;strong>JwtHelperService&lt;/strong> service:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">isTokenExpired&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">decoder&lt;/span>.&lt;span style="color:#a6e22e">isTokenExpired&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, let’s return an observable of the authorization token string, if it is not expired:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">isTokenExpired&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And if it is expired, we need to send a refresh request to get a new authorization token. In the previous post, we had already built a method to refresh an expired token. It basically sends the expired token and a refresh token to a refresh token endpoint and gets back new once. On top of that, we shared the observable and saved the authorization tokens to our local storage inside the same method. Here is what the method looks like:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">refreshToken&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">string&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;url to refresh token here&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">// append refresh token if you have one
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">refreshToken&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">getItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>);
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">expiredToken&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">getItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>);
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>
    .&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#a6e22e">url&lt;/span>, {
      &lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">HttpHeaders&lt;/span>()
        .&lt;span style="color:#a6e22e">set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">refreshToken&lt;/span>)
        .&lt;span style="color:#a6e22e">set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">expiredToken&lt;/span>),
      &lt;span style="color:#a6e22e">observe&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;response&amp;#39;&lt;/span>
    })
    .&lt;span style="color:#a6e22e">pipe&lt;/span>(
      &lt;span style="color:#a6e22e">share&lt;/span>(), &lt;span style="color:#75715e">// &amp;lt;========== YOU HAVE TO SHARE THIS OBSERVABLE TO AVOID MULTIPLE REQUEST BEING SENT SIMULTANEOUSLY
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
        &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>);
        &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">newRefreshToken&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>);
        &lt;span style="color:#75715e">// store the new tokens
&lt;/span>&lt;span style="color:#75715e">&lt;/span>        &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">setItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">newRefreshToken&lt;/span>);
        &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">setItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">token&lt;/span>);
        &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span>;
     })
  );
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We are going to utilize the same method to renew our authorization token. So, let’s call the &lt;code>refreshToken()&lt;/code> method and return it inside our &lt;code>getToken()&lt;/code> method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">refreshToken&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>So, our complete &lt;strong>getToken()&lt;/strong> method will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">getToken&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">string&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">getItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>);
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">isTokenExpired&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">decoder&lt;/span>.&lt;span style="color:#a6e22e">isTokenExpired&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>);
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">isTokenExpired&lt;/span>) {
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>);
  }
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">refreshToken&lt;/span>();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="attaching-authorization-header">Attaching Authorization Header&lt;/h1>
&lt;p>Our HTTP Interceptor already intercepts response with 401 and refreshes the token. We don’t want to remove that, but rather add our new functionality on top of it. This is because, due to network latency, the request might take longer than anticipated and the authorization token expires before getting to the server. So, we still need to intercept expired token responses from the server and refresh them. So, first I want to bring your attention to &lt;code>inflightAuthRequest&lt;/code> property of the http interceptor. This holds the refresh requests in progress, so that other subsequent requests requiring to refresh their token can hitch onto it instead of sending their own refresh request. This is made possible by the &lt;a href="https://www.learnrxjs.io/operators/multicasting/share.html">share&lt;/a> operator of RXJS. So, foreach intercepted request, we need to check if the &lt;code>inflightAuthRequest&lt;/code> is set, and subscribe to it. If not set, we need to initiate a new one.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">authService&lt;/span>.&lt;span style="color:#a6e22e">getToken&lt;/span>();
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we will use &lt;a href="https://www.learnrxjs.io/operators/transformation/switchmap.html">switchMap&lt;/a>, to send the initial request we intercepted after we got the token from the &lt;code>getToken()&lt;/code> method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span>.&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">switchMap&lt;/span>((&lt;span style="color:#a6e22e">newToken&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// unset request inflight
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#75715e">// use the newly returned token
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">authReq&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({
&lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">newToken&lt;/span>)
});
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">authReq&lt;/span>);
}),
&lt;span style="color:#a6e22e">catchError&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// the code to catch 401 response here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> })
);
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: Once the getToken method is resolved successfully, remember to unset the &lt;code>inflightAuthRequest&lt;/code> property, so that you don’t end up attaching an expired token to request that come after that.&lt;/p>
&lt;/blockquote>
&lt;p>The complete code for the above post can be found &lt;a href="https://github.com/MainaWycliffe/refreshing-authorization-token-angular-6">here&lt;/a>.&lt;/p></description></item><item><title>Cool Password Validation – Angular Reactive Forms</title><link>https://codinglatte.com/posts/angular/cool-password-validation-angular/</link><pubDate>Tue, 18 Sep 2018 23:34:54 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/cool-password-validation-angular/</guid><description>&lt;p>In this post, we are going to be creating a simple signup form, with email, password and confirm password controls. We will then validate the data to ensure it fulfills our requirement before a user can submit the form. We are going to enforce the following rules for the password:&lt;/p>
&lt;ul>
&lt;li>Must be at least 8 characters in length,&lt;/li>
&lt;li>Must be alphanumeric, with at least one upper and one lower case character&lt;/li>
&lt;li>And must have at least one special character.&lt;/li>
&lt;/ul>
&lt;p>We are going to validate each of the 5 rules individually using RegExp. And then, we will display a nice visual interface indicating to the user which rule they have not fulfilled. We will also be checking to see whether the password and the confirmation passwords are a match. Here is what the end-product will look like:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/cool-password-validation-angular/images/demo.gif" alt="Cool Password Validation – Angular Reactive Forms" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>In this demo, we are going to use &lt;a href="https://getbootstrap.com/">bootstrap&lt;/a> for the user interface and &lt;a href="https://material.io/tools/icons/">Material Icons&lt;/a> set for icons. Feel free to use the &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI Library&lt;/a> and &lt;a href="https://codinglatte.com/tech/developers/angular/svg-webfont-icon-packs/">Icon set&lt;/a> of your choice. So, without further ado.&lt;/p>
&lt;h2 id="getting-started">Getting Started&lt;/h2>
&lt;p>First, we are going to create a new project using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng new ng-bootstrap-password-validation-example
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we need to install and setup bootstrap for our angular project. First, install bootstrap using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ npm install -s bootstrap
// or
$ yarn add bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, add  bootstrap SCSS Styles to the list of styles for your project inside your &lt;code>angular.json&lt;/code> file. There are three of them, but only one is necessary - &lt;code>node_modules/bootstrap/scss/bootstrap.scss&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
  &lt;span style="color:#e6db74">&amp;#34;src/styles.css&amp;#34;&lt;/span>,
  &lt;span style="color:#e6db74">&amp;#34;node_modules/bootstrap/scss/bootstrap-grid.scss&amp;#34;&lt;/span>,
  &lt;span style="color:#e6db74">&amp;#34;node_modules/bootstrap/scss/bootstrap-reboot.scss&amp;#34;&lt;/span>,
  &lt;span style="color:#e6db74">&amp;#34;node_modules/bootstrap/scss/bootstrap.scss&amp;#34;&lt;/span>
]&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to add material icons to our angular project. Open your index.html (Located inside the &lt;code>src&lt;/code> directory at the root of your angular workspace) and add the following link:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">link&lt;/span>
&lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;https://fonts.googleapis.com/icon?family=Material+Icons&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">rel&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;stylesheet&amp;#34;&lt;/span>
/&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is the easiest way to add material icons to your project. If you are interested in learning of the other ways of adding material icons to any project, you can visit the official guide &lt;a href="https://google.github.io/material-design-icons/">here&lt;/a>. And finally, we need to vertically re-align material icons, so they appear more centralized. We will use the following CSS code:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-css" data-lang="css">.&lt;span style="color:#a6e22e">material-icons&lt;/span> {
 &lt;span style="color:#66d9ef">display&lt;/span>: &lt;span style="color:#66d9ef">inline&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#66d9ef">flex&lt;/span>;
 &lt;span style="color:#66d9ef">vertical-align&lt;/span>: &lt;span style="color:#66d9ef">middle&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Add the above code in your app styles, by default its &lt;code>styles.css&lt;/code> located under the &lt;code>src&lt;/code> directory at the root of your angular workspace. The last thing we need to do is import the modules we need in our app module. In this project, we are going to require &lt;code>ReactiveFormsModule&lt;/code> only, since we are building a reactive form. So, let’s add that module to our imports in the app module (By default &lt;code>app.module.ts&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  ...
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
   &lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
   &lt;span style="color:#a6e22e">ReactiveFormsModule&lt;/span>
  ],
  ...
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="building-a-custom-validator">Building a Custom Validator&lt;/h2>
&lt;p>Angular provides built in validators, but in our case they won’t help us achieve what we want. We need a custom validator that uses regex to check whether a password contains a special character or a number and report the error to back to us.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> If you want to learn more about creating a custom validator, please visit the following &lt;a href="https://codinglatte.com/tech/developers/angular/angular-building-custom-validators/">link&lt;/a> where I cover it in greater details.&lt;/p>
&lt;/blockquote>
&lt;p>So, our custom validator will accept the validation &lt;a href="https://www.w3schools.com/jsref/jsref_obj_regexp.asp">RegExp&lt;/a> expression, and validation error object to return if it encounters an error. For instance, if we want to check whether it has a number, we will pass the following:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">patternValidator&lt;/span>(&lt;span style="color:#e6db74">/\d/&lt;/span>, { &lt;span style="color:#a6e22e">hasNumber&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> }),
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Where &lt;code>/\d/&lt;/code> is the &lt;a href="https://www.w3schools.com/jsref/jsref_obj_regexp.asp">RegExp&lt;/a> expression for checking if it has a number and { hasNumber: true } is our error to return. The error part of our parameters will allow us to use the &lt;code>control&lt;/code>.&lt;code>hasError(&amp;quot;hasNumber&amp;quot;)&lt;/code> within our template, when checking whether to show the error. Now, let’s build our validator. First, we are going to create a &lt;code>CustomValidators&lt;/code> class, where we can place multiple custom validator methods for our project.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng g class custom-validators
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we are going to add a static pattern validator (patternValidator) method.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Follow the comments to see what individual lines of code do.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">patternValidator&lt;/span>(&lt;span style="color:#a6e22e">regex&lt;/span>: &lt;span style="color:#66d9ef">RegExp&lt;/span>, &lt;span style="color:#a6e22e">error&lt;/span>: &lt;span style="color:#66d9ef">ValidationErrors&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">ValidatorFn&lt;/span> {
  &lt;span style="color:#66d9ef">return&lt;/span> (&lt;span style="color:#a6e22e">control&lt;/span>: &lt;span style="color:#66d9ef">AbstractControl&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> { [&lt;span style="color:#a6e22e">key&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span> } &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>) {
      &lt;span style="color:#75715e">// if control is empty return no error
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
    }
&lt;span style="color:#75715e">// test the value of the control against the regexp supplied
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">valid&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">regex&lt;/span>.&lt;span style="color:#a6e22e">test&lt;/span>(&lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>);
&lt;span style="color:#75715e">// if true, return no error (no error), else return error passed in the second parameter
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">valid&lt;/span> &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">error&lt;/span>;
  };
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And we also need a second CustomValidator to check whether our password and confirm password are a match. Add a second customValidator, called &lt;code>passwordMatchValidator&lt;/code> and add the following code.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>You can follow the comments on the code for what individual lines do.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">passwordMatchValidator&lt;/span>(&lt;span style="color:#a6e22e">control&lt;/span>: &lt;span style="color:#66d9ef">AbstractControl&lt;/span>) {
  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">password&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;password&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">value&lt;/span>; &lt;span style="color:#75715e">// get password from our password form control
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">confirmPassword&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;confirmPassword&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">value&lt;/span>; &lt;span style="color:#75715e">// get password from our confirmPassword form control
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#75715e">// compare is the password math
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">password&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#a6e22e">confirmPassword&lt;/span>) {
    &lt;span style="color:#75715e">// if they don&amp;#39;t match, set an error in our confirmPassword form control
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;confirmPassword&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">setErrors&lt;/span>({ &lt;span style="color:#a6e22e">NoPassswordMatch&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> });
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="building-our-signup-form">Building Our Signup Form&lt;/h2>
&lt;p>For this project, we are going to use the default component – &lt;code>AppComponent&lt;/code>.&lt;/p>
&lt;h3 id="component-class">Component Class&lt;/h3>
&lt;p>First, we need to inject the &lt;a href="https://angular.io/api/forms/FormBuilder">FormBuilder&lt;/a> in to our component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">fb&lt;/span>: &lt;span style="color:#66d9ef">FormBuilder&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to add a new property in our component class – &lt;code>frmSignup&lt;/code>, that will hold information about our form:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">frmSignup&lt;/span>: &lt;span style="color:#66d9ef">FormGroup&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to create a method for adding form controls to the &lt;code>frmSignup&lt;/code> property we just created above: We call the method createSignupForm, and it will return a FormGroup class.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">createSignupForm&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">FormGroup&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then inside the createSignupForm() method above, we need to add the controls for our form and the validation rules required.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Follow the comments below for more information about individual lines of code.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">createSignupForm&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">FormGroup&lt;/span> {
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>(
    {
      &lt;span style="color:#75715e">// email is required and must be a valid email email
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">email&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([
         &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>,
         &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])
      ],
      &lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [ &lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([
         &lt;span style="color:#75715e">// 1. Password Field is Required
&lt;/span>&lt;span style="color:#75715e">&lt;/span>         &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>,
         &lt;span style="color:#75715e">// 2. check whether the entered password has a number
&lt;/span>&lt;span style="color:#75715e">&lt;/span>         &lt;span style="color:#a6e22e">CustomValidators&lt;/span>.&lt;span style="color:#a6e22e">patternValidator&lt;/span>(&lt;span style="color:#e6db74">/\d/&lt;/span>, { &lt;span style="color:#a6e22e">hasNumber&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> }),
         &lt;span style="color:#75715e">// 3. check whether the entered password has upper case letter
&lt;/span>&lt;span style="color:#75715e">&lt;/span>         &lt;span style="color:#a6e22e">CustomValidators&lt;/span>.&lt;span style="color:#a6e22e">patternValidator&lt;/span>(&lt;span style="color:#e6db74">/[A-Z]/&lt;/span>, { &lt;span style="color:#a6e22e">hasCapitalCase&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> }),
         &lt;span style="color:#75715e">// 4. check whether the entered password has a lower-case letter
&lt;/span>&lt;span style="color:#75715e">&lt;/span>         &lt;span style="color:#a6e22e">CustomValidators&lt;/span>.&lt;span style="color:#a6e22e">patternValidator&lt;/span>(&lt;span style="color:#e6db74">/[a-z]/&lt;/span>, { &lt;span style="color:#a6e22e">hasSmallCase&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> }),
         &lt;span style="color:#75715e">// 5. check whether the entered password has a special character
&lt;/span>&lt;span style="color:#75715e">&lt;/span>         &lt;span style="color:#a6e22e">CustomValidators&lt;/span>.&lt;span style="color:#a6e22e">patternValidator&lt;/span>(&lt;span style="color:#e6db74">/[ [!@#$%^&amp;amp;*()_+-=[]{};&amp;#39;:&amp;#34;|,.&amp;lt;&amp;gt;/&lt;/span>&lt;span style="color:#f92672">?&lt;/span>]&lt;span style="color:#f92672">/&lt;/span>](&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">mailto&lt;/span>&lt;span style="color:#f92672">:!&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">@#&lt;/span>&lt;span style="color:#a6e22e">$&lt;/span>&lt;span style="color:#f92672">%^&amp;amp;*&lt;/span>()&lt;span style="color:#a6e22e">_&lt;/span>&lt;span style="color:#f92672">+-=&lt;/span>[]{};&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&lt;span style="color:#f92672">|&lt;/span>,.&lt;span style="color:#f92672">&amp;lt;&amp;gt;&lt;/span>&lt;span style="color:#e6db74">/?]/&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>), { &lt;span style="color:#a6e22e">hasSpecialCharacters&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> }),
         &lt;span style="color:#75715e">// 6. Has a minimum length of 8 characters
&lt;/span>&lt;span style="color:#75715e">&lt;/span>         &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">minLength&lt;/span>(&lt;span style="color:#ae81ff">8&lt;/span>)])
      ],
      &lt;span style="color:#a6e22e">confirmPassword&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])]
   },
   {
      &lt;span style="color:#75715e">// check whether our password and confirm password match
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">validator&lt;/span>: &lt;span style="color:#66d9ef">CustomValidators.passwordMatchValidator&lt;/span>
   });
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Are you still with me? Now let’s move to our component template.&lt;/p>
&lt;h3 id="component-template">Component Template:&lt;/h3>
&lt;p>We will create a normal reactive form as you normally would:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">form&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">formGroup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">submit&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">submit&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">form&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we add our individual form controls:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#a6e22e">id&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-control&amp;#34;&lt;/span> /&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we need to show validation errors to users. For instance, to check whether the email provided is valid, we use the following expression:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">frmSignup.controls[&amp;#39;email&amp;#39;].hasError(&amp;#39;email&amp;#39;)
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the same for a required form field:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">frmSignup.controls[&amp;#39;email&amp;#39;].hasError(&amp;#39;required&amp;#39;)
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And to display a message, we can simply use &lt;code>*ngIf&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-danger&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;frmSignup.controls[&amp;#39;email&amp;#39;].hasError(&amp;#39;email&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
Enter a valid email address!
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> This will display the &lt;code>Enter a valid Email Address!&lt;/code> error only when there is such an error. You can do the same for required, and custom validation errors.&lt;/p>
&lt;/blockquote>
&lt;p>The same goes for confirming whether confirm password and password are a match:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-danger&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;frmSignup.controls[&amp;#39;confirmPassword&amp;#39;].hasError(&amp;#39;NoPassswordMatch&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
Password do not match
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can also add a red border around our form field to give the error some prominence. We are going to add &lt;code>is-invalid&lt;/code> bootstrap class using ngClass, adding the class when the form control has an error and remove it when there is no error:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">[ngClass]=&amp;#34;frmSignup.controls[&amp;#39;email&amp;#39;].invalid ? &amp;#39;is-invalid&amp;#39; : &amp;#39;&amp;#39;&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>So, now our form field looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">input&lt;/span>
&lt;span style="color:#a6e22e">id&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;form-control&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">email&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">invalid&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">is-invalid&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span> &lt;span style="color:#a6e22e">:&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&amp;#39;&amp;#34;&lt;/span>
/&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="password-rules-validation">Password Rules Validation&lt;/h4>
&lt;p>There is not much difference from the above code when it customs to custom validation rules.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-danger&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;hasNumber&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
Must have at least 1 number!
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>But, since we don’t want to just hide and show the errors as with other form fields, we want to show text with green font for rules the password has fulfilled, and a red font color for rules not fulfilled. So, instead of &lt;code>*ngIf&lt;/code>, we will use a ngClass, to switch between bootstrap classes  &lt;code>text-success&lt;/code> and &lt;code>text-danger&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">[ngClass]=&amp;#34;frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;required&amp;#39;) ||
frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;hasNumber&amp;#39;)  ? &amp;#39;text-danger&amp;#39; :
&amp;#39;text-success&amp;#39;&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We also need to do the same for icons, showing a check icon when a rule has been fulfilled and cancel icon otherwise.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;material-icons&amp;#34;&lt;/span>&amp;gt;
{{ frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;required&amp;#39;) ||
frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;hasNumber&amp;#39;) ? &amp;#39;cancel&amp;#39; :
&amp;#39;check_circle&amp;#39; }}
&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>So, our complete code will look like this for checking whether password has a number:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">required&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">||&lt;/span> &lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">hasNumber&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span>  &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-danger&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span> &lt;span style="color:#a6e22e">:&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-success&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;material-icons&amp;#34;&lt;/span>&amp;gt;
{{
frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;hasNumber&amp;#39;)
? &amp;#39;cancel&amp;#39; : &amp;#39;check_circle&amp;#39; }}
&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt;
Must contain atleast 1 number!
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the same goes for our other password rules:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">required&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">||&lt;/span> &lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">minlength&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span>  &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-danger&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span> &lt;span style="color:#a6e22e">:&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-success&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;material-icons&amp;#34;&lt;/span>&amp;gt;
{{ frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;required&amp;#39;) ||
frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;minlength&amp;#39;) ? &amp;#39;cancel&amp;#39; :
&amp;#39;check_circle&amp;#39; }}
&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt;
Must be at least 8 characters!
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">required&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">||&lt;/span> &lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">hasNumber&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span>  &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-danger&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span> &lt;span style="color:#a6e22e">:&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-success&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;material-icons&amp;#34;&lt;/span>&amp;gt;
{{ frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;required&amp;#39;) ||
frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;hasNumber&amp;#39;) ? &amp;#39;cancel&amp;#39; :
&amp;#39;check_circle&amp;#39; }}
&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt;
Must contain at least 1 number!
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">required&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">||&lt;/span> &lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">hasCapitalCase&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span>  &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-danger&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span> &lt;span style="color:#a6e22e">:&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-success&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;material-icons&amp;#34;&lt;/span>&amp;gt;
{{ frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;required&amp;#39;) ||
frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;hasCapitalCase&amp;#39;) ? &amp;#39;cancel&amp;#39; :
&amp;#39;check_circle&amp;#39; }}
&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt;
Must contain at least 1 in Capital Case!
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">required&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">||&lt;/span> &lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">hasSmallCase&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span>  &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-danger&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span> &lt;span style="color:#a6e22e">:&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-success&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;material-icons&amp;#34;&lt;/span>&amp;gt;
{{ frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;required&amp;#39;) ||
frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;hasSmallCase&amp;#39;) ? &amp;#39;cancel&amp;#39; :
&amp;#39;check_circle&amp;#39; }}
&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt;
Must contain at least 1 Letter in Small Case!
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">label&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">required&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">||&lt;/span> &lt;span style="color:#a6e22e">frmSignup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">controls&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">[&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;].&lt;/span>&lt;span style="color:#a6e22e">hasError&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">hasSpecialCharacters&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;)&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-danger&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span> &lt;span style="color:#a6e22e">:&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">text-success&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">i&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;material-icons&amp;#34;&lt;/span>&amp;gt;
{{ frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;required&amp;#39;) ||
frmSignup.controls[&amp;#39;password&amp;#39;].hasError(&amp;#39;hasSpecialCharacters&amp;#39;) ? &amp;#39;cancel&amp;#39; :
&amp;#39;check_circle&amp;#39; }}
&amp;lt;/&lt;span style="color:#f92672">i&lt;/span>&amp;gt;
Must contain at least 1 Special Character!
&amp;lt;/&lt;span style="color:#f92672">label&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="demo-and-source-code">Demo and Source Code&lt;/h2>
&lt;p>You can find a demo to play with &lt;a href="https://mainawycliffe.github.io/ng-bootstrap-password-validation-example/">here&lt;/a> and the complete source code for the above project &lt;a href="https://github.com/MainaWycliffe/ng-bootstrap-password-validation-example">here&lt;/a>.&lt;/p></description></item><item><title>Angular 7 Spotlight – News and Updates</title><link>https://codinglatte.com/posts/angular/angular-7-news-updates/</link><pubDate>Mon, 17 Sep 2018 10:31:16 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-7-news-updates/</guid><description>&lt;p>We are about a month or less for the official release of Angular 7. Today, we are going to take a closer look at what to expect in Angular 7, Angular Material and how you can try out the new version of Angular. So, without further ado.&lt;/p>
&lt;h1 id="angular-7-and-angular-cli">Angular 7 and Angular CLI&lt;/h1>
&lt;p>First, let’s focus on features coming to both Angular 7 and Angular 7 CLI.&lt;/p>
&lt;h2 id="updated-compiler-angular-compatibility-compiler">Updated Compiler – Angular Compatibility Compiler&lt;/h2>
&lt;p>We are getting an updated compiler for angular 7. This is great news because it means that you can expect to reduce your bundle size by allowing old packages to use Ivy Rendering Engine. This is a huge performance gain for most application, since smaller bundles, means less size to download and faster load times. Over the next few days, I will be experimenting on some of my projects and I will get back to you with the results. Keep in mind we are still in beta.&lt;/p>
&lt;h2 id="improvement-to-angular-schematics">Improvement to Angular Schematics&lt;/h2>
&lt;p>As of Angular 7, Schematics will allow for interactive install of dependencies and also when creating new angular projects. For instance, when you run ng new project-name, Angular CLI will prompt you whether to add routing and which stylesheet to use. This is particularly helpful, as I forget to add those flags most of the time, and it means one less thing to worry about.&lt;/p>
&lt;h2 id="router-improvement">Router Improvement&lt;/h2>
&lt;p>In the next version of Angular, the CanLoad Interface will now have &lt;code>UrlSegment[]&lt;/code> which will store URLs a user tried to navigate to and can be redirected to them later. This is especially important when you want to redirect user back after they have been authenticated. For more details, please checkout the changelog &lt;a href="https://github.com/angular/angular/blob/master/CHANGELOG.md">here&lt;/a>.&lt;/p>
&lt;h1 id="angular-material-and-cdk">Angular Material and CDK&lt;/h1>
&lt;p>Moving on, lets focus on Angular Material – one of my favorite &lt;a href="//tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI tools&lt;/a> for Angular. On top of lots of bug fixes and minor improvements, here are the major changes to expect:&lt;/p>
&lt;h2 id="virtual-scroll">Virtual Scroll&lt;/h2>
&lt;p>Virtual Scroll enables you to display a large list of items (hundreds or thousands) by only rendering the number of items on view point. There are other &lt;a href="//tech/developers/angular/ngfor-working-large-lists-angular/">third-party solutions out there&lt;/a> but it’s great to see it being officially supported by the Angular Team. This is part of Angular Component Development Kit (Angular CDK) which means you can use it with any UI framework you wish to. You can learn more about this feature &lt;a href="https://beta-angular-material-io.firebaseapp.com/cdk/scrolling/overview">here&lt;/a>.&lt;/p>
&lt;h2 id="drag-and-drop">Drag and Drop&lt;/h2>
&lt;p>This is another exciting feature for Angular CDK. This module allows you to create a drag drop UI which can be used for free dragging, sorting and transferring items through a list etc. It provides a complete API for you to interact with the object being dragged with touch and mouse event detectors and locking along an axis – vertical or horizontal only dragging. You should really see it in action &lt;a href="https://beta-angular-material-io.firebaseapp.com/cdk/drag-drop/examples">here&lt;/a>.&lt;/p>
&lt;h2 id="support-for-native-select-in-matformfieldmodule">Support for Native Select in MatFormFieldModule&lt;/h2>
&lt;p>While not as exciting as the above two, this is a very important development. If you wanted to add a select form field in angular material, you were required to use &lt;a href="https://material.angular.io/components/select/overview">&lt;code>MatSelectModule&lt;/code>&lt;/a>, but as of Angular 7, Material will now support the native html select input.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">select&lt;/span>
&lt;span style="color:#a6e22e">matNativeControl&lt;/span>
&lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Favorite car&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[(&lt;/span>&lt;span style="color:#a6e22e">ngModel&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">selectedCar&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;car&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">option&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">disabled&lt;/span> &lt;span style="color:#a6e22e">selected&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">option&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">option&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let car of cars&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">car&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;
{{car.viewValue}}
&amp;lt;/&lt;span style="color:#f92672">option&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">select&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For more information, visit the beta documentation &lt;a href="https://beta-angular-material-io.firebaseapp.com/components/select/overview">here&lt;/a>. And finally, Angular 2 Material is being updated to the &lt;a href="https://material.io/">2018 Material Design Guidelines&lt;/a>. It is still in progress, so you might come across some visual inconsistencies, hopefully it will be done by the time its released.&lt;/p>
&lt;h2 id="trying-and-testing-angular-7">Trying and Testing Angular 7&lt;/h2>
&lt;p>There two ways you can get into the action with Angular 7. One is a global install of Angular 7 CLI and then all projects you create will be in Angular 7. This won’t affect existing projects. I would strongly advice against this. To upgrade, you one of the following commands depending on the package manager you are using:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ yarn global upgrade @angular/cli@7.0.0-beta.3
$ npm install -g @angular/cli@7.0.0-beta.3
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And any new projects will from now onwards be created with Angular 7. The second option is to manually upgrade a single project. First, upgrade the local version of Angular CLI:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ yarn upgrade @angular/cli@7.0.0-beta.3
$ npm update @angular/cli@7.0.0-beta.3
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then update the individual packages using &lt;code>ng update command&lt;/code>: For instance, upgrading Angular Core:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng update @angular/core@7.0.0-beta.5
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>You have to pass the exact version you want, otherwise it will install the latest stable version of Angular. The same goes for angular material.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng update @angular/material@7.0.0-beta.0
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The last option is to dedicate a directory, where angular 7 projects will be placed. Since, a local version of Angular CLI supersedes the global one. Then all angular projects will be created using Angular 7. First, create a new project directory and then install angular cli:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ yarn add @angular/cli@7.0.0-beta.3
$ npm install @angular/cli@7.0.0-beta.3
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Remember to report any bugs you come across on github issue tracker. This will help improve Angular, Angular CLI and Angular 2 Material.&lt;/p></description></item><item><title>Logging HTTP Response Times in Angular</title><link>https://codinglatte.com/posts/angular/logging-http-response-times-angular/</link><pubDate>Sat, 15 Sep 2018 12:11:57 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/logging-http-response-times-angular/</guid><description>&lt;p>Most API and Backend Services have a metric service to measure to measure request response times. The one downside of this is, it doesn’t consider network latency, or how the device capability is affecting the performance of your web app. This is important, since a lot of the people access your web apps using low end mobile devices.&lt;/p>
&lt;p>Collecting such telemetry data is vital, as it can help you fine tune the performance of your web app. In this post, we will look at how you can measure the time it takes to send and receive HTTP responses, from the frontend. Once you have access to the data, you can then send it to a logging server.&lt;/p>
&lt;p>To make this information useful for analyses in future, we will also be collecting browser, operating system and any device information we can get. Remember to update your apps terms of use and privacy policy accordingly.&lt;/p>
&lt;h3 id="how-it-works">How it Works&lt;/h3>
&lt;p>We are going to be using a &lt;a href="https://codinglatte.com/tech/developers/angular/logging-http-errors-in-angular-6/">HTTP Interceptor&lt;/a> to intercept both outgoing requests and incoming responses. Then, we will be adding a timestamp for outgoing requests and then read it on responses. And then, we are going to find a difference between the current timestamp and the one for outgoing request.&lt;/p>
&lt;p>We will then take that information, together with device information and send it to a logging server. To collect device data, we are going to be using &lt;a href="https://www.npmjs.com/package/ngx-device-detector">ngx-device-detector&lt;/a> library. This will give us information such as OS, Browser, User Agent etc. So, without further ado.&lt;/p>
&lt;h3 id="initial-app-setup">Initial App Setup&lt;/h3>
&lt;p>First, we need to create a new angular application:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng new ng-measure-http-response-times
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we will install our app dependency, using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$  yarn add ngx-device-detector
$ npm install ngx-device-detector
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, import both &lt;code>DeviceDetectorModule&lt;/code> and &lt;code>HttpClientModule&lt;/code> in your application module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">...
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">HttpClientModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/common/http&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">DeviceDetectorModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;ngx-device-detector&amp;#39;&lt;/span>;
...
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  ...
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    ...
    &lt;span style="color:#a6e22e">HttpClientModule&lt;/span>,
    &lt;span style="color:#a6e22e">DeviceDetectorModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>()
    ...
  ],
  ...
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="create-a-http-interceptor">Create a HTTP Interceptor&lt;/h3>
&lt;p>Next up, let’s create a HTTP Interceptor. You can do this by generating a class using &lt;a href="https://github.com/angular/angular-cli/wiki/generate-class">angular cli&lt;/a> and then adding support for dependency injection.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng g class http-response-time-logger
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then implement http interceptor interface, add dependency injection support and an intercept method for our class:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">...
&lt;span style="color:#66d9ef">@Injectable&lt;/span>()
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">HttpResponseTimeLogger&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">HttpInterceptor&lt;/span> {
  &lt;span style="color:#a6e22e">intercept&lt;/span>(&lt;span style="color:#a6e22e">req&lt;/span>: &lt;span style="color:#66d9ef">HttpRequest&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>, &lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">HttpHandler&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">HttpEvent&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span> { ... }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to inject &lt;code>DeviceDetectorService&lt;/code> to our class, so we can use it within our intercept method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">deviceService&lt;/span>: &lt;span style="color:#66d9ef">DeviceDetectorService&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then register our interceptor class in the app module, list of providers:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  ...
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    ...
    {
      &lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">HTTP_INTERCEPTORS&lt;/span>,
      &lt;span style="color:#a6e22e">useClass&lt;/span>: &lt;span style="color:#66d9ef">HttpResponseTimeLogger&lt;/span>,
      &lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
    }
  ],
  ...
})
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="adding-a-timestamp-header">Adding A Timestamp Header&lt;/h4>
&lt;p>Now, we need to get the current timestamp header when the request is being sent. Our timestamp will be in millisecond for some level of accuracy.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">startTimestamp&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">getTime&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we need to clone our request and add the timestamp header:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">newReq&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({
&lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;startTimestamp&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">startTimestamp&lt;/span>.&lt;span style="color:#a6e22e">toString&lt;/span>())
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The idea here is, you will get the header from the request on the server and return it with the response. You can use a middleware to automatically retrieve the header and attach it to the response. Next, return the newly cloned request and &lt;a href="https://www.learnrxjs.io/operators/utility/do.html">tap&lt;/a> to the response.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">newReq&lt;/span>).&lt;span style="color:#a6e22e">pipe&lt;/span>(
  &lt;span style="color:#a6e22e">tap&lt;/span>((&lt;span style="color:#a6e22e">res&lt;/span>: &lt;span style="color:#66d9ef">Response&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> { });
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="calculating-and-logging-http-response-time">Calculating and Logging HTTP Response Time&lt;/h4>
&lt;p>Then, inside our &lt;a href="https://www.learnrxjs.io/operators/utility/do.html">tap method&lt;/a>, we need to read the timestamp from the response header and get the current timestamp in millisecond, then finally get the difference.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// another timestamp
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">endTimestamp&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">getTime&lt;/span>();
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">startTimestamp2&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span> &lt;span style="color:#f92672">=&lt;/span> Number(&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;startTimestamp&amp;#39;&lt;/span>));
&lt;span style="color:#75715e">// get the difference
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">responseTimes&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">endTimestamp&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">startTimestamp2&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>You don’t have to get the difference inside your http interceptor. You can also log the start and end timestamps and let the server handle the calculation for you.&lt;/em>&lt;/p>
&lt;p>Next up, we need to get the device information using the &lt;code>DeviceDetectorService&lt;/code> method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">deviceInfo&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">deviceService&lt;/span>.&lt;span style="color:#a6e22e">getDeviceInfo&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we have everything we need to log the data. One option would be to send the data over to the logging server directly.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>
.&lt;span style="color:#a6e22e">post&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;URL HERE&amp;#39;&lt;/span>, {
&lt;span style="color:#a6e22e">startTime&lt;/span>: &lt;span style="color:#66d9ef">startTimestamp2&lt;/span>,
&lt;span style="color:#a6e22e">endTime&lt;/span>: &lt;span style="color:#66d9ef">endTimestamp&lt;/span>,
&lt;span style="color:#a6e22e">difference&lt;/span>: &lt;span style="color:#66d9ef">difference&lt;/span>,
&lt;span style="color:#a6e22e">deviceInfo&lt;/span>: &lt;span style="color:#66d9ef">JSON.stringify&lt;/span>(&lt;span style="color:#a6e22e">deviceInfo&lt;/span>) &lt;span style="color:#75715e">// decode the data on the server
&lt;/span>&lt;span style="color:#75715e">&lt;/span> })
.&lt;span style="color:#a6e22e">subscribe&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>You can also store the logs locally and collect them periodically on the background&lt;/em>.&lt;/p>
&lt;h3 id="logging-a-portion-of-all-requests">Logging a Portion of all Requests&lt;/h3>
&lt;p>You can also decide instead of logging all requests, to log some of the requests. One way you can achieve this, is by generating a random number between 1 and 6. And then check if the number is greater than 3. If the number is greater than 3, don’t log the request, otherwise log the request. At the beginning of the intercept method, we need to add the following code:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">random&lt;/span> &lt;span style="color:#f92672">=&lt;/span> Math.&lt;span style="color:#a6e22e">floor&lt;/span>(Math.&lt;span style="color:#a6e22e">random&lt;/span>() &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span>) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;span style="color:#75715e">// if number is less than 3 skip logging
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">random&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">req&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If everything works perfectly, you will be logging three in every six requests, about 50 % of the requests at random. So, our final class should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Injectable&lt;/span>()
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">HttpResponseTimeLogger&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">HttpInterceptor&lt;/span> {
&lt;span style="color:#66d9ef">constructor&lt;/span>(
&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">deviceService&lt;/span>: &lt;span style="color:#66d9ef">DeviceDetectorService&lt;/span>,
&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">http&lt;/span>: &lt;span style="color:#66d9ef">HttpClient&lt;/span>
) {}
&lt;span style="color:#a6e22e">intercept&lt;/span>(
&lt;span style="color:#a6e22e">req&lt;/span>: &lt;span style="color:#66d9ef">HttpRequest&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">HttpHandler&lt;/span>
)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">HttpEvent&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">random&lt;/span> &lt;span style="color:#f92672">=&lt;/span> Math.&lt;span style="color:#a6e22e">floor&lt;/span>(Math.&lt;span style="color:#a6e22e">random&lt;/span>() &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span>) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;span style="color:#75715e">// if number is less 3 skip logging
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">random&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">req&lt;/span>);
}
&lt;span style="color:#75715e">// get timestamp
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">startTimestamp&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">getTime&lt;/span>();
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">newReq&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({
&lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;startTimestamp&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">startTimestamp&lt;/span>.&lt;span style="color:#a6e22e">toString&lt;/span>())
});
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">newReq&lt;/span>).&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">tap&lt;/span>((&lt;span style="color:#a6e22e">res&lt;/span>: &lt;span style="color:#66d9ef">Response&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// another timestamp
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">endTimestamp&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Date().&lt;span style="color:#a6e22e">getTime&lt;/span>();
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">startTimestamp2&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span> &lt;span style="color:#f92672">=&lt;/span> Number(
&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;startTimestamp&amp;#39;&lt;/span>)
);
&lt;span style="color:#75715e">// get the difference
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">responseTimes&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">endTimestamp&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">startTimestamp2&lt;/span>;
&lt;span style="color:#75715e">// get browser information
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">deviceInfo&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">deviceService&lt;/span>.&lt;span style="color:#a6e22e">getDeviceInfo&lt;/span>();
&lt;span style="color:#75715e">// send the data to the server
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>
.&lt;span style="color:#a6e22e">post&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;URL HERE&amp;#39;&lt;/span>, {
&lt;span style="color:#a6e22e">startTime&lt;/span>: &lt;span style="color:#66d9ef">startTimestamp2&lt;/span>,
&lt;span style="color:#a6e22e">endTime&lt;/span>: &lt;span style="color:#66d9ef">endTimestamp&lt;/span>,
&lt;span style="color:#a6e22e">deviceInfo&lt;/span>: &lt;span style="color:#66d9ef">JSON.stringify&lt;/span>(&lt;span style="color:#a6e22e">deviceInfo&lt;/span>)
})
.&lt;span style="color:#a6e22e">subscribe&lt;/span>();
})
);
}
}
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>ngFor – Working with Large Lists in Angular</title><link>https://codinglatte.com/posts/angular/ngfor-working-large-lists-angular/</link><pubDate>Fri, 14 Sep 2018 12:02:03 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/ngfor-working-large-lists-angular/</guid><description>&lt;p>ngFor is directive that iterates through a list of data and instantiates a template for each item in the list. It does an amazing job when dealing with small list. The issue with ngFor is that it loads everything on DOM, which is slow – possibly iterating over hundreds of items and rendering them.&lt;/p>
&lt;p>This can impact the performance negatively by hogging memory and processing power. On top of that, any change to a single item on the list, the whole list is re-rendered. There are workaround for this, one option is to  paginate results. In this case, you display a portion of the data to the user and let the user move through the data in sets, like a book. This is great for performance but not great for the user experience since the user must always click on the next button to navigate through the data.&lt;/p>
&lt;p>So, where am I going with this? In this post, I am going to look at two solutions for working with large lists in Angular without sacrificing the user experience or performance. So, without further ado.&lt;/p>
&lt;h3 id="using-angular2-virtual-scroll">Using angular2-virtual-scroll&lt;/h3>
&lt;p>Let’s take this scenario, you have 1000 items to display. If you used ngFor, all of them would be rendered, but with this library, it will only display the section of the list which is on the view point. This could be about 5 items out of a possible 1000 Items.&lt;/p>
&lt;p>As you scroll down, the library will remove items not in view and add new items, maintaining a constant number of items on display. This greatly improves performance, because only a small number of items are rendered in the dom. It also provides an event trigger to dynamically load more content – for instance, from a Rest API endpoint.&lt;/p>
&lt;p>Combine this with a &lt;a href="https://codinglatte.com/tech/developers/angular/service-worker-angular-performance/">Service Worker&lt;/a>, and you will see incredible performance improvement in your angular app. You can watch a demo for this library in action &lt;a href="http://rintoj.github.io/angular2-virtual-scroll">here&lt;/a>. To get started using this library, install it using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ yarn add angular2-virtual-scroll
$ npm install angular2-virtual-scroll --save
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, import the package into your app module (for &lt;a href="https://codinglatte.com/tech/developers/angular/optimizing-your-angular-app-using-lazy-loading/">lazy loaded modules&lt;/a>, import it under a shared module or in the lazy loaded module you are going to use it).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">VirtualScrollModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angular2-virtual-scroll&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, add it to your imports array:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">...
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
  ...
  &lt;span style="color:#a6e22e">VirtualScrollModule&lt;/span>
],
...
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, you can use it in your app, as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">virtual-scroll&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">items&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">items&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">vsUpdate&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">viewPortItems &lt;/span>&lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">$event&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">my-custom-component&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let item of viewPortItems&amp;#34;&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">my-custom-component&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">virtual-scroll&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>As you can see from the above demo, the library determines the items in view point and creates a list of those items which you can iterate through using ngFor.&lt;/em>&lt;/p>
&lt;p>You can visit the documentation of the library &lt;a href="https://github.com/rintoj/angular2-virtual-scroll#readme">here&lt;/a>. And you can also find some samples &lt;a href="http://rintoj.github.io/angular2-virtual-scroll/samples">here&lt;/a>.&lt;/p>
&lt;h3 id="using-ngvfor-libraries">Using ngVFor Libraries&lt;/h3>
&lt;p>This is a relatively new library – about a month old as of the time of writing. The authors of this library intended it to be used as a direct replacement of ngFor. Hence calling it Virtualization for ngFor (ngVFor). What caught my eye was the incredible performance gain being promised. I mean 90 times faster than ngFor cannot be ignored. It works exactly like ngFor, and you can replace globally all your ngFor directives with ngVFor directive and you will still see some performance gain.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;data-list-items-container&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">***&lt;/span>&lt;span style="color:#a6e22e">ngVFor&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">**=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">let&lt;/span> &lt;span style="color:#a6e22e">row&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span> &lt;span style="color:#a6e22e">testData&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>But to fully realize the promised performance gain though, you must wrap your ngVFor around a virtualization container.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">**&amp;lt;&lt;span style="color:#f92672">nggud-items-control&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">nggud-items-control&lt;/span>&amp;gt;**
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Just like the Angular Virtual Scroll library above, this will measure the view point and pass that information to the &lt;code>*ngVFor&lt;/code> directive to only display items on view point, this allows for faster rendering and faster scroll through your content. For more information about the performance benefits and technical details, visit &lt;a href="https://medium.com/@andrew_54539/virtualization-of-ngfor-welcome-to-the-pure-ngfor-replacement-ngvfor-21254034acbc">this blog&lt;/a> &lt;a href="https://medium.com/@andrew_54539/virtualization-of-ngfor-welcome-to-the-pure-ngfor-replacement-ngvfor-21254034acbc">post&lt;/a> on medium.&lt;/p>
&lt;p>To get started using this library, install it using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ yarn add ngvforlib
$ npm install ngvforlib
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, import it to your app module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgGUDCoreModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;ng-vfor-lib&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then add it to the list of your imports:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">...
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [ 
...,
&lt;span style="color:#a6e22e">NgGUDCoreModule&lt;/span>
],
...
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, you can use inside your components:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">nggud-items-control&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;data-list-items-container&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngVFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let row of testData&amp;#34;&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- ... --&amp;gt;&lt;/span>
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">nggud-items-control&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you want to understand how it works, please visit this blog post
&lt;a href="https://medium.com/@andrew_54539/virtualizing-ngfor-part-2-how-ngvfor-works-8972e4c4cca4">here&lt;/a>.&lt;/p>
&lt;h3 id="conclusion-these-two-libraries--one-new-and-the-other-old-are-great-for">Conclusion These two libraries – one new and the other old are great for&lt;/h3>
&lt;p>handling large lists in angular. I am quite sure, they are not the only once out there. If you have any library that I should add to this list, you can post it on the comment section below and I will have a closer look at it. For tables, I suggest using something like &lt;a href="https://codinglatte.com/tech/developers/angular/angular-cdktable-part-1/">Angular CdkTables&lt;/a> or something similar which provides features for displaying data inside tables.&lt;/p></description></item><item><title>Service Worker – Optimizing the Performance of an Angular App</title><link>https://codinglatte.com/posts/angular/service-worker-angular-performance/</link><pubDate>Wed, 12 Sep 2018 11:44:42 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/service-worker-angular-performance/</guid><description>&lt;p>Basically, a service worker intercepts all outgoing http requests sent by your application on the browser. You can choose which request to respond to by using a set of rules (policies) to guide the service worker on how to handle different requests.&lt;/p>
&lt;p>This gives your app some level of offline capabilities and can hugely impact the performance of your app by serving content even faster, on repeat calls and visits. On top of that, it will take some load off your servers, which can reduce your expenses.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> At its simplest, a service worker is a script that runs in the web browser and manages caching for an application.&lt;/p>
&lt;/blockquote>
&lt;h3 id="introduction">Introduction&lt;/h3>
&lt;p>In this post, I will take a closer look at how to optimize the performance of angular app using a Service Worker. We will be using an old tutorial we worked on sometime back for creating an Angular Material AutoComplete with HTTP lookup. It queries the Github API with the keyword you are typing and return a list of possible repos for you to choose one. The more you type, the more relevant the queries become.&lt;/p>
&lt;p>You can learn more about that &lt;a href="https://codinglatte.com/tech/developers/angular/ng-material-autocomplete-http-lookup/">here&lt;/a>. So, in this post, we will be adding and configuring a service worker to the demo we created. We are going to aggressively cache the queries to the Github API using a service worker for 30mins. In case of repeated requests, the service worker will serve the same results from a local cache. Without further ado:&lt;/p>
&lt;h3 id="adding-support-for-a-service-worker">Adding Support for a Service Worker&lt;/h3>
&lt;p>Adding a Service Worker is rather s straight forward process in Angular 6. This is due to angular &lt;a href="https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2">schematics support&lt;/a>, which was introduced in Angular 6. We can achieve this by using the command below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng add @angular/pwa
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above command, makes modification to your app, adding some files and boilerplate code for both &lt;a href="https://codinglatte.com/tech/developers/angular/introduction-to-progressive-web-apps/">Progressive Web Apps (PWAs)&lt;/a> and Service Worker.&lt;/p>
&lt;p>Let’s take a close look at Service Worker specific modifications: In the main app module, the following code was added:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">ServiceWorkerModule&lt;/span>.&lt;span style="color:#a6e22e">register&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;ngsw-worker.js&amp;#39;&lt;/span>, {
&lt;span style="color:#a6e22e">enabled&lt;/span>: &lt;span style="color:#66d9ef">environment.production&lt;/span>
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This enables a service worker for your application during production. Please note, due to security issues, a service worker is only enabled when your site is loaded on HTTPs or on Localhost. And another file was also created at the root of the workspace – &lt;code>ngsw-config.json&lt;/code>.&lt;/p>
&lt;p>By default, it contains rules to cache static assets of a our PWA. They are all contained in a json property called &lt;code>assetsGroup&lt;/code>, which are resources that are part of the app versions and are all updated together. Resources such as JS, CSS, Images and any links from CDNs and other static resources should be added here.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;index&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/index.html&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;assetGroups&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;app&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;installMode&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;prefetch&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;resources&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;files&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;/favicon.ico&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/index.html&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/*.css&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/*.js&amp;#34;&lt;/span>]
}
},
{
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;installMode&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;lazy&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;updateMode&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;prefetch&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;resources&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;files&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;/assets/**&amp;#34;&lt;/span>]
}
}
]
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="configuring-service-worker-for-api-calls">Configuring Service Worker for API Calls&lt;/h3>
&lt;p>By default, http requests are not cached by the service worker. You must add rules to specifically cache various HTTP requests. This are grouped together in a Data Group property.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>Data Groups is an array of Data Group items, which can be presented in the form of the following Typescript Interface&lt;/em>:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span> &lt;span style="color:#a6e22e">DataGroup&lt;/span> {
&lt;span style="color:#a6e22e">name&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">urls&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>[];
&lt;span style="color:#a6e22e">version?&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span>;
&lt;span style="color:#a6e22e">cacheConfig&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">maxSize&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span>;
&lt;span style="color:#a6e22e">maxAge&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">timeout?&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">strategy&lt;/span>&lt;span style="color:#f92672">?:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;freshness&amp;#39;&lt;/span> &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#e6db74">&amp;#39;performance&amp;#39;&lt;/span>;
};
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Taking a close look at the above interface, it has the following properties:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>Name&lt;/code> – The name of the policy. Can be anything.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>URLS&lt;/code> – An array of URLs strings to cache. Could follow a pattern.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note:&lt;/strong> Negative glob patterns are not supported.&lt;/p>
&lt;/blockquote>
&lt;/li>
&lt;li>
&lt;p>&lt;code>Version&lt;/code> (Optional) – Indicates that a new version of the API is backward compatible and old versions may be discarded.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>CacheConfig&lt;/code>: This has 4 properties:&lt;/p>
&lt;ul>
&lt;li>&lt;code>MaxSize&lt;/code> – &lt;em>The maximum number of items to be cached&lt;/em>.&lt;/li>
&lt;li>&lt;code>MaxAge&lt;/code> &lt;em>– How long something stays in the cache. Measured in minutes (m), hours (h), days (d), milliseconds (u) and seconds (s)&lt;/em>.&lt;/li>
&lt;li>&lt;code>Timeout&lt;/code> – Indicates how long the service worker will wait for a response before falling back to a service worker cache.&lt;/li>
&lt;li>&lt;code>Strategy&lt;/code> – Two strategy can be applied here:
&lt;ul>
&lt;li>&lt;code>Freshness&lt;/code> – always looks for fresh content from the backend, fallbacks to cache in case of timeout – relies on timeout setting above.&lt;/li>
&lt;li>&lt;code>Perfomance&lt;/code> – always use a local cache whenever available and has not expired – relies on maxAge setting above.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="configuring-our-demo-app-service-worker">Configuring our Demo App Service Worker&lt;/h3>
&lt;p>First, we are going to add a data group to our &lt;code>ngsw-config.json&lt;/code> file.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;assetGroups&amp;#34;&lt;/span>: [
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
],
&lt;span style="color:#f92672">&amp;#34;dataGroups&amp;#34;&lt;/span>: [
&lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
]
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we are going to add a new caching policy or rule for our API Call to Github. We will name the policy &lt;code>Github API Call&lt;/code>. The new policy should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Github API Call&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;urls&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;https://api.github.com/search/repositories&amp;#34;&lt;/span>],
&lt;span style="color:#f92672">&amp;#34;cacheConfig&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;maxAge&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;30m&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;strategy&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;performance&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;maxSize&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;10&amp;#34;&lt;/span>
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the above configuration, we are setting a maximum age of 30 minutes for all request to our URLs. You can reduce that time so that it reflects the frequency of updates on your backend. I am also using the performance strategy, requiring use of local cache if it is not expired. I have set the maximum number of cached requests to 10 requests, after that, old request are discarded.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/09/service-worker-1024x555.png" alt="Service Worker – Optimizing the Performance of an Angular App">&lt;/p>
&lt;h3 id="demo-and-source-code">Demo and Source Code&lt;/h3>
&lt;p>If you want to see the above demo in action, you can find it &lt;a href="https://angular-material-autocomplete-with-http-service-demo.s3.ap-south-1.amazonaws.com/index.html">here&lt;/a>. &lt;em>Be sure to open the dev tools and observe the network traffic as the service worker responds to the requests. Run a few requests first, then take the app offline and repeat the request and see whether it still works.&lt;/em> You can also find the source code of the angular app &lt;a href="https://github.com/MainaWycliffe/angular-material-autocomplete-with-http-service-demo">here&lt;/a>.&lt;/p></description></item><item><title>Angular CdkTable – Working with Tables like A Pro – Part 1</title><link>https://codinglatte.com/posts/angular/angular-cdktable-part-1/</link><pubDate>Mon, 10 Sep 2018 14:16:23 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-cdktable-part-1/</guid><description>&lt;p>Angular Component Development Kit (CDK) is a set of un-opinionated developers’ tools to add common interaction behavior to your angular UI with minimal effort. It mainly offers some of the tools found in Angular 2 Material, but with the freedom to use the &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI&lt;/a> of choice.&lt;/p>
&lt;p>Whether you want to use Bootstrap, Clarity Design System etc. This will be a two-part post. This post will be an introduction to Angular CdkTable, with a working demo. In the second post, we will add additional functionality such as sorting, searching, which adds some flair to your tables. We will use Angular CdkTable to handle the table controller and Bootstrap for the UI using Bootstrap Table Component. This can easily be swapped for a custom CSS solution or any other &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI Framework&lt;/a> you want. Let’s get started&lt;/p>
&lt;h3 id="setting-up-bootstrap">Setting up Bootstrap&lt;/h3>
&lt;p>First, we are going to create a new application and add Angular CDK and Bootstrap.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ ng new angular-cdk-table-demo
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, install Angular CDK, which is part of Angular Material and bootstrap.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">$ yarn add @angular/cdk bootstrap
$ npm install @angular/cdk bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We are only interested with CSS Bootstrap and not jQuery. So, we need to import those SCSS files into our app inside &lt;code>angular.json&lt;/code> under styles.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;projects&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
  &lt;span style="color:#f92672">&amp;#34;your-app-name&amp;#34;&lt;/span>: {
    &lt;span style="color:#f92672">&amp;#34;targets&amp;#34;&lt;/span>: {
       &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
       &lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
          &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
          &lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
            &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
            &lt;span style="color:#f92672">&amp;#34;styles&amp;#34;&lt;/span>: [
              &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
              &lt;span style="color:#e6db74">&amp;#34;./node_modules/bootstrap/scss/bootstrap-grid.scss&amp;#34;&lt;/span>,
              &lt;span style="color:#e6db74">&amp;#34;./node_modules/bootstrap/scss/bootstrap-reboot.scss&amp;#34;&lt;/span>,
              &lt;span style="color:#e6db74">&amp;#34;./node_modules/bootstrap/scss/bootstrap.scss&amp;#34;&lt;/span>
              &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
            ],
            &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
          }
}
}
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, we have partially integrated bootstrap in to our Angular app. If you wish to fully use the power of bootstrap (Including replacing jQuery with Angular native components) follow the tutorial &lt;a href="https://codinglatte.com/tech/developers/using-angular-4-bootstrap-4/">here&lt;/a>.&lt;/p>
&lt;h3 id="using-angular-cdktable-on-our-component-controller">Using Angular CdkTable on Our Component Controller&lt;/h3>
&lt;p>First, let’s import &lt;code>CdkTableModule&lt;/code> and add to our list of imports in our application module (&lt;code>app.module.ts&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">CdkTableModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/cdk/table&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">CdkTableModule&lt;/span> &lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next up, we need data to display in our table. So, I went ahead and created some data that I think makes sense. We add the data as a component property – &lt;code>StudentData&lt;/code>. I also went ahead and created an interface for our data – &lt;code>StudentResults&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">StudentData&lt;/span>: &lt;span style="color:#66d9ef">StudentResults&lt;/span>[] &lt;span style="color:#f92672">=&lt;/span> [
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;John&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;300&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;B&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Charles&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;300&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;B&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Eunice&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;420&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;A&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Kate&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;410&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;A-&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Joe&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;310&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;B-&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Peter&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;200&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;C&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Henry&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;250&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;C+&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Paul&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;450&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;A&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Pius&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;400&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;A-&amp;#39;&lt;/span> },
  { &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Kennedy&amp;#39;&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Grade 6&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">marks&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;150&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">grade&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;D&amp;#39;&lt;/span> }
];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we need to prepare our data, so we can connect it to our Angular CdkTable. First, we need a DataSource property in our component:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">StudentDataSource&lt;/span>: &lt;span style="color:#66d9ef">BehaviorSubject&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">StudentResults&lt;/span>[]&lt;span style="color:#f92672">&amp;gt;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, connect our StudentData to that property.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>() {
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">StudentDataSource&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">BehaviorSubject&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">StudentResults&lt;/span>[]&lt;span style="color:#f92672">&amp;gt;&lt;/span>(
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">StudentData&lt;/span>
  );
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to define the columns that will be visible for our table:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">DisplayedColumns&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>[] &lt;span style="color:#f92672">=&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;no&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;name&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;class&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;marks&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;grade&amp;#39;&lt;/span>];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, let’s head over our template and create the view.&lt;/p>
&lt;h3 id="creating-our-view-with-bootstrap">Creating our View with Bootstrap&lt;/h3>
&lt;p>Let’s add our table, with Bootstrap classes. I am going to have a condensed, stripped and dark themed table. You can learn more about the bootstrap tables &lt;a href="https://getbootstrap.com/docs/4.1/content/tables/">here&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">table&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;table table-condensed table-striped table-dark&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">table&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let&amp;rsquo;s add a &lt;code>cdk-table&lt;/code> directive and connect our our Data Source through &lt;code>dataSource&lt;/code> property.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">table&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;table table-condensed table-striped table-dark&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">cdk-table&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">dataSource&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">StudentDataSource&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&amp;gt;&amp;lt;/&lt;span style="color:#f92672">table&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to define the columns for our table and connect them to the column data. We do this by using &lt;code>ng-container&lt;/code> with &lt;code>cdkColumnDef&lt;/code> with the column name. Inside &lt;code>ng-container&lt;/code>, we need to define the header and body cell of our column.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#a6e22e">cdkColumnDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">th&lt;/span> &lt;span style="color:#a6e22e">cdk-header-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkHeaderCellDef&lt;/span>&amp;gt;Name&amp;lt;/&lt;span style="color:#f92672">th&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">td&lt;/span> &lt;span style="color:#a6e22e">cdk-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkCellDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let element&amp;#34;&lt;/span>&amp;gt;{{element.name}}&amp;lt;/&lt;span style="color:#f92672">td&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We need to repeat the above process, for each column we have in our table:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#a6e22e">cdkColumnDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">th&lt;/span> &lt;span style="color:#a6e22e">cdk-header-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkHeaderCellDef&lt;/span>&amp;gt;Name&amp;lt;/&lt;span style="color:#f92672">th&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">td&lt;/span> &lt;span style="color:#a6e22e">cdk-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkCellDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let element&amp;#34;&lt;/span>&amp;gt;{{element.name}}&amp;lt;/&lt;span style="color:#f92672">td&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#a6e22e">cdkColumnDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;class&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">th&lt;/span> &lt;span style="color:#a6e22e">cdk-header-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkHeaderCellDef&lt;/span>&amp;gt;Class&amp;lt;/&lt;span style="color:#f92672">th&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">td&lt;/span> &lt;span style="color:#a6e22e">cdk-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkCellDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let element&amp;#34;&lt;/span>&amp;gt;{{element.class}}&amp;lt;/&lt;span style="color:#f92672">td&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#a6e22e">cdkColumnDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;marks&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">th&lt;/span> &lt;span style="color:#a6e22e">cdk-header-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkHeaderCellDef&lt;/span>&amp;gt;Marks&amp;lt;/&lt;span style="color:#f92672">th&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">td&lt;/span> &lt;span style="color:#a6e22e">cdk-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkCellDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let element&amp;#34;&lt;/span>&amp;gt;{{element.marks}}&amp;lt;/&lt;span style="color:#f92672">td&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#a6e22e">cdkColumnDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;grade&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">th&lt;/span> &lt;span style="color:#a6e22e">cdk-header-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkHeaderCellDef&lt;/span>&amp;gt;Grade&amp;lt;/&lt;span style="color:#f92672">th&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">td&lt;/span> &lt;span style="color:#a6e22e">cdk-cell&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkCellDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let element&amp;#34;&lt;/span>&amp;gt;{{element.grade}}&amp;lt;/&lt;span style="color:#f92672">td&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The final thing we have to do, is define our rows – header and body rows. For our header row, we are going to add &lt;strong>cdk-header-row&lt;/strong> directive and pass the list of columns to display through the &lt;code>cdkHeaderRowDef&lt;/code> &lt;a href="https://angular.io/guide/structural-directives">directive&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">thead&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">tr&lt;/span> &lt;span style="color:#a6e22e">cdk-header-row&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkHeaderRowDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;DisplayedColumns&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">tr&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">thead&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, in our table body, we are going to add a &lt;code>cdk-row&lt;/code> directive and pass the column row definition data through the &lt;code>cdkRowDef&lt;/code> directive:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">tbody&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">tr&lt;/span> &lt;span style="color:#a6e22e">cdk-row&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">cdkRowDef&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let row; columns: DisplayedColumns;&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">tr&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">tbody&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it. We have successfully used Angular CdkTable with Bootstrap to display data.&lt;/p>
&lt;h3 id="source-code-and-demo">Source Code and Demo&lt;/h3>
&lt;p>You can find the source code for this post &lt;a href="https://github.com/MainaWycliffe/angular-cdk-table-demo">here&lt;/a> and the demo &lt;a href="https://mainawycliffe.github.io/angular-cdk-table-demo/">here&lt;/a>.&lt;/p></description></item><item><title>Working with Angular CLI Budgets in Angular 6</title><link>https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/</link><pubDate>Sat, 08 Sep 2018 10:57:10 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/</guid><description>&lt;p>In this post, I am going to cover Angular CLI Budgets in details. So, what are CLI Budgets? CLI Budgets is a way of way of ensuring that your angular final build bundles do not deviate by much from the expected sizes. For instance, if you expected the whole built application size to be 2MB, with a deviation of +/-10% for warning and +/- 20% for errors. You can set this configuration in Angular, so that during the build process, Angular CLI will throw a warning when it deviates by more than 10%  and an error when it deviates by more than 20%. This is what is known as an Angular CLI Budget.&lt;/p>
&lt;p>As developers, we are sometimes experimenting with our projects, trying new things. This can result to some unused libraries being left inside our application that can bloat the size of the final built artifacts. With Angular CLI Budgets, you can manage this by ensuring that your production build doesn’t deviate by much from your own expectation.&lt;/p>
&lt;p>Please note, Angular CLI Budgets will not determine for you which libraries are causing your project to be over or under budgets. But, it will give you a hint, which you must follow up and investigate. This is where &lt;a href="https://codinglatte.com/tech/developers/angular/tools-angular-developers/">tools&lt;/a> such as &lt;a href="https://github.com/webpack-contrib/webpack-bundle-analyzer">&lt;code>Webpack Bundle Analyzer&lt;/code>&lt;/a> and &lt;a href="https://github.com/danvk/source-map-explorer#readme">&lt;code>Source Map Explorer&lt;/code>&lt;/a> can be useful.&lt;/p>
&lt;h2 id="adding-cli-budgets-to-your-app">Adding CLI Budgets to your App&lt;/h2>
&lt;p>First, open your &lt;code>angular.json&lt;/code>, at the root of your Angular CLI &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">Workspace&lt;/a>. Next, we need to add our budget for our environments.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;projects&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
  &lt;span style="color:#f92672">&amp;#34;angular-cli-budgets-demo&amp;#34;&lt;/span>: {
    &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
    &lt;span style="color:#f92672">&amp;#34;architect&amp;#34;&lt;/span>: {
      &lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
        &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
        &lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: { &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;lt;====&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">your&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">environments&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">are&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">here&lt;/span>
          &lt;span style="color:#f92672">&amp;#34;production&amp;#34;&lt;/span>: { &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;lt;====&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">production&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">environment&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
            &lt;span style="color:#f92672">&amp;#34;budgets&amp;#34;&lt;/span>: []
          },
          &lt;span style="color:#f92672">&amp;#34;staging&amp;#34;&lt;/span>: { &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;lt;=====&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">custom&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">staging&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">environment&lt;/span>
              &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
              &lt;span style="color:#f92672">&amp;#34;budgets&amp;#34;&lt;/span>: []
          }
        }
      },
 &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We will place our budget just below our other environment configurations. Our budget property accepts an array of budgets with the following content:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#e6db74">&amp;#34;budgets&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
  {
     &lt;span style="color:#e6db74">&amp;#34;type&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;bundle&amp;#34;&lt;/span>, &lt;span style="color:#75715e">//_** type of budget to setup**_
&lt;/span>&lt;span style="color:#75715e">&lt;/span>     &lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;main&amp;#34;&lt;/span>, &lt;span style="color:#75715e">//_** the name of the bundle to be tested**_
&lt;/span>&lt;span style="color:#75715e">&lt;/span>     &lt;span style="color:#e6db74">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;300kb&amp;#34;&lt;/span>, &lt;span style="color:#75715e">//_** the baseline size for comparison**_
&lt;/span>&lt;span style="color:#75715e">&lt;/span>     &lt;span style="color:#e6db74">&amp;#34;error&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;40%&amp;#34;&lt;/span>, &lt;span style="color:#75715e">//_** the deviation from the baseline to trigger error (+/- 40%)**_
&lt;/span>&lt;span style="color:#75715e">&lt;/span>     &lt;span style="color:#e6db74">&amp;#34;warning&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;30%&amp;#34;&lt;/span>, &lt;span style="color:#75715e">//**_ the deviation from baseline to trigger warning (+/- 30%)_**
&lt;/span>&lt;span style="color:#75715e">&lt;/span>     &lt;span style="color:#e6db74">&amp;#34;maximumError&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;20%&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span>&lt;span style="color:#f92672">**&lt;/span>&lt;span style="color:#75715e">// triggers error if size is 20% more than baseline**_
&lt;/span>&lt;span style="color:#75715e">&lt;/span>     &lt;span style="color:#e6db74">&amp;#34;maximumWarning&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;10%&amp;#34;&lt;/span>, &lt;span style="color:#75715e">//_** triggers warning if size is 10% more than baseline**_
&lt;/span>&lt;span style="color:#75715e">&lt;/span>     &lt;span style="color:#e6db74">&amp;#34;minimumError&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;20%&amp;#34;&lt;/span>, &lt;span style="color:#75715e">//_** triggers error if size is 20% less than baseline**_
&lt;/span>&lt;span style="color:#75715e">&lt;/span>     &lt;span style="color:#e6db74">&amp;#34;minimumWarning&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;10%&amp;#34;&lt;/span>, &lt;span style="color:#75715e">//**_ triggers warning if size is 10% less than baseline_**
&lt;/span>&lt;span style="color:#75715e">&lt;/span>   }
]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The following types are allowed:&lt;/p>
&lt;ul>
&lt;li>bundle – The size of a specific bundle.&lt;/li>
&lt;li>initial – The initial size of the app.&lt;/li>
&lt;li>allScript – The size of all scripts.&lt;/li>
&lt;li>all – The size of the entire app.&lt;/li>
&lt;li>anyScript – The size of any one script.&lt;/li>
&lt;li>any – The size of any file.&lt;/li>
&lt;/ul>
&lt;h2 id="setting-the-maximum-size-budget">Setting the Maximum Size Budget&lt;/h2>
&lt;p>Next, let’s say you didn’t want your built application to be more than a specific size – like 400KB. Let’s add a budget for that and see how it goes:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;all&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;baseline&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;400kb&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;maximumError&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;25%&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;maximumWarning&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;12%&amp;#34;&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Since our app is small, this doesn’t trigger any errors or warnings as shown below:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/1.png" alt="Working with Angular CLI Budgets in Angular 6" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>Now, let’s lower our baseline to 250KB:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/2.png" alt="Working with Angular CLI Budgets in Angular 6" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>As you can see from the image above, this triggers the following error and warning:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">WARNING in budgets, maximum exceeded for total. Budget 307 kB was exceeded by 70.5 kB.
ERROR in budgets, maximum exceeded for total. Budget 358 kB was exceeded by 19.3 kB.
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And if we increase the baseline value to 300KBs, it should trigger the warning only, as shown below:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/3.png" alt="Working with Angular CLI Budgets in Angular 6" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;h2 id="setting-a-deviation-from-baseline-budget">Setting a Deviation from Baseline Budget&lt;/h2>
&lt;p>Let’s say we want our error to be trigger if the main bundle is 20% large or smaller than the size, and a warning if it’s 10%. Our budget will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;bundle&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;main&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;baseline&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;300kb&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;error&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;20%&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;warning&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;10%&amp;#34;&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Our main bundle is about 250Kb, this should trigger a warning but not an error. This is because the minimum threshold value of 90% of 300Kb (276kb) was not reached but it was reached by the error minimum threshold which is 80% of 300Kb (240kb).&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/4.png" alt="Working with Angular CLI Budgets in Angular 6" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>And if we lower our error threshold to 15%, we will trigger both errors:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/5.png" alt="Working with Angular CLI Budgets in Angular 6" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>I hope now you are getting the picture. If we were to lower the baseline from 300kb to 200kb. We should trigger the maximum threshold error and warning instead of the previous minimum threshold error.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/8-maximum.png" alt="Working with Angular CLI Budgets in Angular 6" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;h2 id="setting-minimum-size-budget">Setting Minimum Size Budget&lt;/h2>
&lt;p>You can also set the minimum size for various output artifacts. An error or warning is triggered if the specified file is less than the minimum size. Let’s modify the above budget and instead set a minimum size instead of a deviation:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;bundle&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;main&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;baseline&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;300kb&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;minimumError&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;20%&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;minimumWarning&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;10%&amp;#34;&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And if we build this, it should trigger only a warning and not an error:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/6.png" alt="Working with Angular CLI Budgets in Angular 6" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>If we lower the minimum error from 20% to 15% we should trigger both an error and a warning:&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/angular-cli-budgets-angular-6/7.png" alt="Working with Angular CLI Budgets in Angular 6" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;h2 id="final-thoughts">Final Thoughts&lt;/h2>
&lt;p>I hope this gives you an idea of how to work with Angular CLI Budgets. I steered cleared from dealing with bytes, KBs and Mbs because I found it to be working rather inconsistently when it comes to errors, minimum errors and warning. That said, I found working with percentages to be enough for my work and I would recommend that to anyone.&lt;/p></description></item><item><title>Must Have Tools for Angular Developers 2018</title><link>https://codinglatte.com/posts/angular/tools-angular-developers/</link><pubDate>Thu, 06 Sep 2018 06:05:32 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/tools-angular-developers/</guid><description>&lt;p>In web development or any job in general, tools are very vital for you to do your job right. Tools help improve productivity, reduce mistakes and provide useful and rich insight towards your code. Angular is build around excellent tools such as Angular CLI. You can improve your &lt;a href="https://codinglatte.com/tech/developers/angular/angular-development-tips/">experience&lt;/a> by adding a few more tools to your tool box. Here are six tools for you to consider:&lt;/p>
&lt;h3 id="angular-console">Angular Console&lt;/h3>
&lt;p>You can think of Angular Console as a Graphical User Interface for Angular CLI. It provides the power of Angular CLI but with a nice user interface to interact with. When you open an &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">angular cli workspace&lt;/a>, Angular console will show you all apps and libraries within the workspace. It provides a nice visual interface to do almost everything Angular CLI can do. In fact, from what I can tell, it provides an abstraction of Angular CLI, running those commands for you in the background. “Whether or not you are brand new to the Angular ecosystem or a seasoned pro, a command-line novice or a power-user, Angular Console will add a lot of value to your workflow.&lt;/p>
&lt;p>&lt;a href="https://vimeo.com/284057890">https://vimeo.com/284057890&lt;/a>&lt;/p>
&lt;p>With a single click of a button, you can accomplish various tasks around your app such as building, serving, generating etc. It even provides a link to your default text editor if you wish to work on your project.&lt;/p>
&lt;p>For more information about Angular Console, visit the official website &lt;a href="https://angularconsole.com/">here&lt;/a>.&lt;/p>
&lt;h3 id="compodoc">Compodoc&lt;/h3>
&lt;p>Would you like to generate a static documentation of your application? That’s exactly what Compodoc does. The idea here is that it generates a clear and rich in information documentation of your angular application, with the goal of helping other developers – like team members – understand the features of your application/library better.&lt;/p>
&lt;p>Other developers can then navigate through your application, with access to how different modules, components, services relate to each other and work.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/09/main-view-1024x754.gif" alt="Compodoc Must Have Tools for Angular Developers 2018">&lt;/p>
&lt;p>It has full support for Angular CLI out of the box – no configuration needed. And it also supports JSDoc Light for providing more information inside your code. Other features include: Documentation Coverage Reports – Reports on how much of your code is documented.&lt;/p>
&lt;p>And it has a clean and easy to use interface which provides excellent user experience. With support for themes, automatic table of contents and search for going through the documentation. To get started with compodoc, install it globally using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ yarn global add @compodoc/compodoc
$ npm install -g @compodoc/compodoc
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then define a script task in your package.json:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;scripts&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
    &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
    &lt;span style="color:#f92672">&amp;#34;compodoc&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;./node_modules/.bin/compodoc -p src/tsconfig.app.json&amp;#34;&lt;/span>
}&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then run it:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm run compodoc
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about compodoc &lt;a href="https://github.com/compodoc/compodoc">here&lt;/a> and it’s usage &lt;a href="https://compodoc.app/guides/usage.html">here&lt;/a>.&lt;/p>
&lt;h3 id="webpack-bundle-analyzer">Webpack Bundle Analyzer&lt;/h3>
&lt;p>If you would like to know what your final build of Angular is made of, then this is the go to tool. It helps you visualize your projects webpack output files with a nice interactive zoomable tree map. With Webpack bundle analyzer, you can simply walk around your final angular build, with access to your code and third-party libraries you have used.&lt;/p>
&lt;p>This is particularly useful if you want to understand why your app is so huge. Or if you basically want more insight into the building blocks of your application. Helping you to discover which third-party libraries made it to the final build. With this information, you can decide to remove and optimize your application ensuring it meets your expectation.&lt;/p>
&lt;p>It enables you to see the sizes of your application before minification, after minification and after &lt;a href="https://checkgzipcompression.com/">gzip compression&lt;/a> by the server.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/09/93f72404-b338-11e6-92d4-9a365550a701.gif" alt="WebPack Bundle Analyzer - Must Have Tools for Angular Developers 2018">&lt;/p>
&lt;p>To get started with this tool, install is a dev dependency in your project using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm i webpack-bundle-analyzer --save-dev
$ yarn add webpack-bundle-analyzer –dev
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, build your application with &lt;code>--stats-json&lt;/code> flag:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng build --prod --stats-json
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, run Webpack Bundle Analyzer against the generated stats.json file located under &lt;code>dist/app-name&lt;/code> for angular 6, and &lt;code>dist&lt;/code> for angular 5 and below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npx webpack-bundle-analyzer dist/&amp;lt;APP-NAME&amp;gt;/stats.json
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>Your app name can be found inside your &lt;code>angular.json&lt;/code> configuration file.&lt;/p>
&lt;/blockquote>
&lt;p>You can learn more about Webpack Bundle Analyzer &lt;a href="https://github.com/webpack-contrib/webpack-bundle-analyzer">here&lt;/a>.&lt;/p>
&lt;h3 id="source-map-explorer">Source-Map-Explorer&lt;/h3>
&lt;p>This is another tool to help you understand your final build better. It analyses your compiled angular app byte by byte and create a tree map visualization of where your code is coming from. If your final build is too large/small you might want to understand what library is contributing to that bloat. For a quick demo of this tool, checkout this video below:&lt;/p>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=7aY9BoMEpG8">https://www.youtube.com/watch?v=7aY9BoMEpG8&lt;/a>&lt;/p>
&lt;p>To use source-map-explorer, first install it globally using your favorite package manager:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npm install -g source-map-explorer
$ yarn global add source-map-explorer
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then build your angular application with &lt;code>--source-map&lt;/code> flag set to true:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng build --source-map&lt;span style="color:#f92672">=&lt;/span>true --prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally run it on one or more of your generated bundles. For instance, main bundle:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ npx source-map-explorer dist/main.xxx.bundle.js
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="tslint">TSLint&lt;/h3>
&lt;blockquote>
&lt;p>&amp;ldquo;TSLint is an extensible static analysis tool that checks TypeScript code for readability, maintainability, and functionality errors.&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;p>This is a set of rules, which you can customize, that help improve the quality of your code. It is great especially for teams, ensuring consistency style of coding from different developers.&lt;/p>
&lt;p>On top of that, it has rules regarding almost every scenario such as variable, class and interface naming, line breaks, where to place the bracket etc. And it is supported by a host of text editors out there, and angular CLI will install it when you use it to setup your angular project. All you have to do is find the appropriate extension/plugin for your favorite text editor.&lt;/p>
&lt;p>For more information about TSLint, visit the official git repo &lt;a href="https://github.com/palantir/tslint">here&lt;/a>.&lt;/p>
&lt;h3 id="augury">Augury&lt;/h3>
&lt;p>This is a Dev Tool Extension for both Chrome and Firefox that helps you visualize your angular application through component trees and debugging tools. It enables you to gain useful insight such as application structure, change detection and performance characteristics of your application.&lt;/p>
&lt;blockquote>
&lt;p>“Augury is the most used Google Chrome Developer Tool extension for debugging and profiling Angular 2+ applications.&lt;/p>
&lt;/blockquote>
&lt;p>This is a useful tool to have since it will provide you with useful insight about how your app is behaving on the browser. For this to work though, either your app must be in developer mode or at least generate source maps, if it’s a live application. You can generate source maps by passing the &lt;code>--source-map=true&lt;/code> flag during build:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">$ ng build --source-map&lt;span style="color:#f92672">=&lt;/span>true --prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can install this extension on chrome &lt;a href="https://chrome.google.com/webstore/detail/augury/elgalmkoelokbchhkhacckoklkejnhcd">here&lt;/a> and Firefox &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/angular-augury">here&lt;/a>. For more information, please visit their github repo &lt;a href="https://github.com/rangle/augury">here&lt;/a> or website &lt;a href="https://augury.angular.io/">here&lt;/a>.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>These are some of the tools that I can confidently recommend to you. There are other honorable mentions such as &lt;a href="https://github.com/mgechev/codelyzer">codelyzer&lt;/a> and &lt;a href="https://github.com/mgechev/ngrev">ngrev&lt;/a> both from the same developers. Feel free to checkout on these two tools.&lt;/p>
&lt;p>And finally, thank you for getting this far, if you liked this post feel free to share, and if you didn’t, tell me why on the comment section below.&lt;/p></description></item><item><title>Angular Hidden Treasures – Features you might know About</title><link>https://codinglatte.com/posts/angular/angular-hidden-features/</link><pubDate>Tue, 04 Sep 2018 13:43:13 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-hidden-features/</guid><description>&lt;p>In this post, we are going to look at four important features in angular that can help you during your app development life cycle. These features are there but are mainly not openly advertised unless you go out looking for them. This is not because they are not useful but can be quite difficult to use for beginners and not entirely needed for small project.&lt;/p>
&lt;h3 id="angular-cli-budgets">Angular CLI Budgets&lt;/h3>
&lt;p>This is a simple but quite useful feature for Angular. Basically, you specify a baseline size you expect for various parts of your angular app. Then, set how much the size of your parts should deviate from the baseline – a threshold – both minimum and maximum. And during compilation, Angular CLI will check the output artefacts against the configuration and warn you when you are over or under the budget you set. This feature ensure that the final output of angular projects meets your expectation – in terms of expected bundle sizes. This saves you from having to breakout the bundle analysis tool on each production build. You only have to analyze the bundle when you are over or under budget to try and understand why.&lt;/p>
&lt;h4 id="usage">Usage&lt;/h4>
&lt;p>The budget configurations are set inside &lt;code>angular.json&lt;/code> under the environment  you wish to enforce your budgets for:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">angular.json&lt;/span>
{
&lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;production&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;budgets&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;bundle&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">check&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">allowed&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">types&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">below&lt;/span>
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;vendor&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;baseline&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;750kb&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">baseline&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">size&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">for&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">comparison.&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(size&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">in&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">b,&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">kbs,&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">mbs.&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**No&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">percentage&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">allowed&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">here**)&lt;/span>
&lt;span style="color:#f92672">&amp;#34;warning&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;100kb&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">threshold&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">for&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">warning&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">relative&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">to&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">baseline.&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**Can&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">also&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">be&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">in&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">percentage**.&lt;/span>
&lt;span style="color:#f92672">&amp;#34;error&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;200kb&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">threshold&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">for&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">error&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">relative&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">to&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">the&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">baseline.&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**Can&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">also&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">be&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">in&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">percentage.**&lt;/span>
}
]
}
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You provide the baseline size of the application and then provide values of how much the size can deviate from the that baseline, from a maximum and minimum value. In our configuration above, you get a warning if it deviates from the baseline by 100kb and an error if it deviates by 200kb.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;strong>Allowed Types are:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>bundle - The size of a specific bundle.&lt;/li>
&lt;li>initial - The initial size of the app.&lt;/li>
&lt;li>allScript - The size of all scripts.&lt;/li>
&lt;li>all - The size of the entire app.&lt;/li>
&lt;li>anyScript - The size of any one script.&lt;/li>
&lt;li>any - The size of any file.&lt;/li>
&lt;/ul>
&lt;h3 id="code-coverage">Code Coverage&lt;/h3>
&lt;p>The second feature is for testing angular apps (angular code base). When running tests in Angular CLI, using ng test, you can enable code coverage reports. They allow you to see which parts of the code base has not been tested properly. To generate a code coverage report, you must pass &lt;code>--code-coverage&lt;/code> flag when running tests:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng test --watch=false --code-coverage
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can also enable it by default in &lt;code>angular.json&lt;/code> to allow code coverage reports to be generated by default:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;test&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
  &lt;span style="color:#f92672">&amp;#34;builder&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;@angular-devkit/build-angular:karma&amp;#34;&lt;/span>,
  &lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
    &lt;span style="color:#f92672">&amp;#34;main&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/test.ts&amp;#34;&lt;/span>,
    &lt;span style="color:#f92672">&amp;#34;polyfills&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/polyfills.ts&amp;#34;&lt;/span>,
    &lt;span style="color:#f92672">&amp;#34;tsConfig&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/tsconfig.spec.json&amp;#34;&lt;/span>,
    &lt;span style="color:#f92672">&amp;#34;karmaConfig&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/karma.conf.js&amp;#34;&lt;/span>,
    &lt;span style="color:#f92672">&amp;#34;styles&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;src/styles.css&amp;#34;&lt;/span>],
    &lt;span style="color:#f92672">&amp;#34;scripts&amp;#34;&lt;/span>: [],
    &lt;span style="color:#f92672">&amp;#34;assets&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;src/favicon.ico&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;src/assets&amp;#34;&lt;/span>],
    &lt;span style="color:#f92672">&amp;#34;codeCoverage&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;lt;==&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Code&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Coverage&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Reports&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Here&lt;/span>
  }
}&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, the neat part is that you can enforce Code Coverage in your Angular Application. For instance, if you wanted 80% of your code to be covered, all you have to do is open &lt;code>karma.conf.js&lt;/code> and add the following content in the &lt;code>coverageIstanbulReporter&lt;/code> property:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">coverageIstanbulReporter&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
  &lt;span style="color:#a6e22e">reports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;html&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;lcovonly&amp;#39;&lt;/span>],
  &lt;span style="color:#a6e22e">fixWebpackSourcePaths&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
  &lt;span style="color:#a6e22e">thresholds&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
    &lt;span style="color:#a6e22e">statements&lt;/span>: &lt;span style="color:#66d9ef">80&lt;/span>,
    &lt;span style="color:#a6e22e">lines&lt;/span>: &lt;span style="color:#66d9ef">80&lt;/span>,
    &lt;span style="color:#a6e22e">branches&lt;/span>: &lt;span style="color:#66d9ef">80&lt;/span>,
    &lt;span style="color:#a6e22e">functions&lt;/span>: &lt;span style="color:#66d9ef">80&lt;/span>
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> The threshold property will enforce a minimum of 80% code coverage for each of the items under threshold when unit tests are run in the project.&lt;/p>
&lt;/blockquote>
&lt;h3 id="generating-an-app-shell">Generating an App Shell&lt;/h3>
&lt;p>The third feature in this list, is for performance optimization. The &lt;code>app shell&lt;/code> or application shell is the minimum CSS, HTML and JavaScript required to power UI for an application. The goal here is to provide as fast as possible a shell of your app (i.e. navigation, footer, header, loading bar etc.) – as the rest of the content is being loaded after initialization. The performance is further improved when cached offline (using service workers) for returning users, giving them near native performance improvement.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> An application shell (or app shell) architecture is one way to build a Progressive Web App that reliably and instantly loads on your users&amp;rsquo; screens, similar to what you see in native applications.&lt;/p>
&lt;/blockquote>
&lt;p>Angular provides a feature to generate a prerendered app shell for your application for a specific route. This allows users to see a very fast paint, as the app is being loaded. Once initialized, the default view can be replaced with intended content. The prerendered page is loaded with the initial http response from the server together with the index.html. Since its route specific, this will result in more page specific resources being loaded initially. Since, this is a long but useful feature, I am going to recommend the following &lt;a href="https://blog.angular-university.io/angular-app-shell/">tutorial&lt;/a> from Angular University. You can also learn more about App Shell &lt;a href="https://developers.google.com/web/fundamentals/architecture/app-shell">here&lt;/a>.&lt;/p>
&lt;h3 id="hot-module-replacement-hmr">Hot Module Replacement (HMR)&lt;/h3>
&lt;p>Our final feature is a webpack feature that can be enabled for angular. This feature allows for modules to be replaced without need for a full browser refresh. This allows you to retain much of the application state, usually lost when reloading. It also saves you valuable times by only updating what has changed. And changes to the code reflect almost instantly, like when you are messing with dev tools on the browser. I previously covered this feature in details &lt;a href="//tech/developers/angular/enabling-hot-module-replacement-angular-6/">here&lt;/a> – You will be able to run how to enable and use this feature in Angular.&lt;/p></description></item><item><title>How to Handle Errors Globally in Angular</title><link>https://codinglatte.com/posts/angular/handle-errors-globally-angular/</link><pubDate>Sun, 02 Sep 2018 13:28:58 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/handle-errors-globally-angular/</guid><description>&lt;p>By default, when errors occur in Angular during runtime, they are written to the browser console. This is great during development and testing but not great when running on production. This is one environment where you have no access to. And the users may lack technical skills to help. No matter how hard you work on your app, errors are almost inevitable.&lt;/p>
&lt;p>It is therefore necessary to be able to handle errors in a friendly manner and collect them for investigation, analysis and correction. In this post, I will show you how to intercept the default error handler, and then send the errors to a remote logging service (Simple REST API call) and show a friendly message to the user.&lt;/p>
&lt;h3 id="why">Why?&lt;/h3>
&lt;p>In a previous &lt;a href="https://codinglatte.com/tech/developers/angular/logging-http-errors-in-angular-6/">post&lt;/a>, I wrote about catching and logging http errors and some readers asked whether it is wise to trust logs from the users. My argument is simple, while that data is not 100% trustworthy, it provides an important diagnostic data which can guide you in discovering new errors in your application.&lt;/p>
&lt;p>It helps you know which parts of your application require attention and investigation. Most of your users will most likely leave your app without leaving feedback if it ever fails. Also, collecting such errors provides technical information (i.e. Stack Trace) which is not possible to get from users. You could also use Machine Learning to dig into the logged data and wind out false reports.&lt;/p>
&lt;h3 id="creating-a-custom-error-handler-class">Creating a Custom Error Handler Class&lt;/h3>
&lt;p>First, we need to create a new class using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate class custom-error-interceptor
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to implement the ErrorHandler &lt;a href="https://angular.io/api/core/ErrorHandler">interface&lt;/a> for our new class.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CustomErrorHandler&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">ErrorHandler&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we need to add an handleError method in our class, which will catch the errors in our app and do something with the errors.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">handleError&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The method accepts an error parameter which is the error content. Now, we need to do something with our error when it gets here. One option would be sending it to a remote logging server such as AWS Cloud Watch and provide a custom error message to the user. To do this, we need to create a logger service and inject it to our custom error handler class.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">loggerService&lt;/span>: &lt;span style="color:#66d9ef">LoggerService&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then inside our handleError method, we can send the error to an API End Point.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">loggerService&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>).&lt;span style="color:#a6e22e">subscribe&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After that we can show a friendly message to the user. For this we will use &lt;a href="https://material.angular.io/components/snack-bar/overview">Angular Material Snackbar&lt;/a>. First, we are going to inject MatSnackBar to our custom error handler class, next to our loggerService we injected previously.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">loggerService&lt;/span>: &lt;span style="color:#66d9ef">LoggerService&lt;/span>,&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">snackBar&lt;/span>: &lt;span style="color:#66d9ef">MatSnackBar&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, we can show our message:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">snackBar&lt;/span>.&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;Your message here&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;Dismiss&amp;#39;&lt;/span>, {
&lt;span style="color:#a6e22e">duration&lt;/span>: &lt;span style="color:#66d9ef">2000&lt;/span>
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>This can be replaced with something like &lt;a href="https://material.angular.io/components/dialog">Angular Material Dialog&lt;/a> or &lt;a href="https://ng-bootstrap.github.io/#/components/modal/examples">Bootstrap Modal Window&lt;/a>. You can also use &lt;a href="https://codinglatte.com/tech/developers/angular/building-adaptive-layouts-using-angular-flex-layout/">Angular Flex Layout to adaptively&lt;/a> show either a snack bar on a small device and a modal window on a large device.&lt;/em>&lt;/p>
&lt;p>Now, our complete class should look like this now:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CustomErrorHandler&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">ErrorHandler&lt;/span> {
&lt;span style="color:#66d9ef">constructor&lt;/span>(
&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">loggerService&lt;/span>: &lt;span style="color:#66d9ef">LoggerService&lt;/span>,
&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">snackBar&lt;/span>: &lt;span style="color:#66d9ef">MatSnackBar&lt;/span>
) {}
&lt;span style="color:#a6e22e">handleError&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) {
&lt;span style="color:#75715e">// send to the observable
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">loggerService&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>).&lt;span style="color:#a6e22e">subscribe&lt;/span>();
&lt;span style="color:#75715e">// next show a friendly message
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">snackBar&lt;/span>.&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;Your message here&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;Dismiss&amp;#39;&lt;/span>, {
&lt;span style="color:#a6e22e">duration&lt;/span>: &lt;span style="color:#66d9ef">2000&lt;/span>
});
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="our-logger-service">Our Logger Service&lt;/h3>
&lt;p>Our logger service will look something like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Injectable&lt;/span>({
&lt;span style="color:#a6e22e">providedIn&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;root&amp;#39;&lt;/span>
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">LoggerService&lt;/span> {
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">http&lt;/span>: &lt;span style="color:#66d9ef">HttpClient&lt;/span>) {}
&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>
.&lt;span style="color:#a6e22e">post&lt;/span>(
&lt;span style="color:#e6db74">&amp;#39;Your URL Here&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">error&lt;/span>, &lt;span style="color:#75715e">// &amp;lt;&amp;lt;&amp;lt;&amp;lt;=============== sending error as body
&lt;/span>&lt;span style="color:#75715e">&lt;/span> {
&lt;span style="color:#a6e22e">observe&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;response&amp;#39;&lt;/span>
}
)
.&lt;span style="color:#a6e22e">pipe&lt;/span>(&lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">e&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>));
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Please note, that am sending the error as the body. This might not work depending on the logging server. You might have to parse the error and compose a message before sending it to the logging server. You can also send it a base64 string and decode it on the server before storing it.&lt;/p>
&lt;/blockquote>
&lt;h4 id="registering-the-custom-error-handler">Registering the Custom Error Handler&lt;/h4>
&lt;p>Finally, for our custom Error Handler to work, we need to add it to the list of our providers:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>, &lt;span style="color:#a6e22e">HttpClientModule&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">BrowserModule&lt;/span>, &lt;span style="color:#a6e22e">BrowserAnimationsModule&lt;/span>],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">ErrorHandler&lt;/span>,
&lt;span style="color:#a6e22e">useClass&lt;/span>: &lt;span style="color:#66d9ef">CustomErrorHandler&lt;/span>
}
],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Enabling Hot Module Replacement (HMR) in Angular 6</title><link>https://codinglatte.com/posts/angular/enabling-hot-module-replacement-angular-6/</link><pubDate>Fri, 31 Aug 2018 09:12:40 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/enabling-hot-module-replacement-angular-6/</guid><description>&lt;p>Hot Module Replacement (HMR) is a key webpack feature that is not enable by default in Angular. It allows for modules to be replaced without need for a full browser refresh. This allows you to retain much of the application state, usually lost when reloading. It also saves valuable times by only updating what has changed. And changes to the code reflect almost instantly, like when you are messing with dev tools on the browser. This is great for productivity.&lt;/p>
&lt;p>In this post, I will show you how to add Hot Module Replacement to your angular project. We will add it as an extra tool for you, without taking away the tools you are already used to such as ng serve. If you find it useful, you can continue using it and if not, nothing changes, you can fallback to your old tools. To enable HMR, we are going to make some modification to our code and add a new dev dependency. Let’s gets started:&lt;/p>
&lt;h3 id="installing-hot-module-replacement-dependency-for-angular">Installing Hot Module Replacement Dependency for Angular&lt;/h3>
&lt;p>First, we are going to install &lt;a href="https://github.com/gdi2290/angular-hmr">&lt;code>@angularclass/hmr&lt;/code>&lt;/a> dev package:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add –dev @angularclass/hmr
// or with npm
npm install --save-dev @angularclass/hmr
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to add an extra environment for our angular application, specifically for HMR. On top of that, we need to modify our existing environments and set HMR to false. You can learn more about environment variables &lt;a href="https://codinglatte.com/tech/developers/angular/environment-variables-angular/">here&lt;/a>.&lt;/p>
&lt;h3 id="adding-hmr-environment">Adding HMR Environment&lt;/h3>
&lt;p>Create a new environment file called &lt;code>environment.hmr.ts&lt;/code>, under &lt;code>src/environment&lt;/code> directory at the root of your workspace. Add the following code:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#a6e22e">hmr&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please note, we added an extra HMR property for our environment and set it to true. After these, we need to modify our angular configuration and add this environment for both our build and serve properties. Open &lt;code>angular.json&lt;/code> at the root of your angular workspace. Under build property, add a new configuration for HMR, with the content below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;build&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
    &lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: {
      &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
      &lt;span style="color:#f92672">&amp;#34;hmr&amp;#34;&lt;/span>: {
        &lt;span style="color:#f92672">&amp;#34;fileReplacements&amp;#34;&lt;/span>: [
          {
            &lt;span style="color:#f92672">&amp;#34;replace&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.ts&amp;#34;&lt;/span>,
            &lt;span style="color:#f92672">&amp;#34;with&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.hmr.ts&amp;#34;&lt;/span>
          }
        ]
      }
    }
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then under serve property, add another HMR configuration with the content below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;serve&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
    &lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: {
      &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
      &lt;span style="color:#f92672">&amp;#34;hmr&amp;#34;&lt;/span>: {
        &lt;span style="color:#f92672">&amp;#34;hmr&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;browserTarget&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;&amp;lt;project-name&amp;gt;:build:hmr&amp;#34;&lt;/span>
      }
    }
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next up, modify your typescript configurations (&lt;code>src/tsconfig.app.json&lt;/code>), to add Node to the typings array.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;compilerOptions&amp;#34;&lt;/span>: {
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
&lt;span style="color:#f92672">&amp;#34;types&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;node&amp;#34;&lt;/span>]
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="updating-existing-environments">Updating Existing Environments&lt;/h3>
&lt;p>Next, we need to modify our existing environment files, and set the HMR property to false. So, inside our &lt;code>environment.ts&lt;/code> and &lt;code>environment.prod.ts&lt;/code> add the hmr property and set it to false. Do the same for all other extra environments you may have in your app.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// environment.prod.ts
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#a6e22e">hmr&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// environment.ts
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#a6e22e">hmr&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="configure-your-app-to-use-hmr">Configure your App to Use HMR&lt;/h3>
&lt;p>Next up, we need to configure our angular app to use Hot Module Replacement. If you have an &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">Angular Workspace&lt;/a> with multiple projects/apps, you will have to do this for each app. First, create a new file – &lt;code>src/hmr.ts&lt;/code> – next to the &lt;code>src/main.ts&lt;/code> file and add the following code:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgModuleRef&lt;/span>, &lt;span style="color:#a6e22e">ApplicationRef&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">createNewHosts&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angularclass/hmr&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">hmrBootstrap&lt;/span> &lt;span style="color:#f92672">=&lt;/span> (
&lt;span style="color:#a6e22e">module&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>,
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">NgModuleRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span>
) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">ngModule&lt;/span>: &lt;span style="color:#66d9ef">NgModuleRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>;
&lt;span style="color:#66d9ef">module&lt;/span>&lt;span style="color:#a6e22e">.hot.accept&lt;/span>();
&lt;span style="color:#a6e22e">bootstrap&lt;/span>().&lt;span style="color:#a6e22e">then&lt;/span>(&lt;span style="color:#a6e22e">mod&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> (&lt;span style="color:#a6e22e">ngModule&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">mod&lt;/span>));
&lt;span style="color:#66d9ef">module&lt;/span>&lt;span style="color:#a6e22e">.hot.dispose&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">appRef&lt;/span>: &lt;span style="color:#66d9ef">ApplicationRef&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">ngModule&lt;/span>.&lt;span style="color:#a6e22e">injector&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#a6e22e">ApplicationRef&lt;/span>);
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">elements&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">appRef&lt;/span>.&lt;span style="color:#a6e22e">components&lt;/span>.&lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">c&lt;/span>.&lt;span style="color:#a6e22e">location&lt;/span>.&lt;span style="color:#a6e22e">nativeElement&lt;/span>);
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">makeVisible&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">createNewHosts&lt;/span>(&lt;span style="color:#a6e22e">elements&lt;/span>);
&lt;span style="color:#a6e22e">ngModule&lt;/span>.&lt;span style="color:#a6e22e">destroy&lt;/span>();
&lt;span style="color:#a6e22e">makeVisible&lt;/span>();
});
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, modify &lt;code>src/main.ts&lt;/code> file to use &lt;code>src/hmr.ts&lt;/code> code when serving your app with Hot Module Replacement enabled. This modification will only apply when you serve your app with &lt;code>--configuration hmr&lt;/code> flag and not under any other circumstances.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">enableProdMode&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">platformBrowserDynamic&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/platform-browser-dynamic&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AppModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app/app.module&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">environment&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./environments/environment&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">hmrBootstrap&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./hmr&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">production&lt;/span>) {
&lt;span style="color:#a6e22e">enableProdMode&lt;/span>();
}
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">bootstrap&lt;/span> &lt;span style="color:#f92672">=&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">platformBrowserDynamic&lt;/span>().&lt;span style="color:#a6e22e">bootstrapModule&lt;/span>(&lt;span style="color:#a6e22e">AppModule&lt;/span>);
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">hmr&lt;/span>) {
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">module&lt;/span>[&lt;span style="color:#e6db74">&amp;#39;hot&amp;#39;&lt;/span>]) {
&lt;span style="color:#a6e22e">hmrBootstrap&lt;/span>(&lt;span style="color:#a6e22e">module&lt;/span>, &lt;span style="color:#a6e22e">bootstrap&lt;/span>);
} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">error&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;HMR is not enabled for webpack-dev-server!&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;Are you using the --hmr flag for ng serve?&amp;#39;&lt;/span>);
}
} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;span style="color:#a6e22e">bootstrap&lt;/span>().&lt;span style="color:#66d9ef">catch&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>));
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="serving-your-app-with-hmr-enabled">Serving your App with HMR Enabled&lt;/h3>
&lt;p>Now, you can serve your app using the command below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng serve --configuration hmr
&lt;/code>&lt;/pre>&lt;/div>&lt;p>But since this is a long command to write every time, we can add it to our &lt;code>npm scripts&lt;/code> in our &lt;code>package.json&lt;/code> to make it shorter and easier to remember:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;scripts&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
 &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
 &lt;span style="color:#f92672">&amp;#34;hmr&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;ng serve --configuration hmr&amp;#34;&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, we can just run:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm run hmr
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Each time you run the command, you will get the following warning:&lt;/p>
&lt;p>NOTICE: Hot Module Replacement (HMR) is enabled for the dev server.&lt;/p>
&lt;p>With some more information on where to learn more about Hot Module Replacement.&lt;/p>
&lt;p>&lt;!-- raw HTML omitted -->&lt;/p></description></item><item><title>Building Docker Images for Deploying Angular Apps</title><link>https://codinglatte.com/posts/angular/building-docker-images-angular/</link><pubDate>Wed, 29 Aug 2018 14:32:03 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/building-docker-images-angular/</guid><description>&lt;p>In this post, we are going to look at how to deploy an angular app using docker. Docker containers can be used to simplify the process of developing, testing and deploying your app into different environments. With docker containers, you can be assured that the application will run the same no matter the environment in which it is deployed.&lt;/p>
&lt;p>In this demo, we are going to build a docker image for deploying an angular app to two different environments. One for production and the other for staging. Our demo application is going to have 3 environments – development, staging and production. We will be using the  development environment locally for developing and testing using ng serve. While the other two environments are deployed remotely. If you don’t know how to setup environments in angular, you can checkout this &lt;a href="//tech/developers/angular/environment-variables-angular/">post I did earlier&lt;/a>. Without further ado.&lt;/p>
&lt;h3 id="how-it-works">How it works&lt;/h3>
&lt;p>Once you are ready to deploy on either environment – staging or production, we are going to use a dockerfile to specify how our deployment image with our built app is going to be build. A &lt;code>dockerfile&lt;/code> is a special file that contains instructions on how to build our docker image. Since we need to automate the build process as much as possible, we are going to be building the angular app together with docker image.&lt;/p>
&lt;p>First, we are going to pull a NodeJS (node:8.X.X) from docker hub and use it to build our angular application. Then, we will copy our compiled angular application inside the &lt;code>dist&lt;/code> directory to our deployment container. Our deployment image will be a nginx alpine image – as you might have guessed using nginx proxy server. We will also need to copy the configuration to redirect all paths to index.html and compress our server output.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>To make things simple, we will have two dockerfiles for each of our deployment environments. They will have some minor differences such as the target environment when building our angular application. We are going to be using a multi stage docker build, where in stage 1, we will create a docker image to build our angular application.&lt;/p>
&lt;p>And then in the second stage we copy the results of the first stage and use it build and create a super light deployment docker image. This allows our final image to only contain the important files for deployment without any development files and tools being carried over. You can learn more about docker multistage build &lt;a href="https://docs.docker.com/develop/develop-images/multistage-build/#before-multi-stage-builds">here&lt;/a>.&lt;/p>
&lt;p>First, we need to create a new directory called &lt;code>.docker&lt;/code> in the root of our angular workspace. Inside it we are going to create three files. Two dockerfiles (&lt;code>prod.dockerfile&lt;/code> and &lt;code>staging.dockerfile&lt;/code>) and a nginx (&lt;code>nginx.conf&lt;/code>) configurations file.&lt;/p>
&lt;h3 id="nginx-configurations">Nginx Configurations&lt;/h3>
&lt;p>In this configuration file, we are going to have rules for redirecting all paths to index.html and add rules to compress content before being sent to the browser. You can replace this with apache or any other web server you are familiar with. Just make sure the configuration files are okay for your server and copy them in the correct directory inside your final image. Inside the nginx configuration file (nginx.conf), add the following content:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="color:#66d9ef">worker_processes&lt;/span>  &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;span style="color:#66d9ef">events&lt;/span> {
    &lt;span style="color:#f92672">worker_connections&lt;/span>  &lt;span style="color:#ae81ff">1024&lt;/span>;
}
&lt;span style="color:#66d9ef">http&lt;/span> {
    &lt;span style="color:#f92672">server&lt;/span> {
        &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">80&lt;/span>;
        &lt;span style="color:#f92672">server_name&lt;/span>  &lt;span style="color:#e6db74">localhost&lt;/span>;
        &lt;span style="color:#f92672">root&lt;/span>   &lt;span style="color:#e6db74">/usr/share/nginx/html&lt;/span>;
        &lt;span style="color:#f92672">index&lt;/span>  &lt;span style="color:#e6db74">index.html&lt;/span> &lt;span style="color:#e6db74">index.htm&lt;/span>;
        &lt;span style="color:#f92672">include&lt;/span> &lt;span style="color:#e6db74">/etc/nginx/mime.types&lt;/span>;
        &lt;span style="color:#f92672">gzip&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
        &lt;span style="color:#f92672">gzip_min_length&lt;/span> &lt;span style="color:#ae81ff">1000&lt;/span>;
        &lt;span style="color:#f92672">gzip_proxied&lt;/span> &lt;span style="color:#e6db74">expired&lt;/span> &lt;span style="color:#e6db74">no-cache&lt;/span> &lt;span style="color:#e6db74">no-store&lt;/span> &lt;span style="color:#e6db74">private&lt;/span> &lt;span style="color:#e6db74">auth&lt;/span>;
        &lt;span style="color:#f92672">gzip_types&lt;/span> &lt;span style="color:#e6db74">text/plain&lt;/span> &lt;span style="color:#e6db74">text/css&lt;/span> &lt;span style="color:#e6db74">application/json&lt;/span> &lt;span style="color:#e6db74">application/javascript&lt;/span> &lt;span style="color:#e6db74">application/x-javascript&lt;/span> &lt;span style="color:#e6db74">text/xml&lt;/span> &lt;span style="color:#e6db74">application/xml&lt;/span> &lt;span style="color:#e6db74">application/xml+rss&lt;/span> &lt;span style="color:#e6db74">text/javascript&lt;/span>;
&lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
            &lt;span style="color:#f92672">try_files&lt;/span> $uri $uri/ &lt;span style="color:#e6db74">/index.html&lt;/span>;
        }
    }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="creating-the-dockerfiles">Creating the Dockerfiles&lt;/h3>
&lt;p>Both dockerfiles will be the same, with some minor differences. For instance, the staging dockerfile will build targeting staging environment while the production will build with the prod flag. It is also possible to use the same dockerfile for both, but I find separating them doesn’t hurt. It also allows me to experiment with the staging version before making the final changes to the production one. This is all up to you. We are going to separate the dockerfiles into two sections, staging 1 and stage 2. As I said earlier, stage 1 will build the angular application and stage two will create a docker image for deployment.&lt;/p>
&lt;h4 id="stage-1">Stage 1&lt;/h4>
&lt;p>First we need a base image to build our first docker image on, since we are building using NodeJS, we will use node:8.11.4 docker image. Feel free to use any version of NodeJS you are comfortable with.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> node:8.11.4 as node&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we declare a working directory inside our image and then copy our angular workspace into the directory.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /app&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> . .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to install our @angular/cli and if you are a fan of Yarn like me, install it too.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> npm i yarn&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> yarn global add @angular/cli@latest&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, install the dependencies for your project by running either &lt;code>yarn install&lt;/code> or &lt;code>npm install&lt;/code> depending on the package manager you are using. And finally, it’s time to build your angular application. For staging environment, we will use the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> ng build --configuration&lt;span style="color:#f92672">=&lt;/span>staging&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>While for production environment, we will use the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">RUN&lt;/span> ng build –prod&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And now let’s move to stage two.&lt;/p>
&lt;h4 id="stage-2">Stage 2&lt;/h4>
&lt;p>In this stage, we are going to base our image on nginx:alpine image.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> nginx:alpine&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, copy all build artefacts to /usr/share/nginx/html directory and copy the nginx.conf to the /etc/nginx/conf.d/default.conf.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>node /app/dist/angular-docker-deployment /usr/share/nginx/html&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>node /app/.docker/nginx.conf /etc/nginx/conf.d/default.conf&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>One thing to note for those using Angular 5, copy the DIST directory instead of the project name directory inside the DIST directory.&lt;/em>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>node /app/dist /usr/share/nginx/html&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can check out both docker files &lt;a href="https://github.com/MainaWycliffe/angular-docker-deployment/tree/master/.docker">here&lt;/a>.&lt;/p>
&lt;h3 id="building-docker-images">Building Docker Images&lt;/h3>
&lt;p>And finally, you can build your image by running the following command at the root of your angular workspace: Windows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ps" data-lang="ps">&lt;span style="color:#a6e22e">docker&lt;/span> &lt;span style="color:#a6e22e">build&lt;/span> &lt;span style="color:#a6e22e">--rm&lt;/span> &lt;span style="color:#a6e22e">-f&lt;/span> &lt;span style="color:#a6e22e">.docker\staging.dockerfile&lt;/span> &lt;span style="color:#a6e22e">-t&lt;/span> &lt;span style="color:#a6e22e">webapp:latest&lt;/span> &lt;span style="color:#a6e22e">.&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Linux and Mac:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">docker build --rm -f .docker/staging.dockerfile -t webapp:latest .
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Replace &lt;code>webapp:latest&lt;/code> with your preferred image name and add your image tag after colons. To build a production image, replace &lt;code>.docker\staging.dockerfile&lt;/code> with &lt;code>.docker\prod.dockerfile&lt;/code>. Windows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ps" data-lang="ps">&lt;span style="color:#a6e22e">docker&lt;/span> &lt;span style="color:#a6e22e">build&lt;/span> &lt;span style="color:#a6e22e">--rm&lt;/span> &lt;span style="color:#a6e22e">-f&lt;/span> &lt;span style="color:#a6e22e">.docker\prod.dockerfile&lt;/span> &lt;span style="color:#a6e22e">-t&lt;/span> &lt;span style="color:#a6e22e">webapp:latest&lt;/span> &lt;span style="color:#a6e22e">.&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Linux and Mac:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">docker build --rm -f .docker/prod.dockerfile -t webapp:latest .
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And your docker image is ready for deployment. In the next post, I will cover how to deploy your docker image once you have built it. Sample Code You can find the whole code for this post &lt;a href="https://github.com/MainaWycliffe/angular-docker-deployment">here&lt;/a>.&lt;/p></description></item><item><title>Logging HTTP Errors in Angular 6</title><link>https://codinglatte.com/posts/angular/logging-http-errors-in-angular-6/</link><pubDate>Sun, 26 Aug 2018 10:24:01 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/logging-http-errors-in-angular-6/</guid><description>&lt;p>In my last &lt;a href="https://codinglatte.com/tech/developers/angular/refreshing-authorization-tokens-angular-6/">post&lt;/a>, I looked at how you can use HTTP Interceptors to attach and refresh authorization tokens. In this post, we are going to use the same HTTP Interceptor to catch HTTP errors – 500, 401, 400 etc. – and logging them remotely. It is important to analyze how your angular application is interacting with your APIs and other external API, so that you can improve the product itself. Collecting HTTP Errors at an angular app level could provide huge insight to you and your development team.&lt;/p>
&lt;p>So, without further ado:&lt;/p>
&lt;h3 id="creating-a-http-interceptor">Creating a HTTP Interceptor&lt;/h3>
&lt;p>Let’s first start by creating a HTTP Interceptor class – &lt;code>HttpLogInterceptor&lt;/code>, then adding it to our module (&lt;code>app.module.ts&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate class http-log-interceptor
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, open the http interceptor and make the following modifications to it:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Injectable&lt;/span>()
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">HttpLogInterceptor&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">HttpInterceptor&lt;/span> {
&lt;span style="color:#a6e22e">intercept&lt;/span>(
&lt;span style="color:#a6e22e">req&lt;/span>: &lt;span style="color:#66d9ef">HttpRequest&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">HttpHandler&lt;/span>
)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">HttpEvent&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span> {}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>First, we made the class injectable. Then, we implemented the &lt;a href="https://angular.io/api/common/http/HttpInterceptor">HTTP Interceptor&lt;/a> Interface by adding implements &lt;code>HttpInterceptor Interface&lt;/code>. And by adding the &lt;code>intercept&lt;/code> method – the method that will intercept and return the modified requests. Most of the action will take place inside this method. Next, we need to add the newly created HTTP interceptor class to the list of providers, in our module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">CommonModule&lt;/span>, &lt;span style="color:#a6e22e">MatDialogModule&lt;/span>],
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    &lt;span style="color:#a6e22e">AuthService&lt;/span>,
    {
      &lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">HTTP_INTERCEPTORS&lt;/span>,
      &lt;span style="color:#a6e22e">useClass&lt;/span>: &lt;span style="color:#66d9ef">HttpLogInterceptor&lt;/span>,
      &lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
    }
  ]
})
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="catching-and-logging-http-errors">Catching and Logging HTTP Errors&lt;/h3>
&lt;p>Inside our intercept method of our &lt;code>HttpLogInterceptor&lt;/code> class, we need to take the HTTP request, then pipe it and &lt;a href="https://www.learnrxjs.io/operators/error_handling/catch.html">&lt;code>catchErrors&lt;/code>&lt;/a>, then return the errors to the originator using &lt;code>throwError&lt;/code> operator of RXJS.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">req&lt;/span>).&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">catchError&lt;/span>(&lt;span style="color:#a6e22e">httpError&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// log your error here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">loggerService&lt;/span>.&lt;span style="color:#a6e22e">logger&lt;/span>(&lt;span style="color:#a6e22e">httpError&lt;/span>).&lt;span style="color:#a6e22e">subscribe&lt;/span>(); &lt;span style="color:#75715e">// re throw the error so it can be caught by the subscriber
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">throwError&lt;/span>(&lt;span style="color:#a6e22e">httpError&lt;/span>);
})
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to import our logger service into our interceptor. To avoid the Cyclic Dependency Injection error, we will inject Injector into our class. Then, we will use to assign our logger service to a variable and then we can use it as normal.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">loggerService&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inject&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#a6e22e">LoggerService&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In our service, we need a logger method, which will call and pass the &lt;code>HttpErrorResponse&lt;/code> error to our logger. Here, will subscribe to the logging method, inside our logger service. Since, the results of logging action don’t really matter to the end user, we will proceed and rethrow the original error.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">loggerService&lt;/span>.&lt;span style="color:#a6e22e">logger&lt;/span>(&lt;span style="color:#a6e22e">httpError&lt;/span>).&lt;span style="color:#a6e22e">subscribe&lt;/span>();
&lt;span style="color:#75715e">// re throw the error so it can be caught by the subscriber
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">throwError&lt;/span>(&lt;span style="color:#a6e22e">httpError&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>What this allows you to do, is to initiate a logging action on the background without affecting the user experience while waiting for logging to be completed. This is because the logging request will be carried asynchronously. This won’t prevent the execution of the next line of code after being called.&lt;/p>
&lt;h3 id="logging-error-method">Logging Error Method&lt;/h3>
&lt;p>Now, let’s create a logger method in our logger service. We will imaginatively call it “logger”.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">logger&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>: &lt;span style="color:#66d9ef">HttpErrorResponse&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we will send the error details to the logging server:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">logger&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>: &lt;span style="color:#66d9ef">HttpErrorResponse&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
    &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;URL TO Loggger&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>
      .&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#a6e22e">url&lt;/span>, {
        &lt;span style="color:#a6e22e">params&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
          &lt;span style="color:#a6e22e">url&lt;/span>: &lt;span style="color:#66d9ef">error.url&lt;/span>,
          &lt;span style="color:#a6e22e">content&lt;/span>: &lt;span style="color:#66d9ef">error.error&lt;/span>,
          &lt;span style="color:#a6e22e">status&lt;/span>: &lt;span style="color:#66d9ef">error.status.toString&lt;/span>()
        }
      })
      .&lt;span style="color:#a6e22e">pipe&lt;/span>(
        &lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
          &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>;
        })
      );
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this method, we take the HTTP response error object and convert the to the URL parameters of our get http request. You could also use HTTP Post method, to send the data to the logging server, with the error data as part of the body.&lt;/p></description></item><item><title>Refreshing Authorization Tokens – Angular 6</title><link>https://codinglatte.com/posts/angular/refreshing-authorization-tokens-angular-6/</link><pubDate>Wed, 22 Aug 2018 06:50:32 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/refreshing-authorization-tokens-angular-6/</guid><description>&lt;p>In this post, we are going to build a http interceptor for refreshing authorization tokens once expired. The idea here is to be able to intercept http requests, attach an authorization header to the request. And to intercept http response, check for authentication errors and refresh tokens when necessary, otherwise redirect to the login page.&lt;/p>
&lt;p>Once the token has been refreshed successfully, you should resend all intercepted HTTP responses back to their origin, and only return a non auth related error back to the end user. This whole process should occur smoothly without breaking the UX if successful. We should only interrupt the user when action is needed from them – such as log in in this case.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>Let’s first start by creating a HTTP Interceptor class, then adding it to our module (app.module.ts). ng generate class http-auth-interceptor Then, open the http interceptor and make the following modifications to it:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Injectable&lt;/span>()
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">HttpAuthInterceptor&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">HttpInterceptor&lt;/span> {
&lt;span style="color:#a6e22e">intercept&lt;/span>(
&lt;span style="color:#a6e22e">req&lt;/span>: &lt;span style="color:#66d9ef">HttpRequest&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">HttpHandler&lt;/span>
)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">HttpEvent&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span> {}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>First, we made the class injectable. Then, we implemented the &lt;a href="https://angular.io/api/common/http/HttpInterceptor">HTTP Interceptor&lt;/a> Interface, by one, adding implements &lt;code>HttpInterceptor&lt;/code>. And two, by adding the &lt;code>intercept&lt;/code> method – the method that will intercept and return the modified requests. Most of the action will take place inside this method. Next, we need to add the newly created http interceptor class to the list of providers, in our module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">CommonModule&lt;/span>, &lt;span style="color:#a6e22e">MatDialogModule&lt;/span>],
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    &lt;span style="color:#a6e22e">AuthService&lt;/span>,
    {
      &lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">HTTP_INTERCEPTORS&lt;/span>,
      &lt;span style="color:#a6e22e">useClass&lt;/span>: &lt;span style="color:#66d9ef">HttpAuthInterceptor&lt;/span>,
      &lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
    }
  ]
})
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="intercepting-http-requests-adding-authorization-header">Intercepting HTTP Requests (Adding Authorization Header)&lt;/h3>
&lt;p>Here, will are going to take the intercepted request, clone it, modify the copied http requests and return it as the new request.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Clone the request and authorization header
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">authReq&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({
&lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;authorization&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">Authorization&lt;/span> &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#a6e22e">Authorization&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>)
});
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can attach the header based on the authorization method you are using on your server. Example: Bearer Authorization.&lt;/p>
&lt;/blockquote>
&lt;p>After that, you can return the modified request which replaces the original request:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">authReq&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="refreshing-authorization-tokens">Refreshing Authorization Tokens&lt;/h3>
&lt;h4 id="intercepting-expired-tokens-request">Intercepting Expired Tokens Request&lt;/h4>
&lt;p>To refresh tokens, we need to monitor the responses looking for http status code 401 for unauthorized request.&lt;/p>
&lt;p>So, we are going to pipe our modified http request, and catch all errors. Next, we are going to check for http status code 401. Whenever we catch an authentication error, we are going to attempt and refresh our token.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">authReq&lt;/span>).&lt;span style="color:#a6e22e">pipe&lt;/span>(
   &lt;span style="color:#a6e22e">catchError&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
       &lt;span style="color:#75715e">// checks if a url is to an admin api or not
&lt;/span>&lt;span style="color:#75715e">&lt;/span>       &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">error&lt;/span>.&lt;span style="color:#a6e22e">status&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#ae81ff">401&lt;/span>) {
          &lt;span style="color:#75715e">// attempting to refresh our token
&lt;/span>&lt;span style="color:#75715e">&lt;/span>       }
   }
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We also need to avoid sending multiple refresh requests to our endpoint. This happens when you send multiple http requests simultaneously, and all of them return an authentication error. So, we are going to share (using &lt;a href="https://www.learnrxjs.io/operators/multicasting/share.html">Share Operator&lt;/a>) the existing refresh request across all intercepted http responses that find a token refresh request already inflight. Basically, when we catch a response with http status code 401, we are going to check if there is an inflight request to refresh our token, then hitch on it.&lt;/p>
&lt;p>If none exists, we are going to send a new refresh request. In our http interceptor class, we need to and &lt;code>inflightAuthRequest&lt;/code> property and set it to null. Then, when we get a http response error 401, we are going to check whether it is null.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">authService&lt;/span>.&lt;span style="color:#a6e22e">refreshToken&lt;/span>();
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span>) {
&lt;span style="color:#75715e">// remove existing tokens
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">clear&lt;/span>();
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#39;/sign-page&amp;#39;&lt;/span>]);
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">throwError&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>);
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If not, we are going to pipe the existing request and attach our request using &lt;a href="https://www.learnrxjs.io/operators/transformation/switchmap.html">SwitchMap&lt;/a> operator. After the token has been refreshed successfully, we are going to resend each of our http request (that responded with 401) back to the server, hoping to get another response not related to authentication.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">authService&lt;/span>.&lt;span style="color:#a6e22e">getToken&lt;/span>();
}
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span>.&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">switchMap&lt;/span>((&lt;span style="color:#a6e22e">newToken&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// unset inflight request
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#75715e">// clone the original request
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">authReqRepeat&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({
&lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">newToken&lt;/span>)
});
&lt;span style="color:#75715e">// resend the request
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">authReqRepeat&lt;/span>);
})
);
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="our-refresh-method">Our Refresh Method&lt;/h4>
&lt;p>In our refresh method, we are just going to be making a http request to our refresh token endpoint. This is also where we will add the &lt;a href="https://www.learnrxjs.io/operators/multicasting/share.html">RXJS Share Operator&lt;/a>, ensuring that only one request is sent at a time:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">refreshToken&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">string&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;url to refresh token here&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">// append refresh token if you have one
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">refreshToken&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">getItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>);
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>
      .&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#a6e22e">url&lt;/span>, {
        &lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">HttpHeaders&lt;/span>().&lt;span style="color:#a6e22e">set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">refreshToken&lt;/span>),
        &lt;span style="color:#a6e22e">observe&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;response&amp;#39;&lt;/span>
      })
      .&lt;span style="color:#a6e22e">pipe&lt;/span>(
        &lt;span style="color:#a6e22e">share&lt;/span>(), &lt;span style="color:#f92672">**&lt;/span>&lt;span style="color:#75715e">// &amp;lt;========== YOU HAVE TO SHARE THIS OBSERVABLE TO AVOID MULTIPLE REQUEST BEING SENT SIMULTANEOUSLY**
&lt;/span>&lt;span style="color:#75715e">&lt;/span>        &lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
          &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>);
          &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">newRefreshToken&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>);
&lt;span style="color:#75715e">// store the new tokens
&lt;/span>&lt;span style="color:#75715e">&lt;/span>          &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">setItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">newRefreshToken&lt;/span>);
          &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">setItem&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;token&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">token&lt;/span>);
          &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span>;
       })
    );
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="whitelist-and-blacklist-requests">Whitelist and Blacklist Requests&lt;/h3>
&lt;p>What we would like to achieve in this section is a simple way to exempt some request from going through a http interceptor. There are several ways used to achieve this. One common way is to attach a header to requests which you do not want to be modified by the interceptor. Then, check if the header is present at the beginning of the interceptor method. And if present, return an unmodified http request:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;authExempt&amp;#39;&lt;/span>) &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#e6db74">&amp;#39;true&amp;#39;&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">req&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is functional but requires you to manually add the header on the requests you are blacklisting. The other method which I consider to be much better, is to have a blacklist containing URLs or URL regex patterns. The idea being that if a URL is on the list, then you can exempt it from being modified by the http interceptor. For instance, you can simply exempt an entire sub directory using a simple &lt;a href="https://regex101.com/">regex&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">(((https?)://|www.)theinfogrid.com/auth/)
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above regex exempts all subdirectories with auth directory at the root. So, you can check if your URL is in the blacklist or not:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">blacklistCheckup&lt;/span>(&lt;span style="color:#a6e22e">$url&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">boolean&lt;/span> {
&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">returnValue&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>;
&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span> Object.&lt;span style="color:#a6e22e">keys&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">blacklist&lt;/span>)) {
      &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">blacklist&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>].&lt;span style="color:#a6e22e">exec&lt;/span>(&lt;span style="color:#a6e22e">$url&lt;/span>) &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>) {
        &lt;span style="color:#a6e22e">returnValue&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>;
        &lt;span style="color:#66d9ef">break&lt;/span>;
      }
   }
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">returnValue&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This gives you the freedom to blacklist or whitelist an entire domain/subdomain, without needing to attach a header to the request manually. You can then package it as an object and iterate through it. I am assuming, this should be a small list, because if it becomes too large, it will impact the performance of your app.&lt;/p>
&lt;h3 id="tips">Tips&lt;/h3>
&lt;blockquote>
&lt;p>You might want to consider attaching a header to the response originating from the refresh token endpoint. Then, check if the response contains the header before sending another refresh request. And if it does, and has status code 401, it means that the token was not refreshed successfully. Thus, you should redirect the user to the login page instead of sending another refresh token, which could lead into a loop of some sort.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">error&lt;/span>.&lt;span style="color:#a6e22e">status&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#ae81ff">401&lt;/span>) {
  &lt;span style="color:#75715e">// check if the response is from the token refresh end point
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">isFromRefreshTokenEndpoint&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">!!&lt;/span>&lt;span style="color:#a6e22e">error&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(
    &lt;span style="color:#e6db74">&amp;#39;unableToRefreshToken&amp;#39;&lt;/span>
  );
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">isFromRefreshTokenEndpoint&lt;/span>) {
  &lt;span style="color:#a6e22e">localStorage&lt;/span>.&lt;span style="color:#a6e22e">clear&lt;/span>();
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#39;/sign-page&amp;#39;&lt;/span>]);
  &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">throwError&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>To work around the Cyclic Dependency Error, do not inject your AuthService inside the constructor. Instead, inject the injector class and then use it inside the interceptor method to inject AuthService into a variable. The constructor for our http interceptor&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">injector&lt;/span>: &lt;span style="color:#66d9ef">Injector&lt;/span>, ...) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then inside our method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">const authService = this.injector.get(AuthService);
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="get-this-code">Get this Code&lt;/h3>
&lt;p>You can get the complete code &lt;a href="https://github.com/MainaWycliffe/refreshing-authorization-token-angular-6">here&lt;/a>.&lt;/p></description></item><item><title>Getting Started with Debugging Angular Apps in VSCode</title><link>https://codinglatte.com/posts/angular/debugging-angular-apps-vscode/</link><pubDate>Mon, 20 Aug 2018 12:28:36 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/debugging-angular-apps-vscode/</guid><description>&lt;p>In this post, I am going to show you how to get started with debugging angular apps in VSCode. We shall target Firefox, Chrome and Microsoft Edge. VSCode Debugger provide important features that can improve your &lt;a href="https://codinglatte.com/posts/angular/angular-development-tips/">development experience&lt;/a>.&lt;/p>
&lt;p>These features include: break point, code stepping and stack traces. With VSCode debugger,  you can get all errors, console messages and debug information from different browser at the same console. It also provides a consistent debug experience as compared to using individual tools found in each browser. Let’s get started:&lt;/p>
&lt;h2 id="google-chrome-debugger">Google Chrome Debugger&lt;/h2>
&lt;p>Let’s get started with chrome, since it’s the most popular browser out there. Majority of your users will likely be using it. Therefore, you must ensure everything is working as smoothly as possible on the browser. On top of that, there are other browsers that use the JavaScript &lt;a href="https://en.wikipedia.org/wiki/Chrome_V8">Chrome V8 engine&lt;/a>. First, install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome">Debugger for Chrome&lt;/a> extension on VSCode. Once that’s complete, open the angular app you wish to debug.&lt;/p>
&lt;h3 id="configurations">Configurations&lt;/h3>
&lt;p>Next, we need to configure the debugger for our angular app. To do this, open the debugger (&lt;code>CTL + SHIFT + D&lt;/code>) and click on the gear icons to create the launch.json file – this is where our configuration are stored. A new launch.json (under .vscode folder in the root of your VSCode Workspace) file is created with the following defaults:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;version&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;0.2.0&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;configurations&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;chrome&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;request&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;launch&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Launch Chrome against localhost&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;url&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;http://localhost:8080&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;webRoot&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;${workspaceFolder}&amp;#34;&lt;/span>
}
]
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Change the URL to point to the address of your Angular app Server. The default URL is localhost on port 4200 (&lt;code>http://localhost:4200&lt;/code>), but some developers change that especially when you are developing multiple application. Also, change the name of your configuration to something you can easily remember. Next, serve your application as you normally would:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ps" data-lang="ps">&lt;span style="color:#a6e22e">ng&lt;/span> &lt;span style="color:#a6e22e">serve&lt;/span> &lt;span style="color:#a6e22e">or&lt;/span> &lt;span style="color:#a6e22e">ng&lt;/span> &lt;span style="color:#a6e22e">serve&lt;/span> &lt;span style="color:#a6e22e">--aot&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally launch your debugger using either F5 or by pressing on the play icon, at the top of the debugger side panel. A new chrome window will be launched which will open your angular app. To view console messages and activity, open the debug console, by using &lt;code>CTL + SHIFT + Y&lt;/code> or by Going to View, then Click on the Debug Console.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/08/debugg2-1024x663.png" alt="Getting Started with Debugging Angular Apps in VSCode">&lt;/p>
&lt;h3 id="debuggers-for-firefox-and-microsoft-edge">Debuggers for Firefox and Microsoft Edge&lt;/h3>
&lt;p>Next up is Firefox and Microsoft Edge. The process is much like the process of setting up Chrome above. First, install &lt;a href="https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-firefox-debug">Debugger for Firefox&lt;/a> and &lt;a href="https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-edge">Debugger for Edge&lt;/a>.&lt;/p>
&lt;p>Next, open debugger on VSCode (&lt;code>CTL + SHIFT + D&lt;/code>) and press on the gear icon. If you are working on the same angular app as before, clicking on the gear icon, will open launch.json, with configuration to debug on chrome. So, in this case instead of replacing the Chrome Configurations , we need to add new configurations for debugging on both Firefox and Microsoft Edge. To do this, there is an &lt;strong>Add Configurations&lt;/strong> button at the bottom right of the window.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/08/debugg-1024x523.png" alt="Getting Started with Debugging Angular Apps in VSCode">&lt;/p>
&lt;p>Click on the button, and an autocomplete dropdown window will show up, where you can type in the configurations you wish to add. So, to add Firefox, type Firefox and select &lt;code>Firefox: Launch (server)&lt;/code> and to add Edge, type Edge, and then select Edge: Launch. You should have two new configurations in your &lt;code>launch.json&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">[
{
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;firefox&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;request&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;launch&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;reAttach&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Launch localhost&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;url&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;http://localhost:4200&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;webRoot&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;${workspaceFolder}&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;edge&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;request&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;launch&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Launch Edge (Frontend App)&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;url&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;http://localhost:4200&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;webRoot&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;${workspaceFolder}&amp;#34;&lt;/span>
}
]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Make the necessary changes to the configurations, especially the URL to point to your server. Don’t forget to add a port to the URL of the Firefox configuration. Once you are done with the configuration, make sure you are running your Angular server. Then open the debugger (&lt;code>CTL + SHIFT + D&lt;/code>) and on the drop down in between play and gear icon, select which browser you would like to debug with and click on the play button. A browser window of the browser you chose should launch and your app should open.&lt;/p>
&lt;h4 id="vscode-console">VSCode Console&lt;/h4>
&lt;p>To view console activity on VSCode, open the debug console, by using &lt;code>CTL + SHIFT + Y&lt;/code> or by Going to View on the menu bar, then Click on the Debug Console. Now you can add breaking point on your angular code, and it will pause when it gets to the break point. You can also step through your code while observing how various variable change through the process using breaking points among other advantages.&lt;/p>
&lt;h3 id="sign-in-off">Sign in off&lt;/h3>
&lt;p>I hope I have covered every aspect to help you getting started with debugging angular apps on vscode. Thank you for getting this far, if you found this useful, please don’t forget to share with your friends and colleagues. Here is another &lt;a href="https://codinglatte.com/tech/developers/angular/top-vscode-extensions-angular/">post&lt;/a> on Visual Studio Code and Angular that might be helpful.&lt;/p></description></item><item><title>How to build an image cropper form control in angular</title><link>https://codinglatte.com/posts/angular/build-image-cropper-form-control-angular/</link><pubDate>Fri, 17 Aug 2018 15:25:54 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/build-image-cropper-form-control-angular/</guid><description>&lt;p>In an earlier &lt;a href="https://codinglatte.com/tech/developers/angular/angular-build-custom-form-control/">post&lt;/a>, I demonstrated how to build an extremely simple custom form control. Today, I have decided to try to up the stakes. We are going to build an image cropper and package it as a form control which is ready to be used in any of our forms – be it template driven or reactive forms. My goal for this post, is to create something that works like the file input html element, that you can select, crop and validate its content. A simple drop in solution in your forms for cropping images easily alongside other data input.&lt;/p>
&lt;h1 id="getting-started">Getting Started&lt;/h1>
&lt;p>In this demo, we are going to be using &lt;a href="https://foliotek.github.io/Croppie/">Croppie&lt;/a> JavaScript Library to crop our images. To make things easier, we will use an angular wrapper called &lt;a href="https://github.com/deej81/ngx-croppie">&lt;code>ngx-croppie&lt;/code>&lt;/a>. I will try to make it easier to follow for those using a different Image Cropper JavaScript Library. You can install the wrapper together with croppie using either NPM or Yarn:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">npm i croppie ngx-croppie
yarn add croppie ngx-croppie
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then install &lt;code>@types/croppie&lt;/code> (croppie typings for TypeScript) as dev dependencies in your project:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">
npm i @types/croppie -D
yarn add –dev &amp;#34;@types/croppie
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then import &lt;code>NgxCroppieModule&lt;/code> in your module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [ ...],
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    ...
    &lt;span style="color:#f92672">**&lt;/span>&lt;span style="color:#a6e22e">NgxCroppieModule&lt;/span>&lt;span style="color:#f92672">**&lt;/span>,
    ...
  ],
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
  &lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then add croppie.css in your projects list of styles inside the angular.json:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
&lt;span style="color:#e6db74">&amp;#34;node_modules/croppie/croppie.css&amp;#34;&lt;/span>
]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>First, we need to create a new component which will wrap around ngx-croppie component and implement the &lt;a href="https://angular.io/api/forms/ControlValueAccessor">&lt;code>ControlValueAccessor&lt;/code>&lt;/a> interface.&lt;/p>
&lt;h2 id="using-ngx-croppie-to-crop-images">Using ngx-croppie to crop images&lt;/h2>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can skip this whole section if you are using a different image cropper library.&lt;/p>
&lt;/blockquote>
&lt;p>Inside the component controller, we need a &lt;code>croppieImage&lt;/code> property which will hold our current image. Then, we need to pass the height and width of our cropper using our cropper, so we need &lt;code>imgCropToHeight&lt;/code> and &lt;code>imgCropToWidth&lt;/code> properties – both have the &lt;a href="https://angular.io/api/core/Input">&lt;code>Input()&lt;/code>&lt;/a> decorator. I have also added &lt;code>responseType&lt;/code> property, allowing us to request the image in either base64 or blob type. And an &lt;code>outputOptions&lt;/code> property, which we pass to ngx-croppie and allows us to set the image size and output format of the image. On top of that we need &lt;code>ngxCroppie&lt;/code> property – marked by &lt;a href="https://angular.io/api/core/ViewChild">&lt;code>viewChild&lt;/code>&lt;/a> decorator, which just passes the element where our image cropper will be rendered into.&lt;/p>
&lt;h2 id="methods-for-ngx-croppie">Methods for ngx-croppie&lt;/h2>
&lt;p>The first method we need is to construct CroppieOptions. This will stitch together the variables we passed to our component, to create CroppieOptions. You can learn more about the available CroppieOptions &lt;a href="https://foliotek.github.io/Croppie/">here&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">get&lt;/span> &lt;span style="color:#a6e22e">croppieOptions&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">CroppieOptions&lt;/span> {
    &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">opts&lt;/span>: &lt;span style="color:#66d9ef">CroppieOptions&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {};
    &lt;span style="color:#a6e22e">opts&lt;/span>.&lt;span style="color:#a6e22e">viewport&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
      &lt;span style="color:#a6e22e">width&lt;/span>: &lt;span style="color:#66d9ef">parseInt&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">imgCropToWidth&lt;/span>, &lt;span style="color:#ae81ff">10&lt;/span>),
      &lt;span style="color:#a6e22e">height&lt;/span>: &lt;span style="color:#66d9ef">parseInt&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">imgCropToHeight&lt;/span>, &lt;span style="color:#ae81ff">10&lt;/span>)
    };
&lt;span style="color:#a6e22e">opts&lt;/span>.&lt;span style="color:#a6e22e">boundary&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
      &lt;span style="color:#a6e22e">width&lt;/span>: &lt;span style="color:#66d9ef">parseInt&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">imgCropToWidth&lt;/span>, &lt;span style="color:#ae81ff">10&lt;/span>) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>,
      &lt;span style="color:#a6e22e">height&lt;/span>: &lt;span style="color:#66d9ef">parseInt&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">imgCropToWidth&lt;/span>, &lt;span style="color:#ae81ff">10&lt;/span>) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>
    };
&lt;span style="color:#a6e22e">opts&lt;/span>.&lt;span style="color:#a6e22e">enforceBoundary&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>;
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">opts&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need a method that gets triggered when an image is selected.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">imageUploadEvent&lt;/span>(&lt;span style="color:#a6e22e">evt&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) {
    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">evt&lt;/span>.&lt;span style="color:#a6e22e">target&lt;/span>) {
      &lt;span style="color:#66d9ef">return&lt;/span>;
    }
    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">evt&lt;/span>.&lt;span style="color:#a6e22e">target&lt;/span>.&lt;span style="color:#a6e22e">files&lt;/span>) {
      &lt;span style="color:#66d9ef">return&lt;/span>;
    }
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">evt&lt;/span>.&lt;span style="color:#a6e22e">target&lt;/span>.&lt;span style="color:#a6e22e">files&lt;/span>.&lt;span style="color:#a6e22e">length&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>) {
      &lt;span style="color:#66d9ef">return&lt;/span>;
    }
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">file&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">evt&lt;/span>.&lt;span style="color:#a6e22e">target&lt;/span>.&lt;span style="color:#a6e22e">files&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>];
    &lt;span style="color:#66d9ef">if&lt;/span> (
      &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">type&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;image/jpeg&amp;#39;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>
      &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">type&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;image/png&amp;#39;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>
      &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">type&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;image/gif&amp;#39;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>
      &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">type&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;image/jpg&amp;#39;&lt;/span>
    ) {
      &lt;span style="color:#66d9ef">return&lt;/span>;
    }
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">fr&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">FileReader&lt;/span>();
    &lt;span style="color:#a6e22e">fr&lt;/span>.&lt;span style="color:#a6e22e">onloadend&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">loadEvent&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">croppieImage&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">fr&lt;/span>.&lt;span style="color:#a6e22e">result&lt;/span>.&lt;span style="color:#a6e22e">toString&lt;/span>();
    };
&lt;span style="color:#a6e22e">fr&lt;/span>.&lt;span style="color:#a6e22e">readAsDataURL&lt;/span>(&lt;span style="color:#a6e22e">file&lt;/span>);
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After that, we need another method that is triggered when you crop your image. When it is triggered, the image is passed as a parameter that you can then it to the &lt;strong>croppieImage&lt;/strong> property.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">newImageResultFromCroppie&lt;/span>(&lt;span style="color:#a6e22e">img&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">croppieImage&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">img&lt;/span>;
    &lt;span style="color:#75715e">//set this croppieImage value as the value of the component
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">croppieImage&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, on component initialization, we need to set our return image type – whether base64 or blob image type.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>
    &lt;span style="color:#75715e">/* Size the outputoptions of our cropped imaged - whether is base64 or blob */&lt;/span>
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">outputoption&lt;/span> &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#a6e22e">type&lt;/span>: &lt;span style="color:#66d9ef">this.responseType&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;original&amp;#39;&lt;/span> };
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to add a ngOnChanges Method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">ngOnChanges&lt;/span>(&lt;span style="color:#a6e22e">changes&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) {
    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">croppieImage&lt;/span>) {
      &lt;span style="color:#66d9ef">return&lt;/span>;
    }
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">changes&lt;/span>.&lt;span style="color:#a6e22e">imageUrl&lt;/span>) {
      &lt;span style="color:#66d9ef">return&lt;/span>;
    }
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">changes&lt;/span>.&lt;span style="color:#a6e22e">imageUrl&lt;/span>.&lt;span style="color:#a6e22e">previousValue&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">changes&lt;/span>.&lt;span style="color:#a6e22e">imageUrl&lt;/span>.&lt;span style="color:#a6e22e">currentValue&lt;/span>) {
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">croppieImage&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">changes&lt;/span>.&lt;span style="color:#a6e22e">imageUrl&lt;/span>.&lt;span style="color:#a6e22e">currentValue&lt;/span>;
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">croppieImage&lt;/span>);
    }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="controlvalueaccessor-interface-methods">ControlValueAccessor Interface Methods&lt;/h3>
&lt;p>After that, we need to implement the methods necessary for &lt;code>ControlValueAccessor&lt;/code> interface. This is what gives our component the behavior of a form control. I explained everything my previous post &lt;a href="https://codinglatte.com/tech/developers/angular/angular-build-custom-form-control/">here&lt;/a> about creating custom form controls.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">writeValue&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) {
    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#66d9ef">undefined&lt;/span>) {
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">croppieImage&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>;
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">croppieImage&lt;/span>);
    }
}
&lt;span style="color:#a6e22e">propagateChange&lt;/span> &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#a6e22e">_&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {};
&lt;span style="color:#a6e22e">registerOnChange&lt;/span>(&lt;span style="color:#a6e22e">fn&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">fn&lt;/span>;
}
&lt;span style="color:#a6e22e">registerOnTouched() {&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, provide the &lt;code>NG_VALUE_ACCESSOR&lt;/code> for the component:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">NG_VALUE_ACCESSOR&lt;/span>,
&lt;span style="color:#a6e22e">useExisting&lt;/span>: &lt;span style="color:#66d9ef">forwardRef&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">CustomImageFormControlComponent&lt;/span>),
&lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
}
];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And don’t forget to add the interfaces we are implementing to our component:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">CustomImageFormControlComponent&lt;/span>
&lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">OnInit&lt;/span>, &lt;span style="color:#a6e22e">OnChanges&lt;/span>, &lt;span style="color:#a6e22e">ControlValueAccessor&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="our-template">Our Template&lt;/h3>
&lt;p>And then in our template, we need to add ngx-croppie component, a hidden file input html element and a button to trigger the select file dialog of our file input html element.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">ngx-croppie&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;croppieImage&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">ngxCroppie&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">outputFormatOptions&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">outputoption&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">croppieOptions&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">croppieOptions&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">imageUrl&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">croppieImage&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">result&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">newImageResultFromCroppie&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&amp;gt;&amp;lt;/&lt;span style="color:#f92672">ngx-croppie&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">imageUpload&lt;/span>
&lt;span style="color:#a6e22e">hidden&lt;/span>
&lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;file&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">id&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;fileupload&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">imageUpload&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">change&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">imageUploadEvent&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">accept&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;image/gif, image/jpeg, image/png&amp;#34;&lt;/span>
/&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-white font-weight-bold mat-elevation-z0&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;button&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">mat-raised-button&lt;/span>
&lt;span style="color:#a6e22e">color&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;primary&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">imageUpload&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-icon&lt;/span>&amp;gt;add_a_photo&amp;lt;/&lt;span style="color:#f92672">mat-icon&lt;/span>&amp;gt;
Select Image
&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="using-our-image-form-control">Using our image form control&lt;/h3>
&lt;p>To use our image form control, we just use a normal form control:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">myform&lt;/span>: &lt;span style="color:#66d9ef">FormGroup&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">fb&lt;/span>: &lt;span style="color:#66d9ef">FormBuilder&lt;/span>) {}
&lt;span style="color:#a6e22e">createForm&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">FormGroup&lt;/span> {
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({
&lt;span style="color:#a6e22e">BlobImage&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])],
      &lt;span style="color:#a6e22e">base64Image&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])]
    });
}
&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">myform&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">createForm&lt;/span>();
}
&lt;span style="color:#a6e22e">submit() {&lt;/span>
    &lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">myform&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then in our template:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">form&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">formGroup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">myform&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">submit&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">submit&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;500px&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxLayoutAlign&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;center center&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlexOffset&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;calc(50% - 250px)&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">xs&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlexOffset&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">xs&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;0&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;padding: 10px;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-custom-image-form-control&lt;/span>
&lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;BlobImage&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">responseType&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">blob&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&amp;#34;&lt;/span>
&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-custom-image-form-control&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;myform.controls[&amp;#39;BlobImage&amp;#39;].hasError(&amp;#39;required&amp;#39;)&amp;#34;&lt;/span>&amp;gt;
This field is required
&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-custom-image-form-control&lt;/span>
&lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;base64Image&amp;#34;&lt;/span>
&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-custom-image-form-control&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;myform.controls[&amp;#39;base64Image&amp;#39;].hasError(&amp;#39;required&amp;#39;)&amp;#34;&lt;/span>&amp;gt;
This field is required
&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span> &lt;span style="color:#a6e22e">color&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;primary&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-icon&lt;/span>&amp;gt;save&amp;lt;/&lt;span style="color:#f92672">mat-icon&lt;/span>&amp;gt;
Submit
&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">form&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>We can also validate the content of our image form control. In the above post, I just made a required input, but you can do more by using &lt;a href="https://codinglatte.com/tech/developers/angular/angular-building-custom-validators/">custom form validators&lt;/a>.&lt;/em>&lt;/p>
&lt;h3 id="demo-and-source-code">Demo and Source Code&lt;/h3>
&lt;p>You can try this demo &lt;a href="https://mainawycliffe.github.io/cropped-image-form-control-in-angular-demo/">here&lt;/a> and view this demo &lt;a href="https://github.com/MainaWycliffe/cropped-image-form-control-in-angular-demo">here&lt;/a>.&lt;/p></description></item><item><title>Angular Material Autocomplete with HTTP Lookup</title><link>https://codinglatte.com/posts/angular/ng-material-autocomplete-http-lookup/</link><pubDate>Wed, 15 Aug 2018 19:19:33 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/ng-material-autocomplete-http-lookup/</guid><description>&lt;p>In this demo, we will build an angular autocomplete component that gets autocomplete suggestions from a http service such as a REST API. The idea here is that, instead of using a static autocomplete list, we are going to pull autocomplete suggestions directly from our database. This is a neat feature to have especially if you are implementing a search function in your angular app.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>First, I am going to assume that, you have some basic knowledge on both Angular and Angular 2 Material. If you are new to this, please check out the tutorials on Angular &lt;a href="https://angular.io/tutorial">here&lt;/a> and Angular 2 Material &lt;a href="https://material.angular.io/">here&lt;/a>.&lt;/p>
&lt;p>In this demo, we will create a simple search for Github repositories. You enter the name of a repository and get the results. Then you can use the results  (list of repositories matching the name you entered) as a autocomplete options. Github API provides the option to retrieve results for unauthenticated users, you can learn more &lt;a href="https://developer.github.com/v3/search/">here&lt;/a>.&lt;/p>
&lt;p>Make sure you have imported all Angular Material Modules you need for your specific project. In this project we will be using &lt;code>MatAutocompleteModule&lt;/code>, &lt;code>MatFormFieldModule&lt;/code> and &lt;code>MatInputModule&lt;/code>.&lt;/p>
&lt;p>So, without further ado, let’s get into the code:&lt;/p>
&lt;h3 id="github-lookup-service">Github Lookup Service&lt;/h3>
&lt;p>We are going to create a service that will interact with the Github API. It will make HTTP calls to the API and return an observable of the search results. To make things easier, we will also create an interface – &lt;code>GithubResponse&lt;/code> – that we can use to type cast our results we expect from github. Please checkout out the interface details &lt;a href="https://github.com/MainaWycliffe/angular-material-autocomplete-with-http-service-demo/blob/master/src/app/interface.ts">here&lt;/a>.&lt;/p>
&lt;p>First, Let’s look at our service.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// github.service.ts
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">GithubService&lt;/span> {
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">http&lt;/span>: &lt;span style="color:#66d9ef">HttpClient&lt;/span>) {}
&lt;span style="color:#a6e22e">search&lt;/span>(&lt;span style="color:#a6e22e">query&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">GithubResponse&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;https://api.github.com/search/repositories&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>
.&lt;span style="color:#a6e22e">get&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">GithubResponse&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#a6e22e">url&lt;/span>, {
&lt;span style="color:#a6e22e">observe&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;response&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">params&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">q&lt;/span>: &lt;span style="color:#66d9ef">query&lt;/span>,
&lt;span style="color:#a6e22e">sort&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;stars&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">order&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;desc&amp;#39;&lt;/span>
}
})
.&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">map&lt;/span>((&lt;span style="color:#a6e22e">res&lt;/span>: &lt;span style="color:#66d9ef">Response&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">body&lt;/span>;
})
);
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>It has a single method, that takes in the search query and returns the results. This is your normal service and doesn’t do anything special.&lt;/p>
&lt;h3 id="autocomplete-component">Autocomplete Component&lt;/h3>
&lt;p>In our component, we will need an observable Property - &lt;code>GithubAutoComplete$&lt;/code> - which we can subscribe to using &lt;a href="https://angular.io/api/common/AsyncPipe">async pipe&lt;/a>, so that it can always have the latest values of our autocomplete options. So, we shall first subscribe to the autocomplete form control value changes, then use the value of the autocomplete form control as the query for our search method. And then we shall return the results to the &lt;code>GithubAutoComplete$&lt;/code> property of our component.&lt;/p>
&lt;p>First, declare a &lt;code>GithubAutoComplete$&lt;/code> and our form control property - &lt;code>autoCompleteControl&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">githubAutoComplete$&lt;/span>: &lt;span style="color:#66d9ef">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">Items&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">autoCompleteControl&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">FormControl&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, let’s create a lookup method that maps the results from github to an object we can use and catch errors.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">lookup&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">Items&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">githubService&lt;/span>.&lt;span style="color:#a6e22e">search&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>.&lt;span style="color:#a6e22e">toLowerCase&lt;/span>()).&lt;span style="color:#a6e22e">pipe&lt;/span>(
      &lt;span style="color:#75715e">// map the item property of the github results as our return object
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">results&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">results&lt;/span>.&lt;span style="color:#a6e22e">items&lt;/span>),
      &lt;span style="color:#75715e">// catch errors
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">catchError&lt;/span>(&lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
        &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#66d9ef">null&lt;/span>);
      })
    );
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, on component initialization (&lt;code>ngOnInit&lt;/code> Method), assign our &lt;code>GithubAutoComplete$&lt;/code> to the observable of the &lt;code>valueChanges&lt;/code> of our input form control.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">githubAutoComplete$&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">autoCompleteControl&lt;/span>.&lt;span style="color:#a6e22e">valueChanges&lt;/span>.&lt;span style="color:#a6e22e">pipe&lt;/span>(
      &lt;span style="color:#a6e22e">startWith&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>),
      &lt;span style="color:#75715e">// delay emits
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">debounceTime&lt;/span>(&lt;span style="color:#ae81ff">300&lt;/span>),
      &lt;span style="color:#75715e">// use switch map so as to cancel previous subscribed events, before creating new once
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">switchMap&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
        &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>) {
          &lt;span style="color:#75715e">// lookup from github
&lt;/span>&lt;span style="color:#75715e">&lt;/span>          &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">lookup&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>);
        } &lt;span style="color:#66d9ef">else&lt;/span> {
          &lt;span style="color:#75715e">// if no value is present, return null
&lt;/span>&lt;span style="color:#75715e">&lt;/span>          &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#66d9ef">null&lt;/span>);
        }
      })
    );
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>Please read through the comments for further code clarification.&lt;/em> And finally, in our template, we use async pipe to subscribe to the &lt;code>GithubAutoComplete$&lt;/code> observable inside &lt;code>*ngFor&lt;/code> as shown below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-form-field&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">formControl&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">autoCompleteControl&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Pick one&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">aria-label&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Number&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">matInput&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">matAutocomplete&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">auto&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;
    &amp;lt;&lt;span style="color:#f92672">mat-autocomplete&lt;/span> &lt;span style="color:#a6e22e">autoActiveFirstOption&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">auto&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;matAutocomplete&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-option&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">***&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">****=****&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">let&lt;/span> &lt;span style="color:#a6e22e">item&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span> &lt;span style="color:#a6e22e">githubAutoComplete&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">|&lt;/span> &lt;span style="color:#a6e22e">async&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">;&lt;/span> &lt;span style="color:#a6e22e">let&lt;/span> &lt;span style="color:#a6e22e">index &lt;/span>&lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">index&amp;#34;**&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">item&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;
        {{ item.name | titlecase}}
    &amp;lt;/&lt;span style="color:#f92672">mat-option&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-autocomplete&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-form-field&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it, a working Angular 2 Material Autocomplete which works with a HTTP Service.&lt;/p>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>Remember to implement OnInit interface on your component to run the &lt;code>ngOnInit&lt;/code> method on component initialization.&lt;/em>&lt;/p>
&lt;h3 id="source-code-and-demo">Source Code and Demo&lt;/h3>
&lt;p>You can find a demo to tryout with &lt;a href="https://mainawycliffe.github.io/angular-material-autocomplete-with-http-service-demo/">here&lt;/a> and the source code &lt;a href="https://github.com/MainaWycliffe/angular-material-autocomplete-with-http-service-demo">here&lt;/a>.&lt;/p>
&lt;h3 id="sign-in-off">Sign in off&lt;/h3>
&lt;p>Thank you for getting this far on this post, I hope this was helpful. If I missed anything or something was not clear, please tell me on the comment section below. Here are some more topics on Angular:&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/lazy-loading-images-angular-6/">Lazy Loading Images in Angular 6&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/options-deploying-angular-apps/">Options for Deploying Angular Apps&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/angular-build-custom-form-control/">How to Build a Custom Form Control in Angular&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/top-vscode-extensions-angular/">Top VSCode Extensions for Angular Developers&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/environment-variables-angular/">Working with Environment Variables in Angular 6&lt;/a>&lt;/li>
&lt;/ol></description></item><item><title>Lazy Loading Images in Angular 6</title><link>https://codinglatte.com/posts/angular/lazy-loading-images-angular-6/</link><pubDate>Mon, 13 Aug 2018 14:51:13 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/lazy-loading-images-angular-6/</guid><description>&lt;p>In most web apps, images form a huge chunk of the size of the content. If you had, let’s say over 50 images with each having 100Kbs (after compression and resizing) in size, the total of that would be 100 x 50 which is 5MBs in total size. While storage wise, that is not a lot, on a standard 3G internet connection, it would load slowly hence negatively affect the User Experience and the performance of your web app.&lt;/p>
&lt;p>This is because, while images won’t affect initial loading and rendering of the site. All 50 images will be competing for the limited bandwidth to be loaded at once, hence loading slowly. This can be rectified by lazy loading images that are not in the view.&lt;/p>
&lt;p>If out of the 50 images only 3 images are in view initially, then you only need 300KBs (3 x 100 KB s) initially which is less than 10% of what you required initially. Then as each image comes in to view, it is loaded then and only then. If you combine this with a service worker, to cache the already loaded images, the performance gains could be huge.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>For this demo, we will use &lt;a href="https://github.com/TradeMe/ng-defer-load">ng-defer-load&lt;/a> library for lazy loading images. This library can also be used to lazy load any element in your angular application. But for now we will just use it with images. We will start by installing and setting it up in our application: &lt;strong>NPM:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm i @trademe/ng-defer-load
// or with yarn
yarn add @trademe/ng-defer-load
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, import it into your &lt;strong>app.module.ts.&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
    &lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
    &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span>,
    &lt;span style="color:#a6e22e">BrowserAnimationsModule&lt;/span>,
    &lt;span style="color:#a6e22e">DeferLoadModule&lt;/span>
  ],
  &lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
  &lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>})
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="lazy-loading-images">Lazy Loading Images&lt;/h3>
&lt;p>First, we need images to lazy load. We will use images from &lt;a href="https://placeholder.com/">Placeholder&lt;/a>, 100 of them to lazy load them. We are going have a placeholder caption of the image of the image number. Then, we will generate the image collection using a loop, as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">imageCollection&lt;/span> &lt;span style="color:#f92672">=&lt;/span> [];
&lt;span style="color:#66d9ef">constructor&lt;/span>() {
  &lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span>) {
      &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;http://via.placeholder.com/500x450?text=Image No &amp;#39;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> (&lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>);
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">imageCollection&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> {
        &lt;span style="color:#a6e22e">url&lt;/span>: &lt;span style="color:#66d9ef">url&lt;/span>,
        &lt;span style="color:#a6e22e">show&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
    };
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you can see, our image collection has 2 properties:  &lt;code>URL&lt;/code> and &lt;code>show&lt;/code> properties. The show property determines whether the image will be displayed. When the image comes into view, then we will toggle the show property to true and then the image shall be loaded. Inside our template, we will loop through the image collection. Then we shall use &lt;code>deferLoad&lt;/code> directive from the &lt;code>ng-defer-load&lt;/code> library to check whether the image is in view. If in view, it shall set the show property to true and hence display the image.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let image of imageCollection&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">deferLoad&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">image&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">show &lt;/span>&lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">true&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;height: 550px;&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">ng-container&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;image.show&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">img&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">src&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">image&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">url&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">width&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100%&amp;#34;&lt;/span> /&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">ng-container&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>To avoid many images being loaded initially, it is important to assign the image container a fixed height.&lt;/em> And that’s it, you are now able to lazy load images instead of preloading all of them initially. &lt;a href="https://youtu.be/ODSJZN7IKys">https://youtu.be/ODSJZN7IKys&lt;/a>&lt;/p>
&lt;h3 id="source-code">Source Code&lt;/h3>
&lt;p>You can get this source code &lt;a href="https://github.com/MainaWycliffe/angular-images-lazy-loading-demo">here&lt;/a>.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>ng-defer-load uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">Intersection Observer&lt;/a> to detect which items are on view. While this is not available on all browsers, it uses poly fills to fallback to scroll detection mechanism, thus ensuring it is compatible with older browsers. Thank you for getting this far on this post, if you enjoyed it, please share it and if I left out something, you can remind me on the comment section below. Here are some more posts on lazy loading and performance optimization of your angular application.&lt;/p>
&lt;ol>
&lt;li>Lazy Loading of &lt;a href="https://codinglatte.com/tech/developers/angular/optimizing-your-angular-app-using-lazy-loading/">Angular Components and Modules&lt;/a>&lt;/li>
&lt;li>Lazy loading of &lt;a href="https://codinglatte.com/tech/developers/angular/lazy-loading-scripts-and-styles-angular/">Styles and Scripts&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://codinglatte.com/tech/developers/angular/introduction-to-progressive-web-apps/">Introduction to Progressive Web Apps&lt;/a>&lt;/li>
&lt;/ol></description></item><item><title>Options for Deploying Angular Apps</title><link>https://codinglatte.com/posts/angular/options-deploying-angular-apps/</link><pubDate>Fri, 10 Aug 2018 21:40:25 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/options-deploying-angular-apps/</guid><description>&lt;p>We all develop application so that other people can use them, it’s not different for Angular apps. In this post, I will focus on options for deploying angular apps. This guide is applicable to almost all JavaScript Frameworks – with a few modifications.&lt;/p>
&lt;h3 id="using-a-content-delivery-network">Using a Content Delivery Network&lt;/h3>
&lt;p>This is one option that I really like and happens to be the simplest and the cheapest. Content Delivery Network (CDNs) are geographically distributed network of proxy servers. When a customer wants to access your app, they are served from the server that is closest to them.&lt;/p>
&lt;p>This in turn ensures high performance and availability. CDNs are traditionally used to serve static content (JS, CSS etc.) that requires little to no processing on the server. And as you probably already know, most JavaScript applications are executed on the browser – Ignore server-side JavaScript engines like NodeJS.&lt;/p>
&lt;p>This brings the advantages of a CDN to your Angular application – high availability and performance. Another thing that makes this even more attractive is low cost. There are a few things you lose out when you use this option. The first is lack of configurability – while some CDNs may be versatile, you lack the ability to control what software are running on the server.&lt;/p>
&lt;p>Also, even on those Softwares running on the server, you have limited configuration control. This is especially apparent when dealing with Search Engine Optimization. You can’t redirect traffic from search engine bots to search engine friendly content or even do server-side rendering. If find this option suitable for applications behind a login wall where SEO will not offer any benefits.&lt;/p>
&lt;h3 id="using-shared-hosting">Using Shared Hosting&lt;/h3>
&lt;p>Shared hosting provide a cheap option for hosting websites while providing some degree of configurability. Majority of them offer a control panel to manage and configure your account but you are mainly limited to a LAMP server.&lt;/p>
&lt;p>The freedom provided by shared hosting is enough for most small application, especially given the low prices. You can use services such as &lt;a href="https://prerender.io/">prerender.io&lt;/a> for &lt;a href="https://codinglatte.com/tech/developers/angular/search-engine-optimization-angular/">Search Engine Optimization&lt;/a> (SEO) and in future Angular Universal might support php for &lt;a href="https://angular.io/guide/universal">Server Side Rendering&lt;/a> (SSR). But for now, only a few languages are supported.&lt;/p>
&lt;p>There are hacks to spawn a NodeJS server on a LAMP shared hosting, such as &lt;a href="https://github.com/niutech/node.php">this&lt;/a>, which will setup a NodeJS server and proxy all requests to it. Deployment is a matter of building your angular project and uploading build artefacts to the root of your domain or subdomain. After that, all you need is to configure apache so that all routes fall back to index.html inside the htaccess.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">RewriteEngine On
    # If an existing asset or directory is requested go to it as it is
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
    RewriteRule ^ - [L]
    # If the requested resource doesn&amp;#39;t exist, use index.html
RewriteRule ^ /index.html
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For more information about configuration for different servers environments, please check the information provided &lt;a href="https://angular.io/guide/deployment#routed-apps-must-fallback-to-indexhtml">here&lt;/a>.&lt;/p>
&lt;h3 id="using-a-dedicated-hosting">Using a Dedicated Hosting&lt;/h3>
&lt;p>If you are not happy with shared hosting, you should consider dedicated hosting. In this case you lease a server where you have full control of everything that runs on the sever. The cost is very high for dedicated hosting as compared to shared hosting.&lt;/p>
&lt;p>On the up side, you can host more than one app as long as you are aware of your servers’ limitation. For an angular application, this means not having to deal with the limitation of the other two hosting options. Your app can have full support for SEO and all advantages that come with Angular Universal/Server-Side Rendering (SSR). You can think of this as having your own server.&lt;/p>
&lt;h3 id="using-cloud-hosting-and-cloud-platforms">Using Cloud Hosting and Cloud Platforms&lt;/h3>
&lt;p>Cloud hosting is one of the best options for hosting your angular application or any other application for that matter. It offers most, if not all advantages of a dedicated hosting plus a few other advantages.&lt;/p>
&lt;p>One key advantage is scaling on demand, pay as you go model (pay for only what you use) and pricing per second or hour. Cloud heavy weights such as &lt;a href="https://aws.amazon.com/">Amazon Web Service&lt;/a> (AWS), &lt;a href="https://cloud.google.com/">Google Cloud Platform&lt;/a> and &lt;a href="https://azure.microsoft.com/en-us/">Microsoft Azure&lt;/a> offer a range of hosting and cloud services.&lt;/p>
&lt;p>The services include storage options, content delivery networks (CDNs), machine learning etc. AWS offers a 1-year &lt;a href="https://aws.amazon.com/free/">free tier&lt;/a> while Google Cloud Platform and Microsoft Azure have a combination of free platform credit and free tier or both. One of my favorite platforms is &lt;a href="https://firebase.google.com/">Google Firebase&lt;/a>, which offers a free tier for a small application to run without incurring any cost which is great for development and startups.&lt;/p>
&lt;p>On top of that, Google Firebase offers backend solutions such as Authentication, Storage and Database for you. This allows you to rapidly develop and deploy your application using world class infrastructure, that can scale on demand.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>As you can see, there are several options to consider when deploying your angular application. Each is suitable depending on what you want to achieve. For instance, if you are looking to host a simple demo, the first two options are great and won’t cost you a lot.&lt;/p>
&lt;p>On the other hand,  if you are looking to deploy an application with high demand, the cloud hosting might be your best bet. If I skipped any option, I would love to hear your input on the comment section below.&lt;/p></description></item><item><title>How to Build a Custom Form Control in Angular</title><link>https://codinglatte.com/posts/angular/angular-build-custom-form-control/</link><pubDate>Fri, 10 Aug 2018 12:21:59 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-build-custom-form-control/</guid><description>&lt;p>As a developer, sometimes you are required to take some inputs from a form control and do some preprocessing before submitting – commonly on the submit function. A good example of this is a phone number, where you take a country code and phone number and combine them into a complete phone number before saving. While this might work when you need to use it once or twice in your application, if you use it more than once, then a custom form control might be your best bet. A custom form control will behave just like a normal form control and will return your complete phone number.&lt;/p>
&lt;h3 id="introduction">Introduction&lt;/h3>
&lt;p>To build a custom form control, we are going to be using &lt;a href="https://angular.io/api/forms/ControlValueAccessor">ControlValueAccessor&lt;/a>, this is a bridge between native elements like inputs, text area and angular forms API. In simple, it allows component to behave like an input form control. Allowing you to set value and get value from it. This allows you to create complex and powerful form controls which can be reused across your application. This also allows you to use form validators to validate the output of your custom form controls quite easily if you wish to.&lt;/p>
&lt;p>You can also build them as &lt;a href="https://codinglatte.com/tech/developers/angular/building-angular-6-libraries/">libraries&lt;/a> and use them across multiple application, this greatly improves your development experience. &lt;a href="https://codinglatte.com/tech/developers/angular/angular-development-tips/">Here&lt;/a> are some more &lt;a href="https://codinglatte.com/tech/developers/angular/angular-development-tips/">tips&lt;/a> on how you can improve your &lt;a href="https://codinglatte.com/tech/developers/angular/angular-development-tips/">development experience&lt;/a>.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>In this post, we are just going to use the &lt;code>FormsModule&lt;/code> and &lt;code>ReactiveFormsModule&lt;/code>. Since am a huge fan of Angular Material and Angular Flex Layout, am going to use them for the demo, but those can easily be substituted with bootstrap or any other &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">UI Framework&lt;/a>. This post assumes that you have at least the basics of Angular. In this demo, we are going to look at a very basic example.&lt;/p>
&lt;p>We are going to create a simple custom form control that lets users enter their email address in two parts: their username and their email provider domain name. Our custom form control will return the two as a single email address. This will allow us to use built-in validators on. It will also accept a default value as a single email. And then it will separate the email into the username and provider. The it will automatically assign it to the correct input boxes. Without further ado.&lt;/p>
&lt;h3 id="creating-our-component">Creating our Component&lt;/h3>
&lt;p>We will start by creating a normal component using Angular CLI: ng generate component email-address-input Then, we need to implement &lt;code>ControlValueAccessor&lt;/code> in our component:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">EmailAddressInputComponent&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">ControlValueAccessor&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then add a provider for the &lt;code>ControlValueAccessor&lt;/code> we just created:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">NG_VALUE_ACCESSOR&lt;/span>,
&lt;span style="color:#a6e22e">useExisting&lt;/span>: &lt;span style="color:#66d9ef">forwardRef&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">EmailAddressInputComponent&lt;/span>),
&lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
}
];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to add the necessary methods for a class implementing &lt;code>ControlValueAccessor&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">interface&lt;/span> &lt;span style="color:#a6e22e">ControlValueAccessor&lt;/span> {
&lt;span style="color:#a6e22e">writeValue&lt;/span>(&lt;span style="color:#a6e22e">obj&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>
&lt;span style="color:#a6e22e">registerOnChange&lt;/span>(&lt;span style="color:#a6e22e">fn&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>
&lt;span style="color:#a6e22e">registerOnTouched&lt;/span>(&lt;span style="color:#a6e22e">fn&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>
&lt;span style="color:#a6e22e">setDisabledState&lt;/span>(&lt;span style="color:#a6e22e">isDisabled&lt;/span>: &lt;span style="color:#66d9ef">boolean&lt;/span>)&lt;span style="color:#f92672">?:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about the above methods &lt;a href="https://angular.io/api/forms/ControlValueAccessor">here&lt;/a>: On top of the above methods, we need to add set and get methods to set and get the value of our component. This will allow us to read and set the email value easily, including separating it into the username and provider. So,  in our component, we will start by adding 3 properties – &lt;code>username&lt;/code>, &lt;code>emailProvider&lt;/code> and &lt;code>_value&lt;/code> (&lt;strong>&lt;em>note the underscore&lt;/em>&lt;/strong>).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">username&lt;/span>;
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">emailProvider&lt;/span>;
&lt;span style="color:#a6e22e">_value&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, add the methods necessary to implement &lt;code>ControlValueAccessor&lt;/code>: First, add the &lt;code>writeValue&lt;/code> method. It will pass the default value and set it to the &lt;code>_value&lt;/code> property of the field.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">writeValue&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) {
  &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#66d9ef">undefined&lt;/span>) {
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>;
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>);
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we add the other methods to implement &lt;code>ControlValueAccessor&lt;/code> for our component:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">propagateChange&lt;/span> &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#a6e22e">_&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {};
&lt;span style="color:#a6e22e">registerOnChange&lt;/span>(&lt;span style="color:#a6e22e">fn&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">fn&lt;/span>;
}
&lt;span style="color:#a6e22e">registerOnTouched() {&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we are going to add on change event method. This will update the value of our component when you type your username and email provider. The method will concatenate the username and email Provider into an email address. The method will be triggered by the input change event of either the emailProvider or username input fields. You can use any other event depending on what you want to achieve.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">addEvent&lt;/span>(&lt;span style="color:#a6e22e">$event&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">username&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@&amp;#39;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">emailProvider&lt;/span>;
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, we add set and get methods to get and set the value of our &lt;code>_value&lt;/code> property:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">get&lt;/span> &lt;span style="color:#a6e22e">value() {&lt;/span>
    &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">email&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_value&lt;/span>;
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">email&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The set value property will take the input email address and split it into both the username and email provider and assign to respective property – &lt;code>username&lt;/code> and &lt;code>emailProvider&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">set&lt;/span> &lt;span style="color:#a6e22e">value&lt;/span>(&lt;span style="color:#a6e22e">val&lt;/span>) {
    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">val&lt;/span>) {
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_value&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">val&lt;/span>;
      [&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">username&lt;/span>, &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">emailProvider&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">val&lt;/span>.&lt;span style="color:#a6e22e">split&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;@&amp;#39;&lt;/span>);
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_value&lt;/span>);
    }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we create our template:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayoutGap&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;10px&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;padding: 10px&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-form-field&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span>
&lt;span style="color:#a6e22e">matInput&lt;/span>
&lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">change&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">addEvent&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[(&lt;/span>&lt;span style="color:#a6e22e">ngModel&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">username&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">username&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Username&amp;#34;&lt;/span>
/&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-form-field&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-form-field&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span>
&lt;span style="color:#a6e22e">matInput&lt;/span>
&lt;span style="color:#a6e22e">type&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">change&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">addEvent&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[(&lt;/span>&lt;span style="color:#a6e22e">ngModel&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">emailProvider&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">emailProvider&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Email Provider&amp;#34;&lt;/span>
/&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-form-field&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: We are using &lt;code>ngModel&lt;/code> for two-way binding between the template and the component class.&lt;/p>
&lt;/blockquote>
&lt;h3 id="using-our-custom-form-control">Using our Custom Form Control&lt;/h3>
&lt;p>Since now we have our custom form control, we can use it as a normal application. First, we are going to create a formGroup for our custom form:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">formGroup&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({
&lt;span style="color:#a6e22e">email&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>, [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>]],
&lt;span style="color:#a6e22e">email2&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;@codinglatte.com&amp;#39;&lt;/span>, [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>]],
&lt;span style="color:#a6e22e">email3&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;hello&amp;#39;&lt;/span>, [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>]],
&lt;span style="color:#a6e22e">email4&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, [&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>]]
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you can see, we are able to pass default value to our custom form control and use built-in and even &lt;a href="https://codinglatte.com/tech/developers/angular/angular-building-custom-validators/">custom validators&lt;/a> just like normal form control. And using it in our template is the same:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">form&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">formGroup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">formGroup&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-email-address-input&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-email-address-input&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;formGroup.controls[&amp;#39;email&amp;#39;].hasError(&amp;#39;email&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;Your email is invalid email&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>
&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-email-address-input&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email2&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-email-address-input&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;formGroup.controls[&amp;#39;email2&amp;#39;].hasError(&amp;#39;email&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;Your email is invalid email&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>
&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-email-address-input&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email3&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-email-address-input&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;formGroup.controls[&amp;#39;email3&amp;#39;].hasError(&amp;#39;email&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;Your email is invalid email&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>
&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-email-address-input&lt;/span> &lt;span style="color:#a6e22e">formControlName&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;email4&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-email-address-input&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;formGroup.controls[&amp;#39;email3&amp;#39;].hasError(&amp;#39;email&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;Your email is invalid email&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>
&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">form&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>TIP:&lt;/strong> If you are using lazy loading, you can create a module where you declare and export all Pipes and Components that are being used across multiple lazy loaded modules.&lt;/p>
&lt;/blockquote>
&lt;h3 id="where-is-this-code">Where is this Code?&lt;/h3>
&lt;p>The above source code be found on Github repository &lt;a href="https://github.com/MainaWycliffe/angular-building-custom-form-control-demo">here&lt;/a>.&lt;/p></description></item><item><title>Angular Reactive Forms – Building Custom Validators</title><link>https://codinglatte.com/posts/angular/angular-building-custom-validators/</link><pubDate>Wed, 08 Aug 2018 16:17:18 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-building-custom-validators/</guid><description>&lt;p>Angular has built-in input validators for common input validation such as checking min and max length, email etc.  These built-in validators can only take you so far, at some point you might need to build a custom validator. In this post, I will show you how to build your own custom validators for input and a validator to check whether password and confirm password match before submitting. This will help you be able to build custom validators for both form group and specific form controls. So, without further ado, lets get started:&lt;/p>
&lt;h3 id="how-it-will-work">How it will work&lt;/h3>
&lt;p>I am going to assume that you have some prior knowledge on Reactive Forms in Angular and using built-in validators. If not, please checkout this &lt;a href="https://angular.io/guide/reactive-forms">page&lt;/a> for a quick tutorial on Reactive Forms. We are going to have three custom validators. The first validator will check whether the current user is over the age of 18 and under the Age of 60. While the second validator will check whether the email provider is theinfogrid.com (this blogs domain name). The last validator will check to see the password and confirm password are a match.&lt;/p>
&lt;h3 id="building-a-custom-validator">Building a Custom Validator&lt;/h3>
&lt;p>We are going to create a class known as CustomValidators, which will house our validator functions. This will allow us to access all our validator functions under a single class.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng generate class custom-validator
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to first create validators for the first two cases – &lt;code>AgeLimit&lt;/code> and &lt;code>EmailDomain&lt;/code> Validators. We are going to add the methods as static methods inside our &lt;code>CustomValidator&lt;/code> class. The names of our validator classes shall have the term Validator appended. So that, &lt;code>AgeLimit&lt;/code> becomes &lt;code>AgeLimitValidator&lt;/code> and &lt;code>EmailDomain&lt;/code> becomes &lt;code>EmailDomainValidator&lt;/code>. Each of our two methods will return a Validator Function (&lt;code>ValidatorFN&lt;/code>) after evaluating whether the control value is valid or not. In case where the value is valid, the validator function shall return a null value and an object if invalid. The object shall have a name and a true value i.e.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">{ &lt;span style="color:#a6e22e">ageLimit&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>  } &lt;span style="color:#a6e22e">or&lt;/span>  { &lt;span style="color:#a6e22e">emailDomain&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> }
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="agelimitvalidator-function">AgeLimitValidator Function&lt;/h4>
&lt;p>The first validator – &lt;code>AgeLimitValidator&lt;/code> – shall look like this:&lt;/p>
&lt;blockquote>
&lt;p>NB: Follow the comments inside the code for further clarifications.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">ageLimitValidator&lt;/span>(&lt;span style="color:#a6e22e">minAge&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span>, &lt;span style="color:#a6e22e">maxAge&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">ValidatorFn&lt;/span> {
    &lt;span style="color:#66d9ef">return&lt;/span> (&lt;span style="color:#a6e22e">control&lt;/span>: &lt;span style="color:#66d9ef">AbstractControl&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> { [&lt;span style="color:#a6e22e">key&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span> } &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
      &lt;span style="color:#75715e">// if control value is not null and is a number
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>) {
        &lt;span style="color:#75715e">// return null  if it&amp;#39;s in between the minAge and maxAge and is A valid Number
&lt;/span>&lt;span style="color:#75715e">&lt;/span>        &lt;span style="color:#66d9ef">return&lt;/span> isNaN(&lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>) &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#75715e">// checks if its a valid number
&lt;/span>&lt;span style="color:#75715e">&lt;/span>        &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#a6e22e">minAge&lt;/span> &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#75715e">// checks if its below the minimum age
&lt;/span>&lt;span style="color:#75715e">&lt;/span>          &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">maxAge&lt;/span> &lt;span style="color:#75715e">// checks if its above the maximum age
&lt;/span>&lt;span style="color:#75715e">&lt;/span>          &lt;span style="color:#f92672">?&lt;/span> { &lt;span style="color:#a6e22e">ageLimit&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> } &lt;span style="color:#75715e">// return this incase of error
&lt;/span>&lt;span style="color:#75715e">&lt;/span>          &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>; &lt;span style="color:#75715e">// there was not error
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      }
      &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
    };
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>It takes in the minimum and maximum age as parameters and uses them to evaluate age limit.&lt;/p>
&lt;h4 id="emaildomainvalidator-function">EmailDomainValidator Function&lt;/h4>
&lt;p>The second validator – &lt;code>EmailDomainValidator&lt;/code> – function shall look like this:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Follow the comments inside the code for further clarifications.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">emailDomainValidator&lt;/span>(&lt;span style="color:#a6e22e">domain&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">ValidatorFn&lt;/span> {
    &lt;span style="color:#66d9ef">return&lt;/span> (&lt;span style="color:#a6e22e">control&lt;/span>: &lt;span style="color:#66d9ef">AbstractControl&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> { [&lt;span style="color:#a6e22e">key&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span> } &lt;span style="color:#f92672">|&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
      &lt;span style="color:#75715e">// if control value is not undefined, then check if the domain name is valid
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>) {
        &lt;span style="color:#66d9ef">const&lt;/span> [&lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">eDomain&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>.&lt;span style="color:#a6e22e">split&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;@&amp;#39;&lt;/span>); &lt;span style="color:#75715e">// split the email address to get the domain name
&lt;/span>&lt;span style="color:#75715e">&lt;/span>        &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">eDomain&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#a6e22e">domain&lt;/span> &lt;span style="color:#75715e">// check if the domain name matches the one inside the email address
&lt;/span>&lt;span style="color:#75715e">&lt;/span>          &lt;span style="color:#f92672">?&lt;/span> { &lt;span style="color:#a6e22e">emailDomain&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> } &lt;span style="color:#75715e">// return in case there is not match
&lt;/span>&lt;span style="color:#75715e">&lt;/span>          &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>; &lt;span style="color:#75715e">// return null if there is a match
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      }
      &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>; &lt;span style="color:#75715e">// no error, since there was no input
&lt;/span>&lt;span style="color:#75715e">&lt;/span>   };
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="using-the-custom-validators">Using the Custom Validators&lt;/h3>
&lt;p>To use your custom validator inside your reactive forms, import the class and call the validator function as you would a built-in validator.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">createMyForm&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">FormGroup&lt;/span> {
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>({
      ...
      &lt;span style="color:#a6e22e">age&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
        &lt;span style="color:#66d9ef">null&lt;/span>,
        &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">CustomValidator&lt;/span>.&lt;span style="color:#a6e22e">ageLimitValidator&lt;/span>(&lt;span style="color:#ae81ff">18&lt;/span>, &lt;span style="color:#ae81ff">60&lt;/span>)])
      ],
      &lt;span style="color:#a6e22e">email&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
        &lt;span style="color:#66d9ef">null&lt;/span>,
        &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([
          &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">email&lt;/span>,
          &lt;span style="color:#a6e22e">CustomValidator&lt;/span>.&lt;span style="color:#a6e22e">emailDomainValidator&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;theinfogrid.com&amp;#39;&lt;/span>)
        ])
      ],
     ...
    });
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you can see above, you can easily mix your custom validators and built-in validators. Now, inside your template, it’s a matter of checking whether that form control has the specific error and show the error message:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">//For Age Limit Validator
&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;myform.controls[&amp;#39;age&amp;#39;].touched &amp;amp;&amp;amp; myform.controls[&amp;#39;age&amp;#39;].hasError(&amp;#39;ageLimit&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
The age limit is between 18 and 60 years!
&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>&amp;gt;
//For Email Domain Validator
&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;myform.controls[&amp;#39;email&amp;#39;].touched &amp;amp;&amp;amp; myform.controls[&amp;#39;email&amp;#39;].hasError(&amp;#39;emailDomain&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
Email address must be from theinfogrid.com
&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it, we now have a custom validator for our form controls.&lt;/p>
&lt;h3 id="custom-validators-for-forms">Custom Validators for Forms&lt;/h3>
&lt;p>The first two validators are for individual controls. What about if you wanted to validate something that involved more than one control. Like, checking whether password and confirmation passwords are a match. Here we will need a validator for our form group instead of individual form controls. Inside our &lt;code>CustomValidator&lt;/code> class, let’s add a third validator method for checking whether password match – &lt;code>PasswordMatch&lt;/code> – we will call it &lt;code>PasswordMatchValidator&lt;/code>. Then we are going to get the &lt;em>password&lt;/em> and &lt;code>confirmPassword&lt;/code> values from our form and check if they match. Instead of returning a validator function like in the previous two instances, we will instead set an error in our form control for both &lt;em>password&lt;/em> and &lt;em>confirmPassword&lt;/em>. So, our new validator method will look like this:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> &lt;em>Follow the comments inside the code for further clarifications&lt;/em>.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">passwordMatchValidator&lt;/span>(&lt;span style="color:#a6e22e">control&lt;/span>: &lt;span style="color:#66d9ef">AbstractControl&lt;/span>) {
    &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">password&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;password&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">value&lt;/span>; &lt;span style="color:#75715e">// get password from our password form control
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">confirmPassword&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;confirmPassword&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">value&lt;/span>; &lt;span style="color:#75715e">// get password from our confirmPassword form control
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#75715e">// compare is the password math
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">password&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#a6e22e">confirmPassword&lt;/span>) {
      &lt;span style="color:#75715e">// if they don&amp;#39;t match, set an error in our confirmPassword form control
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#a6e22e">control&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;confirmPassword&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">setErrors&lt;/span>({ &lt;span style="color:#a6e22e">NoPassswordMatch&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span> });
    }
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After that, we can add it to the list of our validators of the form group, not the control validators:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-typescript" data-lang="typescript">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">fb&lt;/span>.&lt;span style="color:#a6e22e">group&lt;/span>(
{
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">password&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])],
&lt;span style="color:#a6e22e">confirmPassword&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">compose&lt;/span>([&lt;span style="color:#a6e22e">Validators&lt;/span>.&lt;span style="color:#a6e22e">required&lt;/span>])]
},
{
&lt;span style="color:#75715e">// our validator for the form group
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">validator&lt;/span>: &lt;span style="color:#66d9ef">CustomValidator.passwordMatchValidator&lt;/span>
}
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then you can add the error message in your &lt;em>confirmPassword&lt;/em> form control as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-error&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;myform.controls[&amp;#39;confirmPassword&amp;#39;].touched &amp;amp;&amp;amp; myform.controls[&amp;#39;confirmPassword&amp;#39;].hasError(&amp;#39;NoPassswordMatch&amp;#39;)&amp;#34;&lt;/span>
&amp;gt;
Your password and confirm password do not match
&amp;lt;/&lt;span style="color:#f92672">mat-error&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>I hope this post will enable you to create your own custom validators for your own form. You can find the full code on &lt;a href="https://github.com/MainaWycliffe/angular-custom-validators-demo">Github&lt;/a>.&lt;/p></description></item><item><title>SVG/Webfont Icon Packs for your Angular App</title><link>https://codinglatte.com/posts/angular/svg-webfont-icon-packs/</link><pubDate>Mon, 06 Aug 2018 18:56:37 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/svg-webfont-icon-packs/</guid><description>&lt;p>If you are looking to improve your web app both visually and functionally, icons are a very good place to start. Icons if applied correctly, are easily recognized by users and therefore can substitute long text. This enables developers to utilize the screen real estate wisely especially on small devices.&lt;/p>
&lt;p>For instance, if a user sees a hamburger icon, they will recognize it as the menu icon, eliminating the need to also add the word menu next to it. On top of that, they improve the visual appeal of a website and serve as a guide for users when navigating the site. Icons are shipped mainly as Web Fonts and SVG (&lt;a href="https://www.w3.org/TR/SVG2/">Scalable Vector Graphics&lt;/a>).&lt;/p>
&lt;p>This provides an easy to use icons for web developers that can be resized, and effects applied on the fly easily. With Angular Material, you can use different icon packs with Angular Material Icon &lt;a href="https://material.angular.io/components/icon/overview">Component&lt;/a>, you can learn more about how to integrate different icon packs &lt;a href="https://codinglatte.com/tech/developers/angular/material-icons-angular-5/">here&lt;/a>.&lt;/p>
&lt;h3 id="material-icons">Material Icons&lt;/h3>
&lt;p>This is a set of over 900 Icons which are free to use on your smartphones, desktops and web applications. They are provided as both SVG Icons and Web fonts formats. With the SVG Icons, you can select individually the icons you need from the Material Icons &lt;a href="https://github.com/google/material-design-icons">Repository&lt;/a>. On top of that, they can be installed using &lt;a href="https://www.npmjs.com/package/material-design-icons">NPM&lt;/a> and Bower.&lt;/p>
&lt;p>The one downside of this icon pack is lack of social media icons. If you are looking for social icons to fill this gap, there is &lt;a href="https://github.com/simple-icons/simple-icons">this&lt;/a> GitHub repository which has SVG Icons for all major brands.&lt;/p>
&lt;p>You can browse the vast icon library &lt;a href="https://material.io/tools/icons/">here&lt;/a> and learn how to install and use Material Icons &lt;a href="https://google.github.io/material-design-icons/">here&lt;/a>.&lt;/p>
&lt;h3 id="font-awesome">Font Awesome&lt;/h3>
&lt;p>This is one of the most popular and comprehensive icon packs out there. There are available as both web fonts and SVG Icons and unlike Material Icons, they have social icons. While they offer free icons, 1295 icons, they have a pro &lt;a href="https://fontawesome.com/pricing">license&lt;/a> offering over 3000 icons. On top of that, a component for &lt;a href="https://fontawesome.com/how-to-use/on-the-web/using-with/angular">Angular&lt;/a> is provided together with other popular &lt;a href="https://fontawesome.com/how-to-use/on-the-web/setup/getting-started?using=web-fonts-with-css">flameworks&lt;/a>.&lt;/p>
&lt;p>You can learn more about Font Awesome &lt;a href="https://fontawesome.com/">here&lt;/a>. Glyphicons Another web font/SVG icons with over 1000 icons. You can use these icons in your web app, mobile apps and desktop applications. They have a free license for the icons with about 800 icons but if you want the whole set, you will need to shell out either $25 or $59 with future updates included. You can learn more about the licensing options for the icons &lt;a href="http://glyphicons.com/license/">here&lt;/a>.&lt;/p>
&lt;p>You can learn more about Glyphicons &lt;a href="http://glyphicons.com/">here&lt;/a>.&lt;/p>
&lt;h3 id="clarity-icons">Clarity Icons&lt;/h3>
&lt;p>&lt;a href="https://vmware.github.io/clarity/">Clarity Design System&lt;/a> is a set of UX guidelines, HTML/CSS framework, and Angular components working together to craft exceptional experiences. I covered Clarity Design System in a  previous post, UI Libraries and Frameworks for Angular 6, &lt;a href="https://codinglatte.com/tech/developers/angular/ui-libraries-and-frameworks-for-angular-6/">here&lt;/a>. You can browse the vast icon library &lt;a href="https://vmware.github.io/clarity/icons/icon-sets#core-shapes">here&lt;/a>. They cover all major categories imaginable like technology, social, ecommerce etc.&lt;/p>
&lt;p>You can learn how to get started with Clarity Icons &lt;a href="https://vmware.github.io/clarity/icons/clarity-icons">here&lt;/a>.&lt;/p>
&lt;h3 id="fontello">Fontello&lt;/h3>
&lt;p>This is more of a tool than an icon pack, but I had to add this to the list. This tool packs vector icons from multiple sources into a single usable web font. This gives you important ability of combining icons from multiple source into one icon pack for your own use.&lt;/p>
&lt;p>To quote the authors: “it is like Twitter Bootstrap, but for images and icons.” This gives you the freedom to be picky of icons to include, allowing you to reduce the Web Front footprint and have icons of your choice.&lt;/p>
&lt;p>If you are interested, you can visit the official website &lt;a href="http://fontello.com/">here&lt;/a> or their wiki &lt;a href="https://github.com/fontello/fontello/wiki/Help">here&lt;/a>.&lt;/p>
&lt;p>There are other icons pack that I haven’t worked with before but are worth considering. This include:&lt;/p>
&lt;ol>
&lt;li>&lt;a href="http://pictos.cc/classic/font/">Pictos&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://s-ings.com/typicons/">Typicons&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://pictonic.co/">Pictonic&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://octicons.github.com/">Octicons&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/iconic/open-iconic">Useicons&lt;/a>&lt;/li>
&lt;/ol></description></item><item><title>Lazy Loading Scripts and Styles in Angular</title><link>https://codinglatte.com/posts/angular/lazy-loading-scripts-and-styles-angular/</link><pubDate>Sat, 04 Aug 2018 13:39:57 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/lazy-loading-scripts-and-styles-angular/</guid><description>&lt;p>In my earlier &lt;a href="https://codinglatte.com/tech/developers/angular/optimizing-your-angular-app-using-lazy-loading/">post&lt;/a>, I covered about lazy loading of angular modules. In this post, I will cover lazy loading of scripts and styles, both external and local. The goal of this post is to show how you can defer loading of a script or style and load it manually later when you need.&lt;/p>
&lt;p>This also works perfectly with external scripts that if added to the index.html file of your project would have a negative impact on performance. It works well with styles and scripts that are needed for a specific case. One such scenario that spring to mind is handling payment using PayPal.&lt;/p>
&lt;p>In most cases, payment is usually processed only after a customer has order an item not before. In this case, loading PayPal by placing the script tags at the index.html would negatively impact performance while it’s only needed at the last step for payment processing.&lt;/p>
&lt;h3 id="loading-scripts-and-styles-on-demand">Loading Scripts and Styles on Demand&lt;/h3>
&lt;p>You will most like be loading the scripts in a component. To load the style or script, we are going to use &lt;a href="https://www.w3schools.com/jsref/met_document_createelement.asp">&lt;code>document.CreateElement&lt;/code>&lt;/a> method to add a new script/style element.&lt;/p>
&lt;p>For the script, we will create new scripts tags with the source pointing to our script URL. For the style,  we will create new link element in the header, with HREF to our style URL.&lt;/p>
&lt;p>To load our script, we begin by creating a new method loadExternalScript(scriptURL),  which will return a promise. A promise will make it easier to ensure that we will use our script after it has been loaded successfully and not before.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>(&lt;span style="color:#a6e22e">resolve&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">scriptElement&lt;/span> &lt;span style="color:#f92672">=&lt;/span> document.&lt;span style="color:#a6e22e">createElement&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;script&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">scriptElement&lt;/span>.&lt;span style="color:#a6e22e">src&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">scriptUrl&lt;/span>;
&lt;span style="color:#a6e22e">scriptElement&lt;/span>.&lt;span style="color:#a6e22e">onload&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">resolve&lt;/span>;
document.&lt;span style="color:#a6e22e">body&lt;/span>.&lt;span style="color:#a6e22e">appendChild&lt;/span>(&lt;span style="color:#a6e22e">scriptElement&lt;/span>);
});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The same goes for our style, where we will create a new method and then return a promise:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">loadExternalStyles&lt;/span>(&lt;span style="color:#a6e22e">styleUrl&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Promise&lt;/span>((&lt;span style="color:#a6e22e">resolve&lt;/span>, &lt;span style="color:#a6e22e">reject&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">styleElement&lt;/span> &lt;span style="color:#f92672">=&lt;/span> document.&lt;span style="color:#a6e22e">createElement&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;link&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">styleElement&lt;/span>.&lt;span style="color:#a6e22e">href&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">styleUrl&lt;/span>;
&lt;span style="color:#a6e22e">styleElement&lt;/span>.&lt;span style="color:#a6e22e">onload&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">resolve&lt;/span>;
document.&lt;span style="color:#a6e22e">head&lt;/span>.&lt;span style="color:#a6e22e">appendChild&lt;/span>(&lt;span style="color:#a6e22e">styleElement&lt;/span>);
});
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can wrap the above two methods in a class or service if you wish. It will make it easier to reuse the methods all over your class easily. Then, call the methods to load the scripts/style as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">loadExternalScript&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;url/to/your/scripts&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {}).&lt;span style="color:#66d9ef">catch&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {});
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">loadExternalStyles&lt;/span>(&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">url&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">to&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">your&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">styles&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {}).&lt;span style="color:#66d9ef">catch&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {});
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it. You can now load styles/scripts on demand and not before. In the next step, I am going to cover how to lazy load local scripts.&lt;/p>
&lt;h3 id="lazy-loading-localinternal-scripts-and-styles">Lazy Loading Local/Internal Scripts and Styles&lt;/h3>
&lt;p>When Angular CLI is building your application, all the styles and scripts added to the angular.json file are automatically added to the index.html, meaning they will be preloaded before rendering.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;architect&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {  
&lt;span style="color:#f92672">&amp;#34;build&amp;#34;&lt;/span>: {
    &lt;span style="color:#f92672">&amp;#34;builder&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;@angular-devkit/build-angular:browser&amp;#34;&lt;/span>,
    &lt;span style="color:#f92672">&amp;#34;options&amp;#34;&lt;/span>: {
      &lt;span style="color:#f92672">&amp;#34;styles&amp;#34;&lt;/span>: [
        &lt;span style="color:#e6db74">&amp;#34;src/styles.css&amp;#34;&lt;/span>
      ],
      &lt;span style="color:#f92672">&amp;#34;scripts&amp;#34;&lt;/span>: [
        &lt;span style="color:#e6db74">&amp;#34;src/some-script.js&amp;#34;&lt;/span>
      ],
      &lt;span style="color:#960050;background-color:#1e0010">//...&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To avoid this, you can specify that a specific script/style is to be lazy loaded and angular will just output a bundle and won’t add it to the index.html. You do this by specifying the script/style in object format, instead of a simple string as shown above. The object formats allows you to provide more information to the CLI about how to handle a specific style sheet or script. This information includes the output name, whether to lazy load and the source of the style/script.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>:&lt;span style="color:#e6db74">&amp;#34;path/to/your/lazy-script.js&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;lazy&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;bundleName&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;lazy-loaded-script&amp;#34;&lt;/span>
}&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You also must specify the output name (bundleName) to be able to reference to it later. If you don’t, Angular CLI will randomly generate a bundle name, which will change on each build.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;scripts&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
  &lt;span style="color:#e6db74">&amp;#34;src/some-script.js&amp;#34;&lt;/span>,
  {
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;path/to/your/lazy-script.js&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;lazy&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;bundleName&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;lazy-loaded-script&amp;#34;&lt;/span>
  },
]&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span>
[
  &lt;span style="color:#e6db74">&amp;#34;src/some-styles.css&amp;#34;&lt;/span>,
  {
&lt;span style="color:#f92672">&amp;#34;input&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;path/to/your/lazy-style.css&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;lazy&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;bundleName&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;lazy-loaded-style&amp;#34;&lt;/span>
  },
]&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Working with Environment Variables in Angular 6</title><link>https://codinglatte.com/posts/angular/environment-variables-angular/</link><pubDate>Thu, 02 Aug 2018 09:21:54 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/environment-variables-angular/</guid><description>&lt;p>It’s common for developers to have multiple application versions that target different environments i.e. development and production. It’s common that each environment will have some unique environment variables i.e. API Endpoint, app version etc. Angular provides environment configurations to declare variables unique for each environment.&lt;/p>
&lt;p>Ideally, you want to automatically apply a flag, let’s say &lt;code>--prod&lt;/code>, and the angular compiler replaces the API endpoint variable with the production API endpoint for you. What you don’t want is to manually change the endpoint before building your app. This increases the chance you will make a mistake that might break your app or worse.&lt;/p>
&lt;h2 id="dealing-with-only-2-environments">Dealing with only 2 Environments&lt;/h2>
&lt;p>By default angular supports two environments – production and environment. The environment files for the two environments can be located under the &lt;code>environment&lt;/code> directory, inside the &lt;code>src&lt;/code> directory at the root of your workspace or project folder. You can learn more about angular workspaces &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">here&lt;/a>. Inside, there are two files – &lt;code>environment.ts&lt;/code> and &lt;code>environment.prod.ts&lt;/code>. As you might have guessed, the second file is the production file while the first one is the dev or default environment. Angular CLI compiler, will automatically replace the first file with the second file each time you build with the &lt;code>--prod&lt;/code> flag.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng build --prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you open the file, the content of the first one will have production set to false while the second one will have production set to true.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// environment.ts environment variables
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
};
&lt;span style="color:#75715e">//environment.prod.ts environment variables
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>All variables which vary based on the environment, should be placed inside these two files appropriately. Check the examples given below for the API Endpoint.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// environment.ts environment variables
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#a6e22e">APIEndpoint&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;https://dev.endpoint.com&amp;#39;&lt;/span>
};
&lt;span style="color:#75715e">// environment.prod.ts environment variables
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#a6e22e">APIEndpoint&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;https://prod.endpoint.com&amp;#39;&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To access the variables, import the environment constant, and then use it as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">environment&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./../environments/environment&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Usage&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">APIEndpoint&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span>.&lt;span style="color:#a6e22e">APIEndpoint&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After that, every time you build your application without the &lt;code>--prod&lt;/code> flag, then it will use the dev(default) API endpoint while when you use the &lt;code>--prod&lt;/code> flag, it will use the production API Endpoint.&lt;/p>
&lt;h2 id="dealing-with-3-or-more-environment">Dealing with 3 or More Environment&lt;/h2>
&lt;p>It’s also common to have more than two environments for your app. You could have, let’s say a staging and beta environments on top of production and dev environment. Angular provides a way to add the extra environments you need manually.&lt;/p>
&lt;p>In our case, we need two extra environments – staging and beta, on top of the default two. We start by adding two more environment files next to our two already in existent. Start by creating two new files – &lt;code>environment.staging.ts&lt;/code> and &lt;code>environment.beta.ts&lt;/code> and then copy the content of the &lt;code>environment.prod.ts&lt;/code> to the two files. Next, change the variables to the appropriate values as per your environment.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// environment.staging.ts environment variables
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
  &lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
  &lt;span style="color:#a6e22e">APIEndpoint&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;https://staging.endpoint.com&amp;#34;&lt;/span>
};
&lt;span style="color:#75715e">// environment.beta.ts environment variables
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">environment&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
  &lt;span style="color:#a6e22e">production&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
  &lt;span style="color:#a6e22e">APIEndpoint&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;https://beta.endpoint.com&amp;#34;&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to make configuration changes to our &lt;code>angular.json&lt;/code> – at the root of our workspace. This will enable Angular CLI to recognize our two new environments and use the new environment files we created in the previous step.&lt;/p>
&lt;p>First, open &lt;code>angular.json&lt;/code> and navigate to the &lt;code>configurations&lt;/code> key (Key map: &lt;code>projects -&amp;gt; yourappname -&amp;gt; architect -&amp;gt; build -&amp;gt; configurations&lt;/code>). By default, there will be only one key – production, with the following setting:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;configurations&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
   &lt;span style="color:#f92672">&amp;#34;production&amp;#34;&lt;/span>: {
       &lt;span style="color:#f92672">&amp;#34;fileReplacements&amp;#34;&lt;/span>: [
           {
              &lt;span style="color:#f92672">&amp;#34;replace&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.ts&amp;#34;&lt;/span>,
               &lt;span style="color:#f92672">&amp;#34;with&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.prod.ts&amp;#34;&lt;/span>
           }
        ],
        &lt;span style="color:#f92672">&amp;#34;optimization&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;outputHashing&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;all&amp;#34;&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;sourceMap&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;extractCss&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;namedChunks&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;aot&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;extractLicenses&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;vendorChunk&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;buildOptimizer&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
        &lt;span style="color:#f92672">&amp;#34;serviceWorker&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
   }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Duplicate the production key and its content, rename the key from production to staging, then on the fileReplacements key of the staging configuration key, replace:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#e6db74">&amp;#34;with&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#e6db74">&amp;#34;src/environments/environment.prod.ts&amp;#34;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>with&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#e6db74">&amp;#34;with&amp;#34;&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#e6db74">&amp;#34;src/environments/environment.staging.ts&amp;#34;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Your new configuration for staging environment should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;configurations&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
   &lt;span style="color:#f92672">&amp;#34;production&amp;#34;&lt;/span>: {
        &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
    },
    &lt;span style="color:#f92672">&amp;#34;staging&amp;#34;&lt;/span>: {
    &lt;span style="color:#f92672">&amp;#34;fileReplacements&amp;#34;&lt;/span>: [
     {
         &lt;span style="color:#f92672">&amp;#34;replace&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.ts&amp;#34;&lt;/span>,
         &lt;span style="color:#f92672">&amp;#34;with&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.staging.ts&amp;#34;&lt;/span>
     }],
     &lt;span style="color:#f92672">&amp;#34;optimization&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;outputHashing&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;all&amp;#34;&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;sourceMap&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;extractCss&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;namedChunks&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;aot&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;extractLicenses&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;vendorChunk&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;buildOptimizer&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
     &lt;span style="color:#f92672">&amp;#34;serviceWorker&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
   }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Repeat the above steps for beta and any extra environments you wish to add.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">
&lt;span style="color:#e6db74">&amp;#34;beta&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> {
&lt;span style="color:#f92672">&amp;#34;fileReplacements&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;replace&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.ts&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;with&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;src/environments/environment.beta.ts&amp;#34;&lt;/span>
}
],
&lt;span style="color:#f92672">&amp;#34;optimization&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;outputHashing&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;all&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sourceMap&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;extractCss&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;namedChunks&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;aot&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;extractLicenses&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;vendorChunk&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;buildOptimizer&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;serviceWorker&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You will need to modify the above settings to closely reflect what you expect on your environment.   For instance, you might want to turn off ServiceWorker on the staging server and leave it on in beta. This will ensure service worker has not cached the app and its resources on the browser when refreshing.&lt;/p>
&lt;/blockquote>
&lt;h2 id="building-your-app">Building your App&lt;/h2>
&lt;p>Finally, to build your application with the new custom environment, use the &amp;ndash;configurations=environment-name flag, as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">//for staging environment
ng build --configuration&lt;span style="color:#f92672">=&lt;/span>staging
//for beta environment
ng build --configuration&lt;span style="color:#f92672">=&lt;/span>beta
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And for the Angular default environment, there isn’t any changes at all to their build commands.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">//for production environment
ng build --prod
//for dev environment
ng build
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it, you can now configure your Angular app with as many environments as you wish.&lt;/p></description></item><item><title>Top VSCode Extensions for Angular Developers</title><link>https://codinglatte.com/posts/angular/top-vscode-extensions-angular/</link><pubDate>Mon, 30 Jul 2018 10:08:14 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/top-vscode-extensions-angular/</guid><description>&lt;p>Since the release of VSCode a few years ago, it has become very popular among developers. VSCode is my favorite text editor and use it every day for almost all my projects. The only exception are projects related to &lt;a href="https://codinglatte.com/tech/machine-learning/100daysofmlcode-join-the-challenge-and-learn-machine-learning/">Machine Learning&lt;/a> where Notebook Style IDEs’ are more suitable.&lt;/p>
&lt;p>In &lt;a href="https://codinglatte.com/tech/developers/angular/angular-development-tips/">my previous post&lt;/a>, I wrote about tips to improve the angular development experience. In this post, I am going to look at the VSCode extensions that are a must have for Angular Developers. So, without further ado:&lt;/p>
&lt;h3 id="angular-language-service-extension">Angular Language Service Extension&lt;/h3>
&lt;p>This one is a must for any Angular Developer. Angular language service is a way to get completions, errors, hints, and navigation inside your Angular templates. It doesn’t matter whether they are external, in an HTML file or embedded in annotations/decorators in a string.&lt;/p>
&lt;p>This extension will use &lt;a href="https://angular.io/guide/language-service">Angular Language Service&lt;/a> to provide Intellisense, AOT (Ahead of Time) Compilation Diagnostic Information, Quick Information and Go to Definition. These are useful features that make your life as a developer easier.&lt;/p>
&lt;p>Visit the extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=Angular.ng-template">page&lt;/a> for more information.&lt;/p>
&lt;h3 id="angular-2-inline">Angular-2 Inline&lt;/h3>
&lt;p>I don’t use inline templates that often, but when I do, I find that lack of Intellisense makes my work that more difficult. This extension has alleviated that problem since I started using it. It provides code autocompletion, syntax highlighting and quick information for inline templates.&lt;/p>
&lt;p>Visit the extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=natewallace.angular2-inline">page here&lt;/a> for more information.&lt;/p>
&lt;h3 id="intellisense-for-css-class-names-in-html">IntelliSense for CSS class names in HTML&lt;/h3>
&lt;p>This extension does one simple Job, scan your current workspace looking for CSS Classes and then provide autocompletion for the same classes inside your angular html templates. Whether the classes are bootstrap classes or your own custom classes, this extension will find them and provide autocompletion for them under the class attribute of your html elements. It is simple, neat and works out of the box.&lt;/p>
&lt;p>You can learn more about this extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=Zignd.html-css-class-completion">here&lt;/a>.&lt;/p>
&lt;h3 id="debuggers-for-chrome-firefox-and-edge">Debuggers for Chrome, Firefox and Edge&lt;/h3>
&lt;p>These are three extensions that basically do the same thing but on different browsers. They enable you to test your Angular/JavaScript application. The neat trick is that debug information is sent directly back to visual studio code console instead of the browsers console.&lt;/p>
&lt;p>On top of that, you can add break points to your Angular components, and step through the execution of your code. These are important tools to allow you to test your app compatibility with multiple browsers.&lt;/p>
&lt;p>You can learn more about the extensions in the links provided below:&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome">Google Chrome (Debugger for Google Chrome)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-firefox-debug">Mozilla FireFox (Debugger for Mozilla Firefox)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-edge">Microsoft Edge (Debugger for Edge)&lt;/a>&lt;/li>
&lt;/ol>
&lt;h3 id="tslint-extension-typescript-lint">TSLint Extension (Typescript Lint)&lt;/h3>
&lt;p>This extension integrates &lt;a href="https://github.com/palantir/tslint">TSLint&lt;/a> into VSCode. TSLint is an extensible static analysis tool that checks TypeScript code for readability, maintainability, and functionality errors. This extension brings all this goodness to VSCode.&lt;/p>
&lt;p>For more information about TSLint, visit the official github repo &lt;a href="https://github.com/palantir/tslint">here&lt;/a>. The extension also provides some important VSCode commands such as Auto-Fixing of problems highlighted by TSLint among others.&lt;/p>
&lt;p>You can learn more about this extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=eg2.tslint">here&lt;/a>.&lt;/p>
&lt;h3 id="prettier--code-formatter">Prettier – Code Formatter&lt;/h3>
&lt;p>Every developer wants their code to look clean, organized and be consistently formatted. Clean, organized and consistent code makes it easy to read and follow and even prettier to look at. That’s the goal of this extension.&lt;/p>
&lt;p>This extension also comes with a host of configuration options such as where to add line break, format on save/paste or type, whether to automatically add semicolons at the end of a statement etc. It works well with JavaScript/TypeScript and CSS. For html, VSCode seems to do a fine job on its own – no extension required.&lt;/p>
&lt;p>You can learn more about this extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode">here&lt;/a>.&lt;/p>
&lt;h3 id="npm">NPM&lt;/h3>
&lt;p>This is a simple extension that I find extremely useful. In your package.json file, if you select or hover on a package version number, it will automatically pull the latest version of the package from NPM.&lt;/p>
&lt;p>This gives you an option to easily know whether you are using the latest version of an NPM package. That’s what I use it for mainly, but it can do more than that. The extension will validate your package.json file for errors, quickly run NPM scripts and stop a running script. For those of you who use yarn, some of the features may be unavailable.&lt;/p>
&lt;p>You can learn more about this extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=eg2.vscode-npm-script">here&lt;/a>.&lt;/p>
&lt;h3 id="git-history">Git History&lt;/h3>
&lt;p>This is another essential extension for anyone who uses Git in their projects. It provides a nice UI for you to interact with your Git repo. With a click of button, you can get all your git history for your current VSCode Workspace. You can search, view previous copy of a file, compare, revert, merge and do a lot of git operations with this extension. Right click on a file inside the explorer and you can view its git history and previous versions easily. And with over 3 Million install, you can see why a lot of developers love this extension.&lt;/p>
&lt;p>You can learn more about this extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=donjayamanne.githistory">here&lt;/a>.&lt;/p>
&lt;h3 id="angular-6-snippets">Angular 6 Snippets&lt;/h3>
&lt;p>I don’t use this extension that much, but it would be criminal not to include it. It is developed by John Papa, a prominent member of the Angular Community. It adds snippets for Angular for both TypeScript and HTML.&lt;/p>
&lt;p>In a single command, it will generate boilerplate code for an angular service, component etc. or boilerplate code for your html element. On top of html and typescript, this extension also supports docker file and JavaScript.&lt;/p>
&lt;p>You can learn more about this extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2">here&lt;/a>.&lt;/p>
&lt;h3 id="path-intellisense">Path Intellisense&lt;/h3>
&lt;p>This is a simple yet useful extension whose goal is to provide filename Intellisense inside your code. It relies on the TsConfig Base URL to map the root of your project. It enables you to navigate through your directories in your project until you get to the file you want. There isn’t much to say about this extension considering the name is quite self-explanatory.&lt;/p>
&lt;p>You can learn more about this plugin &lt;a href="https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense">here&lt;/a>.&lt;/p>
&lt;h3 id="conclusion">Conclusion&lt;/h3>
&lt;p>Those are some of the VSCode extensions I use to improve my Angular Development Workflow. If I left any extension from this post, you can suggest it in the comment below and I will be happy to add it to this list. Thank you for getting this far, don’t forget to share if you found this helpful.&lt;/p></description></item><item><title>UI Libraries and Frameworks for Angular 6</title><link>https://codinglatte.com/posts/angular/ui-libraries-and-frameworks-for-angular-6/</link><pubDate>Fri, 27 Jul 2018 13:41:59 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/ui-libraries-and-frameworks-for-angular-6/</guid><description>&lt;p>UI Libraries and Frameworks make it easier for developers to build clean and consistent User Interfaces (UI). They provide components, utilities for common use within your Application. Some UI Libraries provide you with the freedom to switch things up using themes. While other provide a clear consistent User Experience. Forcing developers to adhere to a set of strict design language. If you are looking for a new UI library and Framework for your application, here a few honorable mentions:&lt;/p>
&lt;h2 id="angular-material-2">Angular Material 2&lt;/h2>
&lt;p>&lt;a href="https://material.angular.io/">Angular 2 Material&lt;/a> is an adaptation of &lt;a href="https://material.io/design/">Google Material Design Language&lt;/a> for Angular 2 and above. It offers Material Design Components for angular. Some of these components include Cards, Dialog, Lists, Grid, Side Nav etc. It is closely integrated with Angular, offering APIs for its component with excellent documentation and demos. If you are a fan of Material Design, the this should be on top  of your list. On its own, it lacks the ability to provide a powerful responsive design system. Therefore, it is common to pair it with &lt;a href="https://github.com/angular/flex-layout">Angular Flex Layout&lt;/a>.&lt;/p>
&lt;p>The two libraries are not bundled together. This allows developers to use either of the two libraries independently, or both at the same time. It is also heavily optimized for performance. This is achieved through allowing developers to import only the set of components they are using in their projects. This ensures that your deployment build doesn’t end up with extra components that you are not using.&lt;/p>
&lt;p>You can learn how to get started with Angular Material &lt;a href="https://material.angular.io/guide/getting-started">here&lt;/a>.&lt;/p>
&lt;h2 id="ng-bootstrap">NG Bootstrap&lt;/h2>
&lt;p>&lt;a href="https://getbootstrap.com/">Bootstrap&lt;/a> is one of the most popular and complete UI frameworks out there. It offers everything you would like on a UI framework. The major downside to it, as far as Angular is concerned,  is that it uses jQuery components. While you can still use Bootstrap classes without jQuery, you will require it to take full advantage of it. And this is where &lt;a href="https://ng-bootstrap.github.io/#/home">ng-bootstrap&lt;/a> comes in.&lt;/p>
&lt;p>ng-bootstrap offers a set of components build with bootstrap CSS. These components are build the angular way, using directives and components (angular components). The widgets on offer are the same as the components offered by bootstrap. This eliminates the need for jQuery. On top of the many components/widgets on offer, you still retain the advantages offered by CSS Bootstrap. You get countless styles for your different html element on your site, a responsive grid design and countless utilities classes. You can learn more about ng-bootstrap &lt;a href="https://ng-bootstrap.github.io/#/home">here&lt;/a>.&lt;/p>
&lt;h2 id="clarity-design-system">Clarity Design System&lt;/h2>
&lt;p>This is a set of UX Guidelines, a HTML/CSS Frameworks and a set of Angular Components all rolled into one. The goal of &lt;a href="https://vmware.github.io/clarity/">Clarity Design System&lt;/a> is to provide an exceptional UX by combining the three. The UX guidelines are developed through research to make it easy to design and deliver a great UX.&lt;/p>
&lt;p>It offers a responsive grid system which is similar to what is offered by bootstrap. Just like the other UI Frameworks in this list, it has a lot of &lt;a href="https://vmware.github.io/clarity/documentation/v0.12">components&lt;/a> and utilities for you to use. It also comes with its own Icon Set.&lt;/p>
&lt;p>You can learn how to get started with Clarity &lt;a href="https://vmware.github.io/clarity/documentation/v0.12/get-started">here&lt;/a>.&lt;/p>
&lt;h2 id="primeng">PrimeNG&lt;/h2>
&lt;p>If you have ever worked with Java UI Framework – &lt;a href="https://www.primefaces.org/">Prime Faces&lt;/a>, the PrimeNG will look very familiar. &lt;a href="https://www.primefaces.org/primeng/#/setup">PrimeNG&lt;/a> is a port of the popular Java EE framework for Angular 2 and above. It offers components, responsive design and key utilities for Angular 2 developers.&lt;/p>
&lt;p>It offers over 80 components for Angular, giving it a huge advantage over ng-bootstrap and angular material. On top of that, it can easily be customized through the use of &lt;a href="https://www.primefaces.org/primeng/#/setup">themes&lt;/a>.&lt;/p>
&lt;p>You can learn how to get started with PrimeNG &lt;a href="https://www.primefaces.org/primeng/#/setup">here&lt;/a>.&lt;/p>
&lt;h2 id="onsen-ui-for-angular">Onsen UI for Angular&lt;/h2>
&lt;p>Unlike other frameworks on this list, &lt;a href="https://onsen.io/v2/guide/angular2/">Onsen UI&lt;/a> is designed for building hybrid apps for Android and iOS apps. It provides a set of components with both flat design and material design, which provides more choices for you as a developer.&lt;/p>
&lt;p>You can learn how to get started with Onsen UI for Angular &lt;a href="https://onsen.io/v2/guide/angular2/">here&lt;/a>.&lt;/p>
&lt;h2 id="honorable-mentions">Honorable Mentions:&lt;/h2>
&lt;ol>
&lt;li>&lt;a href="https://github.com/NG-ZORRO/ng-zorro-antd">Ant Design for Angular&lt;/a> – Implements the &lt;a href="https://ant.design/docs/spec/introduce">Ant Design&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/ng-lightning/ng-lightning">Lightning Design System&lt;/a> – Contains native Angular Components written using &lt;a href="https://www.lightningdesignsystem.com/">Lightning Design System&lt;/a> CSS framework.&lt;/li>
&lt;li>&lt;a href="https://ionicframework.com/">Ionic&lt;/a> Framework - for Building Cross Platforms Apps&lt;/li>
&lt;/ol></description></item><item><title>Angular – Managing Authentication State Using NGXS</title><link>https://codinglatte.com/posts/angular/ngxs-authentication-angular/</link><pubDate>Wed, 25 Jul 2018 13:26:34 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/ngxs-authentication-angular/</guid><description>&lt;p>Managing an apps Authentication State is a vital task that as Single Page App (SPA) developers, have to handle very often. It’s every developers goal to provide a consistent user experience in your application, depending on whether they are signed in or not.&lt;/p>
&lt;p>In this post, we are going to build an authentication system that relies on NGXS for state management. NGXS is a state management library made for Angular. There are other alternative of course like the popular &lt;a href="https://github.com/ngrx/platform">NGRX&lt;/a>. You can learn more about NGXS &lt;a href="https://ngxs.gitbook.io/ngxs/getting-started/why">here&lt;/a>.&lt;/p>
&lt;h3 id="introduction">Introduction&lt;/h3>
&lt;p>I want to demonstrate a comprehensive authentication solution that covers all foreseeable angles. This will include:&lt;/p>
&lt;ol>
&lt;li>Authentication Service – to interface with your backend&lt;/li>
&lt;li>A guard to protect your routes&lt;/li>
&lt;li>HTTP Interceptor – To automatically attach authorization tokens to outgoing requests&lt;/li>
&lt;li>State Management – Store Authorization Token, Maintain a State&lt;/li>
&lt;/ol>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>First, you will need to install both NGXS and a NGXS &lt;a href="https://ngxs.gitbook.io/ngxs/plugins/storage">Storage Plugin&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add  @ngxs/store @ngxs/storage-plugin
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, and it to your imports in the App Module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgxsModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@ngxs/store&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">NgxsModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>([])]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For now, let’s leave the &lt;code>forRoot&lt;/code> array empty. We will come back to this later once we have created our authentication state. Next, let’s work on our Authentication Service.&lt;/p>
&lt;h3 id="authentication-service">Authentication Service&lt;/h3>
&lt;p>In this service, we will have a couple of methods to authenticate users. The most common use case is to send http requests to the server and return observables. In our service we will have two methods: A sign in and a sign out method. The sign in method will return an observable with user details while the sign out will return a null observable.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Auth Service Methods
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#a6e22e">signin&lt;/span>(&lt;span style="color:#a6e22e">email&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>,&lt;span style="color:#a6e22e">password&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>{ &lt;span style="color:#a6e22e">name&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>; &lt;span style="color:#a6e22e">email&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> }&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">/*
&lt;/span>&lt;span style="color:#75715e"> This will presumably call a http backend and return the response
&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;span style="color:#75715e"> return this.http.post&amp;lt;{{ name: string; email: string }}&amp;gt;(url, { email: email, password: password })
&lt;/span>&lt;span style="color:#75715e">      .pipe(
&lt;/span>&lt;span style="color:#75715e">        map(res =&amp;gt; res.body)
&lt;/span>&lt;span style="color:#75715e">      )
&lt;/span>&lt;span style="color:#75715e">    */&lt;/span>
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>({
      &lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Some Name&amp;#39;&lt;/span>,
      &lt;span style="color:#a6e22e">email&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;some@email.com&amp;#39;&lt;/span>
    });
}
&lt;span style="color:#a6e22e">signout&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">null&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#66d9ef">null&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="auth-state-management">Auth State Management&lt;/h3>
&lt;p>The first thing we need to create are model and action class for our state. You can put each on its own separate file, or all of them in on a single file. Then, we need to create a single model to hold our current authentication model/data.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Auth State Model
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AuthStateModel&lt;/span> {
&lt;span style="color:#75715e">// if you have an extra token like authorization, you can add it here plus any other user information you might want to store
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">token?&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>; &lt;span style="color:#75715e">// refreshToken?: string;
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">email?&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">name?&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After that, we need to create two actions – A Sign in action and a Sign out action:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Auth State Model
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Signin&lt;/span> {
&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">readonly&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[Auth] Signin&amp;#39;&lt;/span>;
&lt;span style="color:#75715e">// these are parameters to pass to the action when dispatching it also known as metadata // they work just like normal parameters in normal parameters
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">email&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">password&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) {}
}
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Signout&lt;/span> {
&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">readonly&lt;/span> &lt;span style="color:#a6e22e">type&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;[Auth] Signout&amp;#39;&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to create our state class (authentication state class) and wire everything up:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Auth State Model
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">@State&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">AuthStateModel&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>({
&lt;span style="color:#a6e22e">name&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;auth&amp;#39;&lt;/span> &lt;span style="color:#75715e">// the name of our state
&lt;/span>&lt;span style="color:#75715e">&lt;/span>})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AuthState&lt;/span> {
&lt;span style="color:#66d9ef">@Selector&lt;/span>()
&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span>(&lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">AuthStateModel&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">state&lt;/span>.&lt;span style="color:#a6e22e">token&lt;/span>;
}
&lt;span style="color:#66d9ef">@Selector&lt;/span>()
&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">userDetails&lt;/span>(&lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">AuthStateModel&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> {
&lt;span style="color:#a6e22e">name&lt;/span>: &lt;span style="color:#66d9ef">state.name&lt;/span>,
&lt;span style="color:#a6e22e">email&lt;/span>: &lt;span style="color:#66d9ef">state.email&lt;/span>
};
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can add extra selectors for different information stored with our state like refresh token and other personal details&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Auth State
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AuthState&lt;/span> {
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">@Selector&lt;/span>()
&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">refreshToken&lt;/span>(&lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">AuthStateModel&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">state&lt;/span>.&lt;span style="color:#a6e22e">refreshToken&lt;/span>;
}
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">authService&lt;/span>: &lt;span style="color:#66d9ef">AuthService&lt;/span>) {}
&lt;span style="color:#66d9ef">@Action&lt;/span>(&lt;span style="color:#a6e22e">Signin&lt;/span>)
&lt;span style="color:#a6e22e">login&lt;/span>(
{ &lt;span style="color:#a6e22e">patchState&lt;/span> }&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">StateContext&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">AuthStateModel&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
{ &lt;span style="color:#a6e22e">email&lt;/span>, &lt;span style="color:#a6e22e">password&lt;/span> }&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Signin&lt;/span>
) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">authService&lt;/span>.&lt;span style="color:#a6e22e">signin&lt;/span>(&lt;span style="color:#a6e22e">email&lt;/span>, &lt;span style="color:#a6e22e">password&lt;/span>).&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">tap&lt;/span>(&lt;span style="color:#a6e22e">result&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">patchState&lt;/span>({
&lt;span style="color:#a6e22e">token&lt;/span>: &lt;span style="color:#66d9ef">result.token&lt;/span>,
&lt;span style="color:#a6e22e">name&lt;/span>: &lt;span style="color:#66d9ef">result.name&lt;/span>,
&lt;span style="color:#a6e22e">email&lt;/span>: &lt;span style="color:#66d9ef">result.email&lt;/span>
});
})
);
}
&lt;span style="color:#66d9ef">@Action&lt;/span>(&lt;span style="color:#a6e22e">Signout&lt;/span>)
&lt;span style="color:#a6e22e">logout&lt;/span>({ &lt;span style="color:#a6e22e">setState&lt;/span>, &lt;span style="color:#a6e22e">getState&lt;/span> }&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">StateContext&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">AuthStateModel&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>) {
&lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#a6e22e">token&lt;/span> } &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">getState&lt;/span>();
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">authService&lt;/span>.&lt;span style="color:#a6e22e">signout&lt;/span>().&lt;span style="color:#a6e22e">pipe&lt;/span>(
&lt;span style="color:#a6e22e">tap&lt;/span>(&lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">setState&lt;/span>({});
})
);
}
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, we need to add our new &lt;code>Auth State&lt;/code> to the state of array of &lt;code>NgxsModule.forRoot([])&lt;/code> method (The array we left empty at the beginning):&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">NgxsModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>([&lt;span style="color:#a6e22e">AuthState&lt;/span>])],
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And because we want our authentication state to survive page reloads, lets import the NGXS Storage Plugin we installed into our app module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">NgxsStoragePluginModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>({
&lt;span style="color:#a6e22e">key&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;auth.token &amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;auth.email &amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;auth.name &amp;#39;&lt;/span>]
});
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> The keys passed start with the name of our state followed by the item we are storing. So, if you check local storage on the browser, you will find the token under &lt;code>auth.token&lt;/code> instead of just token.&lt;/p>
&lt;/blockquote>
&lt;h3 id="signing-in-and-out">Signing in and out&lt;/h3>
&lt;p>Now, we can add a method to sign in and sign out in our components. Instead of directly calling sign in and sign out methods in Auth Service, we will call on NGXS Store to dispatch sign in and sign out actions. Then we will subscribe to the observable:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">
&lt;span style="color:#a6e22e">signin&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_store&lt;/span>
      .&lt;span style="color:#a6e22e">dispatch&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Signin&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;some@email.com&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;password&amp;#39;&lt;/span>))
      .&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">success&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {}, &lt;span style="color:#a6e22e">error&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {});
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The same goes for our sign out method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_store&lt;/span>.&lt;span style="color:#a6e22e">dispatch&lt;/span>(&lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">Signout&lt;/span>()).&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">success&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {}, &lt;span style="color:#a6e22e">error&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {});
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Remember to inject NGXS Store into your components:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Store&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@ngxs/store&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">_store&lt;/span>: &lt;span style="color:#66d9ef">Store&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="http-interceptor">HTTP Interceptor&lt;/h3>
&lt;p>In one of my earliest posts, I covered &lt;a href="https://codinglatte.com/tech/developers/angular/building-http-interceptor-angular-5/">HTTP Interceptors&lt;/a> in Angular, in this section I won’t go into details about them. Our http interceptor will catch all requests and attach our token from our auth state. We are going to fetch the token from our auth state and attach it to every outgoing requests.&lt;/p>
&lt;p>First, get our auth token from the auth state:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_store&lt;/span>.&lt;span style="color:#a6e22e">selectSnapshot&lt;/span>(&lt;span style="color:#a6e22e">state&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">state&lt;/span>.&lt;span style="color:#a6e22e">auth&lt;/span>.&lt;span style="color:#a6e22e">authorization&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> We are using &lt;code>selectSnapshot&lt;/code> to get the token because it returns a simple string/value that is readily usable by our http interceptor. There is no need to subscribe to get the token we need.&lt;/p>
&lt;/blockquote>
&lt;p>Then, clone and attach the token to the header of our intercepted http request:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// Clone the request to add the new header.
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">modifiedRequest&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({
&lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;authorization&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>)
});
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Always remember to always validate the token on the server side.&lt;/p>
&lt;/blockquote>
&lt;p>And finally, send the modified request:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">modifiedRequest&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Don&amp;rsquo;t forget to add it to your list of providers in the app module:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">AuthService&lt;/span>,
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">HTTP_INTERCEPTORS&lt;/span>,
&lt;span style="color:#a6e22e">useClass&lt;/span>: &lt;span style="color:#66d9ef">OurHttpInterceptor&lt;/span>,
&lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
}
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>];
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="router-guard">Router Guard&lt;/h3>
&lt;p>Router Guards are used to protects routes from unauthorized access. In our case, we need to check whether the user is authorized and if not redirect to the login page. We need to get the token, from our auth state and check if it is set. If not, then redirect back to login or home page:&lt;/p>
&lt;p>First, inject NGXS store and router into our auth guard:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">_store&lt;/span>: &lt;span style="color:#66d9ef">Store&lt;/span>, &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">router&lt;/span>: &lt;span style="color:#66d9ef">Router&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, inside of our &lt;code>canActivate&lt;/code> method, we need to check if the token is set, and if not redirect to the sign in page:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">GuardGuard&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">CanActivate&lt;/span> {
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
&lt;span style="color:#a6e22e">canActivate&lt;/span>(
&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRouteSnapshot&lt;/span>,
&lt;span style="color:#a6e22e">state&lt;/span>: &lt;span style="color:#66d9ef">RouterStateSnapshot&lt;/span>
)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">boolean&lt;/span> {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">token&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">!!&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_store&lt;/span>.&lt;span style="color:#a6e22e">selectSnapshot&lt;/span>(
&lt;span style="color:#a6e22e">ourState&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">ourState&lt;/span>.&lt;span style="color:#a6e22e">auth&lt;/span>.&lt;span style="color:#a6e22e">authorization&lt;/span>
);
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#a6e22e">token&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#39;/&amp;#39;&lt;/span>]);
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>;
}
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>;
}
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The same will do for &lt;code>canActivateChild&lt;/code> method if you need one. And that’s it. You should now have a functioning authentication system using NGXS that can sign in and sign out users, maintain authentication state, attach authorization tokens to your HTTP request and protect routes from unauthorized requests.&lt;/p>
&lt;p>You can find all the above code in the Github Repository &lt;a href="https://github.com/MainaWycliffe/ngxs-auth-demo">here&lt;/a>.&lt;/p></description></item><item><title>Angular Tips to Improve your Development Experience</title><link>https://codinglatte.com/posts/angular/angular-development-tips/</link><pubDate>Mon, 23 Jul 2018 05:49:13 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-development-tips/</guid><description>&lt;p>Developing web apps using Angular and other frameworks and languages can be sometime a daunting task. You need to write thousands of lines of code and sometime rewrite countless times some of them, to achieve a common goal. Today, I am going to share some Tips to make your development work less daunting. Most – if not all – of these tips are applicable to other JavaScript frameworks and Programming in general but for the sake of simplicity (and my sanity) I will concentrate on Angular and TypeScript.&lt;/p>
&lt;h1 id="build-libraries-for-use-in-your-projects">Build Libraries for use in your Projects&lt;/h1>
&lt;p>If you are an active angular developer, you will always be working on multiple projects at any given time. While most projects are unique in their designs, there are those overlapping aspects which are shared across most if not all projects. You can make it easier by building libraries for the shared features and use them across multiple projects that needs them. This could potentially save you a lot of copy-pasting and testing hours.
It also makes it easier to update the code and upgrade to newer versions of Angular without necessarily breaking old applications. Even better, you could open-source the libraries and have other developers, use, contribute and enrich your libraries. And with angular 6, it is even easier to build, package and deploy libraries. If you are looking to get started, &lt;a href="https://codinglatte.com/tech/developers/angular/building-angular-6-libraries/">here are some tutorials&lt;/a> to help you.&lt;/p>
&lt;h1 id="always-write-test-both-end-to-end-and-unit-testing">Always Write Test (Both End to End and Unit Testing)&lt;/h1>
&lt;p>This may sound obvious to experienced developers, but it’s not, especially to beginners and intermediate ones. Writing Tests is a time-consuming activity that most developers don’t see the need for. Sometimes, you are just working on small project and other times working on a tight deadline. Before you know it, the project is so large, in such a way writing tests has become an enormous task. So, the rule of the thumb is, write tests for all your projects. If you are looking to get started with testing, I suggest the &lt;a href="https://angular.io/guide/testing">official documentation&lt;/a> of Angular.&lt;/p>
&lt;h1 id="user-alias-for-imports">User Alias for Imports&lt;/h1>
&lt;p>Have you ever tried to restructure your code by moving things around in an Angular &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">CLI Workspace&lt;/a>? You end up having to update so many components, services, modules etc. that imported those items. This may not be a problem in a small project but in a huge project it can be time-consuming. You can make this easier by using aliases. Instead of using a relative path to your service:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">someservice&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">‘&lt;/span>..&lt;span style="color:#f92672">/&lt;/span>..&lt;span style="color:#f92672">/&lt;/span>..&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">services&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">some&lt;/span>.&lt;span style="color:#a6e22e">service&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">’&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can instead user an alias that points to your services:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">someservice&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">‘&lt;/span>&lt;span style="color:#66d9ef">@myservices&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">’&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To achieve this, first, you need to create a TypeScript files for exporting all your services – let’s call it &lt;strong>services.ts.&lt;/strong> Then export all the services we want from inside this file:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./some.service&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./some.other.service&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After that, modify the typescript configuration &lt;code>(tsconfig.json)&lt;/code> and add a reference to our service.ts under our paths:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
  &lt;span style="color:#f92672">&amp;#34;compileOnSave&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>,
  &lt;span style="color:#f92672">&amp;#34;compilerOptions&amp;#34;&lt;/span>: {
    &lt;span style="color:#f92672">&amp;#34;baseUrl&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;./&amp;#34;&lt;/span>,
    &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
    &lt;span style="color:#f92672">&amp;#34;paths&amp;#34;&lt;/span>: {
      &lt;span style="color:#f92672">&amp;#34;@services&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;src/app/services/services&amp;#34;&lt;/span>],
  }
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This way, any changes to the path of a service (like moving it somewhere else or just renaming it), then all you need to do is reflect the new location inside the service.ts file.&lt;/p>
&lt;h1 id="write-readable-code">Write Readable Code&lt;/h1>
&lt;p>We have all been there, when you spend a lot of time trying to figure out what a block of code does. Or wondering what that variable with an ambiguous name does. Poorly written code is not only a problem to other developers who will read your code but even to you. When you come back to your code after a while and start wondering – what did I want to achieve here or how or what’s does this do? Then you should review your coding habit – I am also guilty about this &lt;code>[bummer]&lt;/code>.&lt;/p>
&lt;p>I would love to go on about this, but it will turn out to be a rant which is not helpful to anyone. Instead, I advise you to watch &lt;a href="https://twitter.com/John_Papa">John Papa&lt;/a> presentation on readable code on ng-conf below.&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://www.youtube-nocookie.com/embed/56mETnrByBM" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video">&lt;/iframe>
&lt;/div>
&lt;h1 id="always-use-static-type-and-interfaces-for-your-objects">Always use Static Type and Interfaces for your objects&lt;/h1>
&lt;p>In TypeScript, Interfaces define the type of content and shape an object can have. For instance, If the object is a list of students, then it might have a name, age, class etc. inside. So, what an interface does is define, the object must have a name, age and class. In this case, name and class are of type string while age is a number. By using interface and static types in your code, you will be able to catch a good number of errors that may arise due to type mismatch – like trying to multiply a string and a number.&lt;/p>
&lt;p>But, the main reason I am suggesting this – in the context of this post – is, when you are using a good text editor (i.e. &lt;a href="https://code.visualstudio.com/">VS Code&lt;/a>, &lt;a href="https://atom.io/">Atom&lt;/a>, &lt;a href="https://www.sublimetext.com/">Sublime&lt;/a> etc.) you will be able to receive Intellisense (auto-completion, error checking and navigation) right inside your angular templates (You will need Angular &lt;a href="https://angular.io/guide/language-service">Language Service&lt;/a> for that).&lt;/p>
&lt;p>This gives you a piece of mind that your variables are correctly reflected inside the template. There are no stupid errors misspelling errors. That’s time and effort saved that you can use elsewhere. This is not an exhaustive list, if you have a tip to share, post it in the comment section for others who will come after you.&lt;/p></description></item><item><title>A Guide for Building Angular 6 Libraries</title><link>https://codinglatte.com/posts/angular/building-angular-6-libraries/</link><pubDate>Sat, 21 Jul 2018 11:18:54 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/building-angular-6-libraries/</guid><description>&lt;p>In an earlier post, I wrote about &lt;a href="https://codinglatte.com/tech/developers/angular/angular-6-angular-cli-workspaces/">Angular CLI Workspaces&lt;/a>, a new feature in Angular 6 that allows you to have more than one project in a single workspace (Angular CLI environment). In this post, I will show you how to create angular 6 Libraries. On top of that, I will show you how to pass configurations and data to your new library from your Angular Application.&lt;/p>
&lt;h3 id="why">Why?&lt;/h3>
&lt;p>If you have multiple active angular projects, you may have come to realize that there so many things they share or have in common. Sometime, as a developer you are forced to copy paste their code to new projects for features they have in common.&lt;/p>
&lt;p>A good example of this is Authentication. While the UI (Sign in, sign up, password reset etc. forms in the case of Authentication) may change, the underlying code (Services, HTTP Interceptors, Guards etc.) tends to remain the same apart from some incremental modifications and bug fixes. Wouldn’t it be easier that instead of copy pasting, you could just have a private library that you can hook into your project and have access to all the features you need for your new project? This would save you lots of hours which you could utilize on the UI and other features of your new project.&lt;/p>
&lt;h3 id="overview-of-our-library">Overview of our Library&lt;/h3>
&lt;p>We are going to work with a demo that does the following: A component to display a list of Football/Soccer National Teams and the number of World Cup trophies they have won. A service that will take a list of teams Injected to our library and sort it by descending order. The &lt;code>config&lt;/code> file will be injected using the &lt;code>forRoot&lt;/code> method through the module (Similar to the way you pass routes to the &lt;a href="https://angular.io/tutorial/toh-pt5">router module&lt;/a>).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#f92672">:&lt;/span> [ &lt;span style="color:#a6e22e">RouterModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>(&lt;span style="color:#a6e22e">routes&lt;/span>) ]
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> To inject our configuration, we will rely on &lt;a href="https://angular.io/api/core/InjectionToken">Injection Token&lt;/a> method. It is not the only way to pass configurations into a library or module. If you want to explore the other methods, I suggest going over &lt;a href="https://medium.com/@michelestieven/angular-writing-configurable-modules-69e6ea23ea42">this excellent post&lt;/a> by &lt;a href="https://medium.com/@michelestieven">Michele Stieven&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>For our demo, we are going to rely on the following libraries: Angular Material, Angular CDK and Angular Flex Layout.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>To get started, we are going to create a new angular project (just a regular project):&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng new application-name
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, open that directory on terminal or PowerShell:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">cd application-name
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And generate a library inside our angular workspace using &lt;code>ng generate library&lt;/code> &lt;a href="https://github.com/angular/angular-cli/wiki/generate-library">command&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng generate library test-library --prefix=tl
&lt;/code>&lt;/pre>&lt;/div>&lt;p>A new library is generated and is placed under the &lt;code>/projects/my-library&lt;/code> directory in your angular workspace. To use your library in your current app, you need to build your library every time. To build the library, use the &lt;code>ng build&lt;/code> command followed by the name of the project (library in this case):&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng build my-library
ng build --prod my-library
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The build artefacts can be found under a directory with the name of the library, inside the &lt;code>/dist&lt;/code> directory in your workspace.&lt;/p>
&lt;h3 id="working-on-the-library">Working on the library&lt;/h3>
&lt;p>If you open your project folder, the folder structure will look like this: &lt;img src="https://codinglatte.com/wp-content/uploads/2018/07/folder-setup-here-152x300.png" alt="A Guide to Building Angular 6 Libraries"> When you generate a library, Angular CLI will creates 3 files: the main library module, a component and a service. For our demo, there is no need to add any extra component or service. But, if you need to add one, the ng generate command with the project flag will do the trick.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng generate component component-name --project-name=test-library
ng generate service service-name --project-name=test-library
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="building-the-library">Building the Library&lt;/h3>
&lt;p>Our demo library can be broken down into 3 items: The Library Module (think of AppModule), Our Service and Component. On top of the three items, there are classes and interfaces that will play a supporting role for our library. You can get the whole source code on&lt;a href="https://github.com/MainaWycliffe/demo-for-building-angular-6-library"> Github here&lt;/a>. First, we need to define an injection token constant to use Injection Token method:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">TestLibConfigService&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">InjectionToken&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">TestLibConfig&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(
&lt;span style="color:#e6db74">&amp;#39;TestLibConfig&amp;#39;&lt;/span>
);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then, we need to define our interface(&lt;code>TestLibConfig&lt;/code>) for the object we will be passing using our &lt;code>forRoot&lt;/code> method.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span> &lt;span style="color:#a6e22e">TestLibConfig&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">teams&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">country&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span>;
}[];
&lt;span style="color:#a6e22e">sport&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> To avoid &lt;code>Circular dependency&lt;/code> warning, you can put the &lt;code>TestLibConfig&lt;/code> and &lt;code>TestLibConfigService&lt;/code> into separate files instead of the module file. These warnings occur because the two will be imported by the service and the module, while the module will import the service.&lt;/p>
&lt;/blockquote>
&lt;h5 id="library-module">Library Module&lt;/h5>
&lt;p>Since we now have an injection token, we can now go ahead and create our &lt;code>forRoot&lt;/code> method that we will use to pass the configuration object to our library.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#a6e22e">forRoot&lt;/span>(&lt;span style="color:#a6e22e">config&lt;/span>: &lt;span style="color:#66d9ef">TestLibConfig&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">ModuleWithProviders&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> {
&lt;span style="color:#a6e22e">ngModule&lt;/span>: &lt;span style="color:#66d9ef">TestLibraryModule&lt;/span>,
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">TestLibraryService&lt;/span>,
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">TestLibConfigService&lt;/span>,
&lt;span style="color:#a6e22e">useValue&lt;/span>: &lt;span style="color:#66d9ef">config&lt;/span>
}
]
};
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you can see, our &lt;code>forRoot&lt;/code> method takes a config object and provides it together with the services that are in our library. Also, we need to import Material Components we are using in our Library and declare and export our component.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span>,
&lt;span style="color:#a6e22e">MatListModule&lt;/span>,
&lt;span style="color:#a6e22e">MatToolbarModule&lt;/span>,
&lt;span style="color:#a6e22e">MatCardModule&lt;/span>],
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">TestLibraryComponent&lt;/span>],
&lt;span style="color:#a6e22e">exports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">TestLibraryComponent&lt;/span>]
})
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="library-service">Library Service&lt;/h3>
&lt;p>Then, we need to inject the configuration object into our service.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">@Inject&lt;/span>(&lt;span style="color:#a6e22e">TestLibConfigService&lt;/span>) &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">config&lt;/span>: &lt;span style="color:#66d9ef">TestLibConfig&lt;/span>) {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">config&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now the configuration object is ready for use in our service. The rest of the service looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">TestLibraryService&lt;/span> {
&lt;span style="color:#75715e">// inject our configuration into our service
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">@Inject&lt;/span>(&lt;span style="color:#a6e22e">TestLibConfigService&lt;/span>) &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">config&lt;/span>: &lt;span style="color:#66d9ef">TestLibConfig&lt;/span>) {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">config&lt;/span>);
}
&lt;span style="color:#75715e">// You can now use your configuration as you normally would
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// if it was a http request, then you could return observables which you can subscribe to
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">getConfig&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">TestLibConfig&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">config&lt;/span>);
}
&lt;span style="color:#a6e22e">getTitle&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">string&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">config&lt;/span>.&lt;span style="color:#a6e22e">title&lt;/span>);
}
&lt;span style="color:#a6e22e">getTeams&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>{ &lt;span style="color:#a6e22e">country&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>; &lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span> }[]&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">// just for fun, let&amp;#39;s sort this by descending order
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// we shall use, bubble sort
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">sorted&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">config&lt;/span>.&lt;span style="color:#a6e22e">teams&lt;/span>.&lt;span style="color:#a6e22e">slice&lt;/span>();
&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#a6e22e">sorted&lt;/span>.&lt;span style="color:#a6e22e">length&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span>) {
&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#a6e22e">sorted&lt;/span>.&lt;span style="color:#a6e22e">length&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>; &lt;span style="color:#a6e22e">j&lt;/span>&lt;span style="color:#f92672">++&lt;/span>) {
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">sorted&lt;/span>[&lt;span style="color:#a6e22e">j&lt;/span>].&lt;span style="color:#a6e22e">trophies&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#a6e22e">sorted&lt;/span>[&lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>].&lt;span style="color:#a6e22e">trophies&lt;/span>) {
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">swap&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">sorted&lt;/span>[&lt;span style="color:#a6e22e">j&lt;/span>];
&lt;span style="color:#a6e22e">sorted&lt;/span>[&lt;span style="color:#a6e22e">j&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">sorted&lt;/span>[&lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>];
&lt;span style="color:#a6e22e">sorted&lt;/span>[&lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">swap&lt;/span>;
}
}
}
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#a6e22e">sorted&lt;/span>);
}
&lt;span style="color:#a6e22e">getSport&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">string&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">of&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">config&lt;/span>.&lt;span style="color:#a6e22e">sport&lt;/span>);
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="our-component">Our Component:&lt;/h3>
&lt;p>And finally, our service is ready to be used by our library component normally. Here is the component content:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">TestLibraryComponent&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">OnInit&lt;/span> {
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">teams$&lt;/span>: &lt;span style="color:#66d9ef">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>{ &lt;span style="color:#a6e22e">country&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>; &lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span> }[]&lt;span style="color:#f92672">&amp;gt;&lt;/span>;
&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">title$&lt;/span>: &lt;span style="color:#66d9ef">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">string&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>;
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">testLibService&lt;/span>: &lt;span style="color:#66d9ef">TestLibraryService&lt;/span>) {}
&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">teams$&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">testLibService&lt;/span>.&lt;span style="color:#a6e22e">getTeams&lt;/span>();
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">title$&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">testLibService&lt;/span>.&lt;span style="color:#a6e22e">getTitle&lt;/span>();
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the template looks like this (&lt;em>Remember I am using Angular Material, you can replace everything easily with any UI Library like Bootstrap and it will still work&lt;/em>):&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-toolbar&lt;/span> &lt;span style="color:#a6e22e">color&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;primary&amp;#34;&lt;/span>&amp;gt; &amp;lt;&lt;span style="color:#f92672">span&lt;/span>&amp;gt;Demo App&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt; &amp;lt;/&lt;span style="color:#f92672">mat-toolbar&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">gdAuto&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span>
&lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">xs&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;600px&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlexOffset&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;calc(50% - 300px)&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">fxFlexOffset&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">xs&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;0&amp;#34;&lt;/span>
&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-card&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-card-header&lt;/span>&amp;gt;{{ title$ | async }}&amp;lt;/&lt;span style="color:#f92672">mat-card-header&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-card-content&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-list&lt;/span> &lt;span style="color:#a6e22e">role&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-list-item&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngFor&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;let x of teams$ | async; let i = index&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">role&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;listitem&amp;#34;&lt;/span>
&amp;gt;
{{ i + 1 }}. {{ x.country }} - {{ x.trophies }}&amp;lt;/&lt;span style="color:#f92672">mat-list-item&lt;/span>
&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-list&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-card-content&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-card&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, build the library:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng build –prod test-library
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="using-our-library-in-our-angular-app">Using our Library in our Angular App&lt;/h4>
&lt;p>After building the library is complete, go ahead and import it to your Angular application:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">TestLibraryModule&lt;/span>, &lt;span style="color:#a6e22e">TestLibConfig&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;test-library&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And add it to your imports array:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">TestLibraryModule&lt;/span>,
&lt;span style="color:#a6e22e">TestLibraryModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>(&lt;span style="color:#a6e22e">testLibConfigs&lt;/span>)
],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Don’t forget to define the &lt;code>testLibConfigs&lt;/code> constant which we are passing to the library:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">testLibConfigs&lt;/span>: &lt;span style="color:#66d9ef">TestLibConfig&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;World Cup Teams&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">teams&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">country&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;France&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">2&lt;/span>
},
{
&lt;span style="color:#a6e22e">country&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Brazil&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">5&lt;/span>
},
{
&lt;span style="color:#a6e22e">country&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Germany&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">4&lt;/span>
},
{
&lt;span style="color:#a6e22e">country&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Argentina&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">2&lt;/span>
},
{
&lt;span style="color:#a6e22e">country&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Spain&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">1&lt;/span>
},
{
&lt;span style="color:#a6e22e">country&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;England&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">1&lt;/span>
},
{
&lt;span style="color:#a6e22e">country&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Uruguay&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">2&lt;/span>
},
{
&lt;span style="color:#a6e22e">country&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Italy&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">trophies&lt;/span>: &lt;span style="color:#66d9ef">4&lt;/span>
}
],
&lt;span style="color:#a6e22e">sport&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Football/Soccer&amp;#39;&lt;/span>
};
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, you can now use the library component inside your app components as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">gdAuto&lt;/span>&amp;gt;&amp;lt;&lt;span style="color:#f92672">tl-test-library&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">tl-test-library&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Our demo library is using the prefix &lt;code>tl&lt;/code>. By default, libraries will use &lt;code>app&lt;/code> prefix just like a normal angular app. You can specify the prefix for the library when generating a library using &lt;code>--prefix&lt;/code> flag.&lt;/p>
&lt;/blockquote>
&lt;h3 id="deploying-your-library">Deploying your Library&lt;/h3>
&lt;p>When you have build your library, you will want to deploy it. To do that, just navigate to the build artefacts of your library and run NPM publish.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">cd dist/test-library
npm publish
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Angular 6 – Introduction to Progressive Web Apps</title><link>https://codinglatte.com/posts/angular/introduction-to-progressive-web-apps/</link><pubDate>Sat, 14 Jul 2018 01:22:13 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/introduction-to-progressive-web-apps/</guid><description>&lt;p>Earlier this week, I wrote a &lt;a href="https://codinglatte.com/tech/developers/angular/optimizing-your-angular-app-using-lazy-loading/">post&lt;/a> about optimizing your angular application using lazy loading. In this post, I will focus on Progressive Web Apps to further improve the performance and user experience.&lt;/p>
&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>The main goal of Progressive Web Apps (&lt;code>PWAs&lt;/code>) is to provide a reliable, fast and engaging experience to your users. This basically involves caching static resources of your web app on the browser or client device, while also utilizing a ServiceWorker to cache some requests based on predetermined rules.&lt;/p>
&lt;p>Basically, a ServiceWorker acts like an edge Content Delivery Network (CDN) on the client browser with almost zero latency. For instance, if you are operating a blog – the content of the blog post rarely changes once written. Therefore, there is no need to fetch it each time the user requests it or loads the page. It would be better if you could cache the blog post and only check for changes maybe every hour. This results to a much more smoother and rich experience for your users.&lt;/p>
&lt;p>If you are interested in learning more about the internals of PWAs, please visit this &lt;a href="https://developers.google.com/web/progressive-web-apps/">page&lt;/a>. The beauty of PWAs is that they will still work as normal website in older browsers or browsers. But in newer browsers, the experience is further enhanced. Another advantage is that it is possible to package and submit your PWA to &lt;a href="https://docs.microsoft.com/en-us/microsoft-edge/progressive-web-apps/microsoft-store">Microsoft Store&lt;/a> (For windows 10 users) increasing your audience significantly. A good example of this is the Twitter PWA. As major players continue to support PWAs, the benefits are only going to increase.&lt;/p>
&lt;h2 id="adding-support-for-pwas-to-your-app">Adding Support for PWAs to Your App&lt;/h2>
&lt;p>In Angular 6, adding support for PWA is almost too easy, thanks to &lt;a href="https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2">Schematics&lt;/a> support. With a single command, angular will download and install relevant libraries and setup the basics of PWAs and ServiceWorker. The command is:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng add @angular/pwa
&lt;/code>&lt;/pre>&lt;/div>&lt;p>When you run the above command, a web app manifest (&lt;code>manifest.json&lt;/code>) and an Angular ServiceWorker config (&lt;code>ngsw-config.json&lt;/code>) files are created. A web app manifest is a set of instructions to the browser on how the web app should behave once installed by the user. While the Angular ServiceWorker config file specifies which files and URLs to cache and how they should be updated.&lt;/p>
&lt;h3 id="service-worker-configurations">Service Worker Configurations&lt;/h3>
&lt;p>By default, the ServiceWorker looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;index&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/index.html&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;assetGroups&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;app&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;installMode&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;prefetch&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;resources&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;files&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;/favicon.ico&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/index.html&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/_.css&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/_.js&amp;#34;&lt;/span>]
}
},
{
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;installMode&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;lazy&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;updateMode&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;prefetch&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;resources&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;files&amp;#34;&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;/assets/**&amp;#34;&lt;/span>]
}
}
]
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will cache the following resources: index.html, favicon.ico, CSS and JavaScript build artefacts and your assets under assets directory. You can add any extra JS and CSS files you have to this list. You can find a detailed description of the service worker configuration file &lt;a href="https://angular.io/guide/service-worker-config">here&lt;/a>.&lt;/p>
&lt;h3 id="app-manifest-json">App Manifest JSON&lt;/h3>
&lt;p>On the other hand, the web app manifest looks like this by default:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;appname&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;short_name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;appname&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;theme_color&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;#1976d2&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;background_color&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;#fafafa&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;display&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;standalone&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;scope&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;start_url&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;icons&amp;#34;&lt;/span>: [
{
&lt;span style="color:#f92672">&amp;#34;src&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets/icons/icon-72x72.png&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sizes&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;72x72&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;image/png&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;src&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets/icons/icon-96x96.png&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sizes&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;96x96&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;image/png&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;src&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets/icons/icon-128x128.png&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sizes&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;128x128&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;image/png&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;src&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets/icons/icon-144x144.png&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sizes&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;144x144&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;image/png&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;src&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets/icons/icon-152x152.png&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sizes&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;152x152&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;image/png&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;src&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets/icons/icon-192x192.png&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sizes&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;192x192&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;image/png&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;src&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets/icons/icon-384x384.png&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sizes&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;384x384&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;image/png&amp;#34;&lt;/span>
},
{
&lt;span style="color:#f92672">&amp;#34;src&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;assets/icons/icon-512x512.png&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sizes&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;512x512&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;image/png&amp;#34;&lt;/span>
}
]
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first thing you would want to do is replace the icons under icons with your own. Then, change your app name to your full app name and short name to the shortest name possible a visitor is familiar with. And finally change the theme color and background color to your web apps colors. You can leave the rest as they are. For a more detailed description of the manifest file, please learn more &lt;a href="https://developers.google.com/web/fundamentals/web-app-manifest/">here&lt;/a>. A few key things to note here:&lt;/p>
&lt;ol>
&lt;li>Angular will only add the service worker to your app when you build with the production flag.&lt;/li>
&lt;li>Due to security reasons, you need an SSL/TLS certificate to use a ServiceWorker on your website. This setting is enforced by the browser and there is nothing much you can do about it. For testing purpose, you can test a ServiceWorker on localhost without an SSL Certificate. On the positive side of things – you can easily get a Let’s Encrypt certificate for free &lt;a href="https://www.sslforfree.com/">here&lt;/a> that works with any hosting.&lt;/li>
&lt;/ol></description></item><item><title>Optimizing your Angular App using Lazy Loading</title><link>https://codinglatte.com/posts/angular/optimizing-your-angular-app-using-lazy-loading/</link><pubDate>Sun, 08 Jul 2018 22:36:17 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/optimizing-your-angular-app-using-lazy-loading/</guid><description>&lt;p>Lazy loading is a technique where you defer loading of content until such a time it’s needed. In single page apps (SPA), usually the whole web app is loaded initially before rendering can even begin. This includes sections of the web app that a user doesn’t need immediately or might never need.&lt;/p>
&lt;p>The time it takes to load and render the initial view is usually high especially on slower connections. This is made worse if your app is very large. You can reduce the time it takes to load the initial view by breaking down your applications into smaller chunks, then loading them on demand i.e. &lt;code>Lazy Loading&lt;/code>.&lt;/p>
&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>Let’s take this scenario – If you have an app with three sections: Admin, Customer and Public sections. It’s very rare that visitors using the public section are interested in the admin or customer section. The components,  modules and content that are part of those two sections are more content the browser needs to download before it can render your app. The visitor might not even need those sections and you wasted their time and possibly data. It makes sense to break down your application into at least 3 chunks and load them when needed.&lt;/p>
&lt;p>So, if your application is over let’s say 2MB, and if the chunks are &lt;code>ideally&lt;/code> equal in size, they end up being about 600 – 700 KBS for each section which &lt;code>ideally&lt;/code> increases your loading times by about 66%. This can be further improved by breaking it down into smaller chunks for the individual section or lazy loading the content in the individual pages such as images and articles. This is entirely up to you as the developer.&lt;/p>
&lt;p>Before we can continue, you need to have a good grasp on the basics of angular and routing in angular. You can learn the basics of angular routing &lt;a href="https://angular.io/guide/router">here&lt;/a>.&lt;/p>
&lt;h2 id="getting-started-with-lazy-loading">Getting Started with Lazy Loading&lt;/h2>
&lt;p>Lazy loading works with angular route module, which supports it out of the box. If you are creating a new application, use the &lt;code>--routing&lt;/code> flag to automatically add routing module to your app.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng new application-name --routing
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: For Angular 7 and above, you can drop the &lt;code>--routing&lt;/code> flag, and angular CLI will prompt you whether you want to enable Routing for your new project.&lt;/p>
&lt;/blockquote>
&lt;p>This will generate a routing file (&lt;code>app-routing.module.ts&lt;/code>) next to the &lt;code>app.module.ts&lt;/code>. Inside the routing file, there will be an empty variable routes, where you place your routes.&lt;/p>
&lt;p>Next, you need to create a feature module (lazy loaded module) for each section of your app you want to lazy load. Ideally, they should be place at the root of the directory where all the components of that sections are placed.&lt;/p>
&lt;p>In our case, if we structured our application in such a way that all components for the admin section are in the admin directory, then the feature module for admin, should be placed inside the directory at the root (&lt;code>admin/admin.module.ts&lt;/code> and &lt;code>admin/admin-routing.module.ts&lt;/code>). To generate such a module, you use the &lt;code>ng generate (g) module module-name&lt;/code> command with &lt;code>--routing&lt;/code>and &lt;code>--flat&lt;/code> options.&lt;/p>
&lt;p>This generates a new module with a routing module at the root of the given directory. Learn more about ng generate for modules &lt;a href="https://github.com/angular/angular-cli/wiki/generate-module">here&lt;/a>.&lt;/p>
&lt;p>In our case, our command will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate module admin/admin --flat --routing
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can do the same for each of our other feature modules (I will refer to them as lazy loaded modules from now onwards) – guest and customer:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate module customer/customer --flat –routing
ng generate module guest/guest --flat –routing
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="adding-routes">Adding Routes&lt;/h3>
&lt;p>Next, you need to instruct the main module router, to load lazily the module modules you have just created. To do this, we need to provide &lt;code>path&lt;/code> and &lt;code>loadChildren&lt;/code> keys for each of our lazy loaded module in our route object.&lt;/p>
&lt;h4 id="after-angular-8">After Angular 8&lt;/h4>
&lt;p>Before the release of Angular 8, angular used a static custom string to import lazy loaded modules. This made it harder for Typescript and Linters to catch incorrect path or module until runtime. This changed with the release of Angular 8, which now uses Dynamic imports method to import Lazy Loaded Modules.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">[
{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;admin&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">loadChildren&lt;/span>&lt;span style="color:#f92672">:&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">import&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;./admin/admin.module&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">AdminModule&lt;/span>) &lt;span style="color:#75715e">// dynamic import
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }
];
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: If you use &lt;code>ng update&lt;/code> to update Angular to version 8, Angular will automatically convert the import paths from static custom string to dynamic import.&lt;/p>
&lt;/blockquote>
&lt;h4 id="before-angular-8">Before Angular 8&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">[
{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;admin&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">loadChildren&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./admin/admin.module#AdminModule&amp;#39;&lt;/span>
}
];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You must provide the path to the module followed by the module name, separated by a hash under the &lt;code>loadChildren&lt;/code> key. This should be done for all lazily loaded module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">[
{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;guest&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">loadChildren&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./guest/guest.module#GuestModule&amp;#39;&lt;/span>, &lt;span style="color:#75715e">// For Angular 7 and Below
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">loadChildren&lt;/span>&lt;span style="color:#f92672">:&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">import&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;./guest/Guest.module&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">GuestModule&lt;/span>) &lt;span style="color:#75715e">// For Angular 8, using dynamic import method
&lt;/span>&lt;span style="color:#75715e">&lt;/span> },
{
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;customer&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">loadChildren&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./customer/customer.module#CustomerModule&amp;#39;&lt;/span>, &lt;span style="color:#75715e">// For angular 7 and Below
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">loadChildren&lt;/span>&lt;span style="color:#f92672">:&lt;/span> () &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">import&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;./customer/customer.module&amp;#39;&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">CustomerModule&lt;/span>) &lt;span style="color:#75715e">// For Angular 8, using dynamic import method
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }
];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The routes in your feature module should look as your normal routes do. Also, take note that you can mix both lazy loaded routes and your normal routes.&lt;/p>
&lt;h2 id="shared-pipes-and-components">Shared Pipes and Components&lt;/h2>
&lt;p>Working with lazy loaded modules is not always as straight forward as you would like. For one, you can’t declare a component or a pipe in multiple modules in the same angular application. Also, you can’t use two components or pipes together that are not declared in the same module. These are some of the restrictions that I have come across and there could be more. But don’t worry, there are work around for this issues and others.&lt;/p>
&lt;p>If you have a component or a pipe you would like to share across multiple lazy loaded modules, you need to create a shared module. In that module, you must declare the Components and Pipes you need to share and then export them. Then, in the lazy loaded module you want to use the shared components and pipes, you import the shared module and you will have access to all components and pipes exported under the shared module. A shared module is just a normal module without routing. I prefer placing all my shared modules under a single directory.&lt;/p>
&lt;p>To generate such a module, use the &lt;code>ng generate module module-name --flat&lt;/code>. Then, declare (not import) all the pipes and components and the export them.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">NgModule&lt;/span>({
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">CommonModule&lt;/span>],
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">CustomComponent1&lt;/span>, &lt;span style="color:#a6e22e">CustomCompent2&lt;/span>, &lt;span style="color:#a6e22e">CustomComponent3&lt;/span>],
&lt;span style="color:#a6e22e">exports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">CustomComponent1&lt;/span>, &lt;span style="color:#a6e22e">CustomCompent2&lt;/span>, &lt;span style="color:#a6e22e">CustomComponent3&lt;/span>]
});
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">SharedModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Avoid creating large shared modules unless necessary. If you find yourself doing this, you need to evaluate your lazy loading approach and possibly change it.&lt;/p>
&lt;/blockquote>
&lt;h2 id="working-with-third-party-modules-packages-or-libraries">Working with Third Party Modules (Packages or Libraries)&lt;/h2>
&lt;p>This is where you will really rip the benefits of Lazy Loading if you rely heavily on large libraries. For each lazy loaded module, you must import only the needed Modules/Libraries it needs. This can significantly reduce the size of your chunks and reducing loading times of your application. A good example of this is &lt;a href="https://material.angular.io/">Angular Material&lt;/a>, which has a lot of &lt;a href="https://codinglatte.com/tech/developers/angular-material-and-bootstrap-framework-components-comparison/">material components&lt;/a> that needs to be imported. With lazy loading, you can only import only the material component you need per lazy loaded module.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can also bundle multiple modules under a single shared module to make it easier to import all these modules – just the same way as we did with shared components and pipes.&lt;/p>
&lt;/blockquote>
&lt;h2 id="working-with-services">Working with Services&lt;/h2>
&lt;p>Services in Angular are less problematic since there singleton. This means that there is only one instance of a service shared by the whole angular app. As such, you can provide services at the highest possible level of your apps lazy loading hierarchy. This allows all lazy loaded modules below to inherit the instance of your service(s). You can learn more about singleton services &lt;a href="https://angular.io/guide/singleton-services">here&lt;/a>.&lt;/p>
&lt;h2 id="final-thoughts">Final Thoughts&lt;/h2>
&lt;p>Lazy loading is just one of the many steps of optimizing an angular application. On top of lazy loading angular modules, you can also lazy load content such as images. You can use 3rd party libraries to achieve this. In the next few weeks, I am going to be covering more steps for optimizing your angular application, to reduce load times and improve the user experience.&lt;/p></description></item><item><title>#100DaysOfMLCode – Join the challenge and learn Machine Learning</title><link>https://codinglatte.com/posts/ml/100daysofmlcode-join-the-challenge-and-learn-machine-learning/</link><pubDate>Fri, 06 Jul 2018 23:36:43 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/ml/100daysofmlcode-join-the-challenge-and-learn-machine-learning/</guid><description>&lt;p>Machine Learning is the new cool kid in the block. It has huge application from Space Exploration to Finances, Medicine and Science. It is also estimated that demand for Machine Learning experts is going to increase for the foreseeable future, with an &lt;a href="https://www.livemint.com/Technology/rYudcXx0AA9UPXABa9ooFL/Demand-for-artificial-intelligence-machine-learning-experts.html">estimated increase of about 60%&lt;/a> this year alone. On top of that, the industry has gone through huge transformation over the last few years. Before, to be a machine learning expert, you needed to have a PHD (or some high education level), but that&amp;rsquo;s no longer the case. Due to the involvement of large tech companies like Alphabet (Google parent company), IBM, Microsoft and others, it is now easier for anyone to start a career in Machine Learning.&lt;/p>
&lt;h2 id="what-is-100daysofmlcode">What is #100DaysOfMLCode?&lt;/h2>
&lt;p>This is a challenge issued to Machine Learning developers (experts or newbies) to dedicate at least an hour a day for the next 100 days to learning and building machine learning models. I will let &lt;a href="https://github.com/llSourcell">Siraj Raval&lt;/a> explain this in the YouTube video below: &lt;a href="https://www.youtube.com/watch?v=cuQMBj1cWPo">https://www.youtube.com/watch?v=cuQMBj1cWPo&lt;/a> By accepting and committing to the challenge publicly, you are likely to be dedicated to the course. Also, the fact that you are not doing this alone will be a motivation to many people to stay true to the course. The challenge ends at the end of this year (2018). For more details about the challenge, visit the official github repo &lt;a href="https://github.com/llSourcell/100_Days_of_ML_Code">here&lt;/a>.&lt;/p>
&lt;h2 id="i-am-new-to-machine-learning">I am new to Machine Learning&lt;/h2>
&lt;p>If you are new to Machine Learning, there multiple resources which you can use to learn and am going to share them below. But before you can get started, I would like to suggest that you familiarize yourself with Python or R Programming languages. This is because majority of the tools you are going to come across will work natively with Python or R. Also, learning some mathematics especially in linear algebra and matrices will not hurt. If you are looking to getting started, below is a list of learning resources to help you:&lt;/p>
&lt;ol>
&lt;li>Machine Learning Crash &lt;a href="https://developers.google.com/machine-learning/crash-course/">Course by Google&lt;/a> – This is a free course by Google to introduce you to concepts of Machine Learning and &lt;a href="https://www.tensorflow.org/">TensorFlow&lt;/a>. It has been used by Google internally to train their ML engineers and comes highly recommended.&lt;/li>
&lt;li>A &lt;a href="https://github.com/llSourcell/Learn_Machine_Learning_in_3_Months">Guide&lt;/a> by Siraj Raval for Learning Machine Learning in 3 Months.&lt;/li>
&lt;li>&lt;a href="https://www.tensorflow.org/">io&lt;/a> – You can use this website to Learn Machine Learning concepts using a hands-on step by step interactive tutorial. You can also polish your Python programming skills using the same model if need be. I recommend this to those with minimal to little experience of Python Programming.&lt;/li>
&lt;li>YouTube – If you want to learn through demonstrations and short videos, just head over to YouTube and search for Machine Learning tutorials. Also, I would recommend you follow &lt;a href="https://www.youtube.com/channel/UCWN3xxRkmTPmbKwht9FuE5A">Siraj Raval&lt;/a> and &lt;a href="https://www.youtube.com/channel/UC0rqucBdTuFTjJiefW5t-IQ">TensorFlow&lt;/a> YouTube Channel.&lt;/li>
&lt;li>And finally, &lt;a href="https://www.kaggle.com/learn/overview">Kaggle&lt;/a> – A great platform where you can learn Machine Learning.&lt;/li>
&lt;/ol>
&lt;p>I will keep updating this article for new learning resources as I come across them. Join &lt;a href="https://twitter.com/search?q=%23100DaysOfMLCode&amp;amp;src=tyah">#100DaysOfMLCode&lt;/a> movement on twitter and together let us master Machine Learning. And remember to spread the love, don’t do this alone.&lt;/p></description></item><item><title>Using custom date formats for Angular Material Date Picker</title><link>https://codinglatte.com/posts/angular/custom-date-formats-angular-material-date-picker/</link><pubDate>Tue, 03 Jul 2018 19:29:11 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/custom-date-formats-angular-material-date-picker/</guid><description>&lt;p>Angular material has a very nice date picker but while its functionality can accommodate a lot of developers, sometimes it just falls short. For instance, I find it very inflexible when dealing with date formats. While I understand that it’s nice to have a common date format for the whole application, sometimes you need to be able to set date formats on the fly without breaking your back. Sometimes all you need is a simple solution that is ready to be used anywhere in your application.&lt;/p>
&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>This tutorial assumes you have some knowledge in Angular and Angular Material, because I won’t go into details on the basics like setting up modules. You can learn more about Angular &lt;a href="https://angular.io/guide/quickstart">here&lt;/a> and Angular Material &lt;a href="https://material.angular.io/guide/getting-started">here&lt;/a>. This tutorial has been tested with Angular 6, but I expect it to work with Angular 5 as well but not any earlier version than that.&lt;/p>
&lt;p>We will be using &lt;code>ControlValueAccessor&lt;/code> from &lt;code>@angular/forms&lt;/code> to create a custom form component that will wrap around &lt;code>Angular Material Date Picker&lt;/code> component. The new component will extend the Material Date Picker component and allow you to pass a date format in which to use. To format the date, we will use &lt;code>MomentJS&lt;/code> which you can learn more about &lt;a href="https://momentjs.com/">here&lt;/a>. Feel free to use a different library or rely with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">JavaScript/Typescript&lt;/a> in build methods.&lt;/p>
&lt;p>In the demo for this tutorial, we will have multiple Date Pickers that give back different date formats. To simplify this tutorial, I will ignore all &lt;a href="https://material.angular.io/components/datepicker/api">properties&lt;/a> of Angular Material Date Pickerthat are optional like minimum and maximum date. This can easily be remedied by passing them as options in your component using the &lt;a href="https://angular.io/guide/component-interaction">&lt;code>Input()&lt;/code>&lt;/a> method. This method allows parent components to pass variables to child component, you can learn more about this &lt;a href="https://angular.io/guide/component-interaction">here&lt;/a>.&lt;/p>
&lt;p>You can play with this tutorial demo &lt;a href="https://angular-material-date-picker.s3-us-west-2.amazonaws.com/index.html">here&lt;/a>.&lt;/p>
&lt;h2 id="getting-started">Getting Started&lt;/h2>
&lt;p>To get started, you need to install (using either NPM or Yarn) the following packages: &lt;code>momentjs&lt;/code>, &lt;code>angular-material&lt;/code>, &lt;code>angular-flex-layout&lt;/code> and &lt;code>material-moment-adapter&lt;/code> inside your angular application. You can install them using Yarn in one command as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">yarn add –dev @angular/material moment @angular/material-moment-adapter @angular/flex-layout
&lt;/code>&lt;/pre>&lt;/div>&lt;p>For those using Angular 6, you can install angular material using the new ng new command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng add @angular/material
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally import the following in your main NgModules file:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
MatDatepickerModule,
MatInputModule,
MatFormFieldModule,
FlexLayoutModule,
MatCardModule
&lt;/code>&lt;/pre>&lt;/div>&lt;p>On top of Angular Material, I am using &lt;a href="https://github.com/angular/flex-layout/wiki">Angular Flex Layout&lt;/a>, which you can learn more about &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-better-than-bootstrap/">here&lt;/a>.&lt;/p>
&lt;h2 id="create-custom-date-picker-component">Create Custom Date Picker Component&lt;/h2>
&lt;p>Next, create a new component – &lt;code>date-picker-component&lt;/code> – using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng new component date-picker
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This component will have our Material Date Picker inside it but will read and format the date as we want. It will also accept date input incase we have an initial date or are setting it programmatically from an API. Inside the component typescript file, we are going to implement &lt;code>ControlValueAccessor&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">DatePickerComponent&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">ControlValueAccessor&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, we are going to add a provider for the component, as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">NG_VALUE_ACCESSOR&lt;/span>,
&lt;span style="color:#a6e22e">useExisting&lt;/span>: &lt;span style="color:#66d9ef">forwardRef&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">DatePickerComponent&lt;/span>), &lt;span style="color:#75715e">//Name of our component
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
}
];
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NB:&lt;/strong> Remember to import remember the necessary imports for the component as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Component&lt;/span>, &lt;span style="color:#a6e22e">forwardRef&lt;/span>, &lt;span style="color:#a6e22e">Input&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">ControlValueAccessor&lt;/span>, &lt;span style="color:#a6e22e">NG_VALUE_ACCESSOR&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/forms&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MatDatepickerInputEvent&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/material/datepicker&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">moment&lt;/span> &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;moment&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Inside our component, we need to add a get and set method for the value of the date. We start by declaring a property of the form &lt;code>_dateValue&lt;/code> (note the preceding underscore) and then creating the two methods to set and get the value of the &lt;code>_dateValue&lt;/code> property:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Input&lt;/span>() &lt;span style="color:#a6e22e">_dateValue&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#a6e22e">get&lt;/span> &lt;span style="color:#a6e22e">dateValue() {&lt;/span>
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">moment&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_dateValue&lt;/span>, &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">format&lt;/span>);
}
&lt;span style="color:#a6e22e">set&lt;/span> &lt;span style="color:#a6e22e">dateValue&lt;/span>(&lt;span style="color:#a6e22e">val&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_dateValue&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">moment&lt;/span>(&lt;span style="color:#a6e22e">val&lt;/span>).&lt;span style="color:#a6e22e">format&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">format&lt;/span>);
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span>(&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">_dateValue&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>On top of those two methods, you need the following methods – which I won’t go into details about:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">addEvent&lt;/span>(&lt;span style="color:#a6e22e">type&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">event&lt;/span>: &lt;span style="color:#66d9ef">MatDatepickerInputEvent&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>Date&lt;span style="color:#f92672">&amp;gt;&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">dateValue&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">moment&lt;/span>(&lt;span style="color:#a6e22e">event&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>, &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">format&lt;/span>);
}
&lt;span style="color:#a6e22e">writeValue&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) {
    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">value&lt;/span> &lt;span style="color:#f92672">!==&lt;/span> &lt;span style="color:#66d9ef">undefined&lt;/span>) {
      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">dateValue&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">moment&lt;/span>(&lt;span style="color:#a6e22e">value&lt;/span>, &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">format&lt;/span>);
    }
}
&lt;span style="color:#a6e22e">propagateChange&lt;/span> &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#a6e22e">_&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {};
&lt;span style="color:#a6e22e">registerOnChange&lt;/span>(&lt;span style="color:#a6e22e">fn&lt;/span>) {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">propagateChange&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">fn&lt;/span>;
}
&lt;span style="color:#a6e22e">registerOnTouched() {&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We also need a placeholder and format property in our component. The placeholder will be passed to the Material Date Picker Component as a placeholder text. While format property will be used to format the value of the Date Picker when getting.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Input&lt;/span>() &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">placeholder&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#66d9ef">@Input&lt;/span>() &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">format&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;YYYY/MM/DD HH:mm:ss&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, to our component template, where we will add a normal Material Date Picker input field:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-form-field&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-datepicker-toggle&lt;/span> &lt;span style="color:#a6e22e">matPrefix&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">for&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">picker&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">mat-datepicker-toggle&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">input&lt;/span>
&lt;span style="color:#a6e22e">matInput&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">matDatepicker&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">picker&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">value&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">dateValue&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">dateInput&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">addEvent&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">input&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;,&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
/&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-datepicker&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">picker&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">mat-datepicker&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-form-field&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that’s it, you have now a custom date picker that you can use anywhere in your application:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-date-picker&lt;/span>
&lt;span style="color:#a6e22e">placeholder&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Enter The First Date&amp;#34;&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">[(&lt;/span>&lt;span style="color:#a6e22e">ngModel&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">firstDate&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span>
&lt;span style="color:#a6e22e">format&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;YYYY/MM/DD HH:mm:ss&amp;#34;&lt;/span>
&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-date-picker&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can find the above code on github, here is the &lt;a href="https://github.com/MainaWycliffe/Custom-Date-Format-using-Material-DatePicker">link&lt;/a>. If you have any questions, please leave it on the comment section below.&lt;/p></description></item><item><title>Angular 6 - Angular CLI Workspaces</title><link>https://codinglatte.com/posts/angular/angular-6-angular-cli-workspaces/</link><pubDate>Sat, 02 Jun 2018 14:36:05 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-6-angular-cli-workspaces/</guid><description>&lt;p>One of the least talked about features of Angular 6 is Angular CLI Workspaces. Workspaces or Angular CLI Workspaces give angular developers the ability to have more than one project in one workspace. This brings all your projects under the same workspace. This is not limited to applications but also angular libraries. This gives developers the freedom of breaking down large applications into smaller applications and modules. The modules such as authentication module can then be shared across the applications using those specific modules. This improves the workflow by reducing code repetition using shared libraries that are generated and managed by Angular CLI.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>To use Angular CLI Workspaces, you must be running the latest version of Angular, Angular 6. If you are using an earlier version of Angular in your project, please upgrade by following the instructions &lt;a href="https://update.angular.io/">here&lt;/a>.&lt;/p>
&lt;p>For a new project, there is nothing special about creating a new one:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng new application-name
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will look like any other angular project, with all your source code being under &lt;code>src&lt;/code> directory. To add another angular project (application or library) to your application, you use the &lt;code>ng generate command&lt;/code>. This is the same command you use to generate new components, services, classes etc.&lt;/p>
&lt;h4 id="generating-a-new-application">Generating a new application&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate application *new-application-name*
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="generating-a-new-library">Generating a new library&lt;/h4>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng generate library *library-name*
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> You can learn more about ng generate command &lt;a href="https://github.com/angular/angular-cli/wiki/generate">here&lt;/a>. By default, all new applications and libraries are placed under the projects directory in the root of the angular workspace. You can change this by modifying the &lt;code>angular.json&lt;/code> file in the root of your workspace, then modify the &lt;code>newProjectRoot&lt;/code> to your preferred directory.&lt;/p>
&lt;/blockquote>
&lt;h3 id="running-ng-generate-on-new-projects">Running ng generate on new Projects&lt;/h3>
&lt;p>The initial application in your workspace is the default application. This means that when you run angular cli commands like ng generate component without specifying the project, then they are automatically generated in the default application. To generate components, services, classes etc. for the new projects you must provide the project option, as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng g c my-new-component --project application-name
ng g s my-new-service --project application-name
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The same applies to libraries:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng g c my-new-component --project library-name
ng g s my-new-service --project library-name
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="building-and-running-different-projects">Building and Running Different Projects&lt;/h3>
&lt;p>This is the easy part. When building or serving your application, you only need to add your project name to your build command, as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng serve application-name --aot
ng build application-name –prod
ng build library-name --prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can skip the project name when building or serving the default project.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng serve --aot
ng build --prod
ng build –prod
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The build files can be located in a &lt;code>project folder&lt;/code> under &lt;code>dist&lt;/code> folder in the root of your workspace. For instance, if the project name is project1, then they will be located under &lt;code>dist/project1&lt;/code> folder.&lt;/p>
&lt;h3 id="final-thoughts">Final Thoughts&lt;/h3>
&lt;p>Angular CLI Workspaces is not a perfect tool but will improve with each release of Angular in the future. It would be nice if all projects could be placed under a single projects folder and not one for generated project and the src directory for the initial project. The other downside I came across is lack of or scattered documentation although this can be attributed to the fact that not many developers are using it for now. That being said, it’s a simple to use tool yet very effective that you should definitely give a try. In my case, I am already using it for most of my projects.&lt;/p></description></item><item><title>Automate Deployment of Angular Apps using AWS CodeBuild</title><link>https://codinglatte.com/posts/angular/automate-deployment-of-angular-apps-using-aws-codebuild/</link><pubDate>Thu, 10 May 2018 13:42:46 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/automate-deployment-of-angular-apps-using-aws-codebuild/</guid><description>&lt;p>Building and deploying Angular app is very time consuming, especially with large application. You also must keep track of which branch you are deploying to which environment and a little mix-up could be catastrophic. You can smoothen the building and deployment of your application using AWS CodeBuild. “AWS CodeBuild is a fully managed build service that compiles source code, runs tests, and produces software packages that are ready to deploy.”&lt;/p>
&lt;h1 id="what-we-are-going-to-use">What we are going to use&lt;/h1>
&lt;ol>
&lt;li>An AWS Account, if you don’t have one you can create on &lt;a href="https://portal.aws.amazon.com/billing/signup#/start">here&lt;/a>. They have a 12 Month Free tier which you can learn more about &lt;a href="https://aws.amazon.com/free/">here&lt;/a>.&lt;/li>
&lt;li>AWS CodeCommit/Github Repository.&lt;/li>
&lt;li>AWS CodeBuild, CodePipeline, S3 and CloudFront for Deployment.&lt;/li>
&lt;li>Angular Project with GIT Enabled&lt;/li>
&lt;/ol>
&lt;blockquote>
&lt;p>NB: AWS charges for using the above resources, please cleanup after you are done using them.&lt;/p>
&lt;/blockquote>
&lt;h1 id="how-does-it-work">How does it work&lt;/h1>
&lt;ol>
&lt;li>AWS CodePipeline will detect changes on our repository, then will initiate the process of automatically building and deploying our app to an S3 bucket.&lt;/li>
&lt;li>Then it will launch AWS CodeBuild to build and deploy the application on an S3 Bucket of your choice.&lt;/li>
&lt;/ol>
&lt;h2 id="preparations">Preparations&lt;/h2>
&lt;h3 id="aws-s3">AWS S3&lt;/h3>
&lt;p>You will need to create a new bucket and then give AWS CodeBuild permission to access and put the build files inside the S3 Bucket. If you don’t know how to create an S3 bucket, please follow this official &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html">guide&lt;/a>. For permissions, we will cover this at the end of this post.&lt;/p>
&lt;h2 id="getting-started">Getting Started&lt;/h2>
&lt;p>First, head over to AWS CodeCommit on AWS using the following &lt;a href="https://us-west-2.console.aws.amazon.com/codepipeline/home?region=us-west-2#/intro">link&lt;/a>. Your window will probably look like the one below:&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/05/AWS-CodePipeline-ScreenShot-1024x463.png" alt="Automate Deployment of Angular Apps using AWS CodeBuild">&lt;/p>
&lt;p>Click on &lt;strong>Getting Started&lt;/strong> or &lt;strong>Create Pipeline&lt;/strong> to get started. You will be presented with the following window, where there are six steps to follow for you to create your new pipeline. Let’s go through them step by step. If you are already familiar with AWS CodePipeline you can skip this guide up to Step 3.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/05/AWS-CodePipeline-ScreenShot-2-1024x483.png" alt="Automate Deployment of Angular Apps using AWS CodeBuild">&lt;/p>
&lt;h3 id="step-1-enter-pipeline-name-self-explanatory">Step 1: Enter Pipeline Name (Self Explanatory).&lt;/h3>
&lt;p>Please enter an Appropriate Name for your pipeline.&lt;/p>
&lt;h3 id="step-2-select-source-for-your-pipeline">Step 2: Select Source for your Pipeline&lt;/h3>
&lt;p>This is the location of your Angular Source Code. It could be either &lt;strong>AWS CodeCommit Repo, S3 Bucket Files or Github Rep&lt;/strong>. Select the source in the drop down, in our case we will use either Github or AWS CodeCommit. If you select Github, then click on the “Connect Github” button and follow the steps to authorize AWS Access. Then select the repository and the branch you would like to automatically detect changes and build.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/05/AWS-CodePipeline-ScreenShot-3-1024x486.png" alt="Automate Deployment of Angular Apps using AWS CodeBuild">&lt;/p>
&lt;p>If you select AWS CodeCommit, please select the appropriate repository and branch to automatically build. You can leave the rest of the settings as they are.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/05/AWS-CodePipeline-ScreenShot-4-1024x484.png" alt="Automate Deployment of Angular Apps using AWS CodeBuild">&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Please Note:&lt;/strong> For AWS CodeCommit, the repo you wish to connect to AWS CodePipeline must be in the same region as the one you are creating the pipeline for. You can change the region you are in by clicking on the drop-down button between Your account and Support at the top right corner of your browser. The default region is North Virginia.&lt;/p>
&lt;/blockquote>
&lt;h3 id="step-3-build">Step 3: Build&lt;/h3>
&lt;p>This is what this whole article is about. Here we are going to setup CodeBuild to automatically build our application and deploy to an S3 Bucket.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2018/05/AWS-CodePipeline-ScreenShot-5-1024x507.png" alt="Automate Deployment of Angular Apps using AWS CodeBuild">&lt;/p>
&lt;p>Under &lt;strong>Build Provider&lt;/strong>, select CodeBuild, then under &lt;strong>configure your project&lt;/strong>, select &lt;strong>Create a New Build Project&lt;/strong> under &lt;strong>AWS CodeBuild&lt;/strong>.&lt;/p>
&lt;h5 id="creating-a-new-build-project">Creating a new Build Project:&lt;/h5>
&lt;ol>
&lt;li>Enter an appropriate name of the New Project. No spaces.&lt;/li>
&lt;li>Under &lt;code>Environment Image&lt;/code>, select ubuntu.&lt;/li>
&lt;li>Then under &lt;code>Operating System&lt;/code>, Select &lt;code>Ubuntu 14&lt;/code>&lt;/li>
&lt;li>Then under &lt;code>Runtime&lt;/code>, Select Base (Not NodeJS) and then Select the Appropriate Version (As at the time of writing, this was Ubuntu 14) below that.&lt;/li>
&lt;li>Under &lt;code>Build Specification&lt;/code>, we are going to be using &lt;code>yaml&lt;/code> file at the root of our project that will provide all commands to build our Angular Project. I will provide a sample for angular later in the post. You can learn more about Build Spec File &lt;a href="https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html">here&lt;/a>.&lt;/li>
&lt;li>You can leave the rest as they are.&lt;/li>
&lt;li>Save the Build Project.&lt;/li>
&lt;/ol>
&lt;p>Once the Build Project has been created successfully, let’s go ahead and get the &lt;code>Service Role name&lt;/code>. We are going to need this to configure AWS CodeBuild permission to put the built project on AWS S3. &lt;img src="https://codinglatte.com/wp-content/uploads/2018/05/AWS-CodePipeline-ScreenShot-6-1024x485.png" alt="Automate Deployment of Angular Apps using AWS CodeBuild">&lt;/p>
&lt;ol>
&lt;li>Click on the &lt;strong>View Project Details&lt;/strong> &lt;em>This will open in a new window&lt;/em>.&lt;/li>
&lt;li>Click on &lt;strong>Edit Project&lt;/strong>, then scroll down to &lt;code>Service Role&lt;/code> and take note of the &lt;code>Service Role Name&lt;/code>.&lt;/li>
&lt;li>Then, head over to &lt;a href="https://console.aws.amazon.com/iam/home?#/home">AWS IAM (Identity and Access Management)&lt;/a> on the console.&lt;/li>
&lt;li>On the left panel, select&lt;/li>
&lt;li>Then search and open the role of the CodeBuild Project you took note of above.&lt;/li>
&lt;li>Copy the &lt;strong>Role ARN&lt;/strong>, we will need this when configuring access to the bucket.&lt;/li>
&lt;/ol>
&lt;p>&lt;img src="//wp-content/uploads/2018/05/aws-codepipeline-screenshot-7-1024x511.png" alt="Automate Deployment of Angular Apps using AWS CodeBuild">&lt;/p>
&lt;h4 id="step-4-deploy">Step 4 Deploy&lt;/h4>
&lt;p>We already took care of deployment under the last step, so select &lt;strong>No Deployment&lt;/strong> option. This is because CodePipeline doesn’t have the option to deploy to an S3 bucket. We will automatically deploy to an S3 bucket after building the project using &lt;a href="https://aws.amazon.com/cli/">aws-cli&lt;/a> – it is installed automatically in the build server.&lt;/p>
&lt;h4 id="step-5-service-role">Step 5 Service Role&lt;/h4>
&lt;p>Create a new &lt;strong>Aws Service Role&lt;/strong> for CodePipeline and click on next.&lt;/p>
&lt;h4 id="step-6-review">Step 6 Review&lt;/h4>
&lt;p>Review the details of the Pipeline and click on create at the bottom.&lt;/p>
&lt;h3 id="configuring-your-project">Configuring Your Project&lt;/h3>
&lt;p>To build your project, we need to add the commands to install all &lt;code>npm packages (Dependencies).&lt;/code>  Then it will run &lt;code>ng build&lt;/code> and copy all the files inside &lt;code>/dist&lt;/code> directory (or wherever the location of your build artefacts are placed) to the s3 bucket. To do this add a new file to the root of the project known as &lt;code>buildspec.yaml&lt;/code>. Then add the following content: (Read the moment for what each line of command does)&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">version&lt;/span>: &lt;span style="color:#ae81ff">0.2&lt;/span>
&lt;span style="color:#66d9ef">env&lt;/span>:
    &lt;span style="color:#66d9ef">variables&lt;/span>:
        &lt;span style="color:#66d9ef">S3_BUCKET&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;&amp;lt;S3_BUCKET_HERE&amp;gt;&amp;#34;&lt;/span>
&lt;span style="color:#66d9ef">APP_NAME&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;&amp;lt;APP_NAME_HERE&amp;gt;&amp;#34;&lt;/span>
&lt;span style="color:#66d9ef">BUILD_ENV &lt;/span>: &lt;span style="color:#e6db74">&amp;#34;prod&amp;#34;&lt;/span>
&lt;span style="color:#66d9ef">phases&lt;/span>:
    &lt;span style="color:#66d9ef">install&lt;/span>:
        &lt;span style="color:#66d9ef">commands&lt;/span>:
&lt;span style="color:#75715e"># Download and Install NodeJS 8.0&lt;/span>
        - curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash &lt;span style="color:#e6db74">-
&lt;/span>&lt;span style="color:#e6db74">        - sudo apt-get install -y nodejs&lt;/span>
        - echo Installing source NPM dependencies...
        &lt;span style="color:#75715e"># Install http drivers for node&lt;/span>
        - sudo apt-get update -y
        - sudo apt-get install -y apt-transport-https
        &lt;span style="color:#75715e"># Install Yarn Package Manager (Replace the commands below if you using NPM).&lt;/span>
        - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add &lt;span style="color:#e6db74">-
&lt;/span>&lt;span style="color:#e6db74">        - echo &amp;#34;deb https://dl.yarnpkg.com/debian/ stable main&amp;#34; | sudo tee /etc/apt/sources.list.d/yarn.list&lt;/span>
        - sudo apt-get update -y
        - sudo apt-get install -y yarn
        &lt;span style="color:#75715e"># Install Angular CLI, If you are not using Angular 6, install angular/cli@1.7.0 or lower, confirm by running ng -v inside your project folder&lt;/span>
        - yarn global add @angular/cli@&lt;span style="color:#ae81ff">6.0.8&lt;/span>
        &lt;span style="color:#75715e"># Install node dependancies.&lt;/span>
        - yarn install
&lt;span style="color:#66d9ef">build&lt;/span>:
        &lt;span style="color:#66d9ef">commands&lt;/span>:
        &lt;span style="color:#75715e"># Builds Angular application. You can also build using custom environment here like mock or staging&lt;/span>
        - echo Build started on `date`
        - ng build --${BUILD_ENV}
&lt;span style="color:#66d9ef">post_build&lt;/span>:
        &lt;span style="color:#66d9ef">commands&lt;/span>:
        &lt;span style="color:#75715e"># Clear S3 bucket.&lt;/span>
        - aws s3 rm s3://${S3_BUCKET} --recursive
        - echo S3 bucket is cleared.
        &lt;span style="color:#75715e"># Copy dist folder to S3 bucket, As of Angular 6, builds are stored inside an app folder in distribution and not at the root of the dist folder&lt;/span>
        - aws s3 cp dist s3://${S3_BUCKET}/${APP_NAME} --recursive
        - echo Build completed on `date`
&lt;span style="color:#66d9ef">artifacts&lt;/span>:
    &lt;span style="color:#66d9ef">files&lt;/span>:
        - &lt;span style="color:#e6db74">&amp;#39;/&amp;#39;&lt;/span>
    &lt;span style="color:#66d9ef">discard-paths&lt;/span>: yes
    &lt;span style="color:#66d9ef">base-directory&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;dist*&amp;#39;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you can see, am using &lt;a href="https://codinglatte.com/tech/developers/angular/setup-angular-touse-yarn-package-manager/">Yarn Package Manager&lt;/a> for my project, but you can replace the Yarn commands with NPM commands. And finally, we need to allow our CodeBuild permission to write and delete in to our S3 Bucket, otherwise this won’t work.&lt;/p>
&lt;h3 id="revisiting-aws-s3-bucket-permission">Revisiting AWS S3 Bucket Permission&lt;/h3>
&lt;p>Head over to AWS S3 Bucket management interface and open your bucket. Then under &lt;strong>Permissions&lt;/strong>, you open &lt;strong>Bucket Policy&lt;/strong>. We need to modify the policy to include the role you copied when you create the CodeBuild Project up there. Under statement, add a new object (JSON Object) and Add the following content:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#f92672">&amp;#34;Sid&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;CodeBuildPermision&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;Effect&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Allow&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;Principal&amp;#34;&lt;/span>: {
&lt;span style="color:#f92672">&amp;#34;AWS&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;&amp;lt; ROLE ARN HERE&amp;gt;&amp;#34;&lt;/span>
},
&lt;span style="color:#f92672">&amp;#34;Action&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;s3:*&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;Resource&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;arn:aws:s3:::your-bucket-name &amp;#34;&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Replace &lt;code>your-bucket-name&lt;/code> with your own bucket name and &lt;code>ROLE ARN&lt;/code> from Step 3 Above. Finally, you need to be able to access your web app over the internet, to do this configure your S3 Bucket for Web Hosting and add a domain name if need be.
This guide &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html">here&lt;/a> will help you configure your bucket for web hosting.&lt;/p></description></item><item><title>How to Build Adaptive Layout Design using Angular Flex Layout</title><link>https://codinglatte.com/posts/angular/building-adaptive-layouts-using-angular-flex-layout/</link><pubDate>Sat, 21 Apr 2018 21:21:33 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/building-adaptive-layouts-using-angular-flex-layout/</guid><description>&lt;p>Angular Flex Layout is a powerful layout tool available for Angular. It provides an API than can be easily used in both component templates and class allowing you to adaptively react to the device screen size. If you are new to Angular Flex Layout and Adaptive Layout design, please check out my earlier post &lt;a href="https://codinglatte.com/tech/developers/angular/adaptive-layout-design-angular-flex-layout/">here&lt;/a>.&lt;/p>
&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>In today’s example, I will create a simple example that will display a form in either modal window or new page based on screen size.  In small screen sizes – smartphones &amp;amp; phablets – it will show the form in a new page while in large devices it will display a simple modal window with the form. The form component will be the same in both instances, ensuring consistency and making it easy to update.&lt;/p>
&lt;h2 id="why">Why?&lt;/h2>
&lt;p>The reason for this is quite simple: A modal window provides a much better user experience when screen real estate is not an issue while in smaller devices it just makes things worse. With adaptive layout design you get to achieve both without compromising a lot, just some extra code to check the screen size.&lt;/p>
&lt;h2 id="getting-started">Getting Started&lt;/h2>
&lt;p>In this example, we will be using both Angular Flex Layout and Angular Material. This post assumes you know the basics of &lt;a href="https://angular.io/guide/quickstart">Angular&lt;/a> and &lt;a href="https://material.angular.io/guide/getting-started">Angular Material&lt;/a>. You can install both using either NPM or Yarn Package Manager as shown below.&lt;/p>
&lt;p>&lt;strong>NPM:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">npm install @angular/flex @angular/material @angular/cdk
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Or Yarn:&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">yarn add @angular/flex @angular/material @angular/cdk
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Go ahead and import Angular Flex Layout to your project.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/flex-layout&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the case of Angular Material, we are only going to require two modules – &lt;a href="https://material.angular.io/components/dialog/overview">&lt;code>MatDialog&lt;/code>&lt;/a> and &lt;a href="https://material.angular.io/components/snack-bar/overview">&lt;code>MatSnackbar&lt;/code>&lt;/a> Modules. Import them to your project too.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MatSnackBarModule&lt;/span>, &lt;span style="color:#a6e22e">MatDialogModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/material&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then Add them to the list of imports&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#a6e22e">BrowserModule&lt;/span>,
&lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span>,
&lt;span style="color:#a6e22e">MatSnackBarModule&lt;/span>,
&lt;span style="color:#a6e22e">MatDialogModule&lt;/span>,
&lt;span style="color:#a6e22e">MatButtonModule&lt;/span>
&lt;span style="color:#a6e22e">RouterModule&lt;/span>
  ],
  &lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="how-it-works">How it works&lt;/h2>
&lt;p>We are going to have 4 components in our project.&lt;/p>
&lt;ol>
&lt;li>App Component (app.component.ts)&lt;/li>
&lt;li>Main Component&lt;/li>
&lt;li>Form Component&lt;/li>
&lt;li>Page Wrapper Component&lt;/li>
&lt;li>Dialog Wrapper Component&lt;/li>
&lt;/ol>
&lt;p>The two-wrapper component are there to make thing simple: providing a container for the &lt;code>form component&lt;/code> while also injecting any data the &lt;code>Form Component&lt;/code> may require. This is necessary since a dialog uses data attribute to pass data to dialog component while pages use URL query parameters. Checking whether it was loaded as a page or modal dialog at the form component just complicates everything. So, in our case, when loading a dialog - we load the Dialog Wrapper Component which in turn loads the form component as a child. And when loading the page – We load the Page Wrapper Component which in turn loads the form component as a child.&lt;/p>
&lt;h3 id="code-highlights">Code Highlights&lt;/h3>
&lt;p>I won’t go over all details in the code, I will share the Github repo, but let me highlight the key parts that you should take note:&lt;/p>
&lt;h4 id="main-component">Main Component&lt;/h4>
&lt;p>This is where the open button is located. Make sure to inject &lt;code>ObservableMedia&lt;/code>, &lt;code>MatDialog&lt;/code> and &lt;code>Router&lt;/code> in to the component under constructor. &lt;code>ObservableMedia&lt;/code> is from Angular Flex Layout and will allow you to query the screen size in real time as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#a6e22e">message?&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
    &lt;span style="color:#75715e">//query screen size
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">media&lt;/span>.&lt;span style="color:#a6e22e">isActive&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;lt-md&amp;#34;&lt;/span>)) {
      &lt;span style="color:#75715e">//redirect
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#34;/open-form&amp;#34;&lt;/span>]);
    } &lt;span style="color:#66d9ef">else&lt;/span> {
      &lt;span style="color:#75715e">//show dialog
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">d&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">matDialog&lt;/span>.&lt;span style="color:#a6e22e">open&lt;/span>(&lt;span style="color:#a6e22e">ModalWrapperComponent&lt;/span>, {
        &lt;span style="color:#a6e22e">hasBackdrop&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
        &lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
          &lt;span style="color:#a6e22e">message&lt;/span>: &lt;span style="color:#66d9ef">message&lt;/span>
        }
      });
&lt;span style="color:#a6e22e">d&lt;/span>.&lt;span style="color:#a6e22e">afterClosed&lt;/span>().&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">results&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
        &lt;span style="color:#75715e">//do something like show a message box
&lt;/span>&lt;span style="color:#75715e">&lt;/span>        &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#34;/open&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">message&lt;/span>]);
      });
    }
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> I Am loading the &lt;code>ModalWrapperComponent&lt;/code> instead of the &lt;code>FormComponent&lt;/code> in the dialog. First, I check to see whether the screen size is less than medium (&lt;code>lt-md&lt;/code>) and navigate to page housing the &lt;code>FormComponent&lt;/code>.&lt;/p>
&lt;/blockquote>
&lt;p>In all other cases I load a modal dialog of the &lt;code>FormCompponent&lt;/code> instead. Please refer to the image below for different breaking points for Angular Flex Layout.&lt;/p>
&lt;p>&lt;img src="http://theinfogridc.com/wp-content/uploads/2017/11/screen-sizes.png" alt="Default Breakpoints for Angular Flex Layout">&lt;/p>
&lt;p>The message for modal dialog is passed under data inside config options while its passed a router parameter when navigating to another page.&lt;/p>
&lt;h4 id="form-component">Form Component&lt;/h4>
&lt;p>The form component for now will just show the message passed to it and will not have anything special to it. To do this it needs an input and an output for the form. The input allows the parent component (wrapper components in our case) to pass the message to the form. The output on the other hand allows the child component (Form component in our case) to pass events and data back to our parent component. This is done to keep things as simple as possible.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Input&lt;/span>() &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">message&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#66d9ef">@Output&lt;/span>() &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">output&lt;/span>: &lt;span style="color:#66d9ef">EventEmitter&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">EventEmitter&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">boolean&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>();
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Since our variables are public, you can use them directly on the template as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">p&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row wrap&amp;#34;&lt;/span>&amp;gt;{{ **message | titlecase** }}&amp;lt;/&lt;span style="color:#f92672">p&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;**&lt;/span>&lt;span style="color:#a6e22e">output&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">emit&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">true&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)**&amp;#34;&lt;/span>&amp;gt;Close&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="modal-wrapper-components">Modal Wrapper Components&lt;/h4>
&lt;p>This wrapper component will be loaded when loading the form in modal window. The component will process the modal request and then load the form component with the necessary data and react to events such as close in the form component.&lt;/p>
&lt;p>First, inject &lt;code>MatDialogRef&lt;/code> and &lt;code>MAT_DIALOG_DATA&lt;/code> into the component and then set global message variable using the message supplied from the component data.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">message&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#66d9ef">constructor&lt;/span>(
&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">dialogRef&lt;/span>: &lt;span style="color:#66d9ef">MatDialogRef&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">ModalWrapperComponent&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;span style="color:#66d9ef">@Inject&lt;/span>(&lt;span style="color:#a6e22e">MAT_DIALOG_DATA&lt;/span>) &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>)
{
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>.&lt;span style="color:#a6e22e">message&lt;/span>;
}
&lt;span style="color:#a6e22e">close&lt;/span>(&lt;span style="color:#a6e22e">results&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">dialogRef&lt;/span>.&lt;span style="color:#a6e22e">close&lt;/span>(&lt;span style="color:#a6e22e">results&lt;/span>);
}
&lt;span style="color:#a6e22e">ngOnInit() {&lt;/span>}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally add the form component into your template and inject the message and output as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;500px&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-form&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">message&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">message&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">output&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">close&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>&amp;gt; &amp;lt;/&lt;span style="color:#f92672">app-form&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="page-wrapper-component">Page Wrapper Component&lt;/h4>
&lt;p>This will resemble the Modal Wrapper Component closely with a few key differences. First, instead of injecting MAT_DIALOG_DATA and MatDialogRef, it will take in router and activatedRoute. This is because in this case, data is passed via route parameters. Here is how it looks:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">message&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>;
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">router&lt;/span>: &lt;span style="color:#66d9ef">Router&lt;/span>, &lt;span style="color:#a6e22e">activatedRoute&lt;/span>: &lt;span style="color:#66d9ef">ActivatedRoute&lt;/span>) {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">message&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">activatedRoute&lt;/span>.&lt;span style="color:#a6e22e">snapshot&lt;/span>.&lt;span style="color:#a6e22e">params&lt;/span>[&lt;span style="color:#e6db74">&amp;#34;message&amp;#34;&lt;/span>];
}
&lt;span style="color:#a6e22e">close&lt;/span>(&lt;span style="color:#a6e22e">results&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>([&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>]);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The template doesn’t change at all:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;500px&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">xs&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;100&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">app-form&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">[&lt;/span>&lt;span style="color:#a6e22e">message&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">]=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">message&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">output&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">close&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">($&lt;/span>&lt;span style="color:#a6e22e">event&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)&amp;#34;&lt;/span>&amp;gt; &amp;lt;/&lt;span style="color:#f92672">app-form&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can find the full example &lt;a href="https://github.com/MainaWycliffe/Adaptive-Layouts-using-Angular-Flex-Layout">here on GitHub.&lt;/a>&lt;/p>
&lt;h3 id="final-thoughts-this-is-a-simple-example-of-how-you-can-apply-adaptive-layout">Final Thoughts This is a simple example of how you can apply adaptive layout&lt;/h3>
&lt;p>design in Angular with Flex Layout. And since Angular Flex Layout is independent from Angular Material, you can use this with a host of other UI Libraries. You can now expand on this and build amazing UX for your users by mixing both Responsive and Adaptive layout design. If you have any questions regarding this topic or any angular related topic, you can use the comment section below.&lt;/p></description></item><item><title>How to Implement Sign-in with Google in Angular and a REST API</title><link>https://codinglatte.com/posts/angular/sign-in-with-google-angular/</link><pubDate>Sun, 04 Mar 2018 22:48:29 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/sign-in-with-google-angular/</guid><description>&lt;p>A few weeks ago, I demonstrated how to implement &lt;a href="https://codinglatte.com/tech/developers/angular/facebook-login-angular-rest-api/">Sign in with Facebook with a REST API&lt;/a>. Today, I will show you how to Sign-in with Google in Angular 5 with a REST API involved. We will use PHP at the backend, but this will work with any backend language you are totally comfortable with. To put it simply, your Angular App will request a token from Google OAuth Servers and then send the token to the REST API.&lt;/p>
&lt;p>The REST API will then validate the token against Google Servers (Never Trust Anything from the User) and if genuine, Sign-in or create account or do something that needed user to be authenticated. You will also get user profile data from Google including the profile picture which you can store for future reference. Let’s get started:&lt;/p>
&lt;h2 id="create-a-google-app-and-get-api-credentials">Create a Google App and Get API Credentials&lt;/h2>
&lt;p>The first thing we need is to create Google Project, so that we can get Access Credentials. To do this, you can head over to &lt;a href="https://console.developers.google.com/">Google Developer Console&lt;/a> and create an account or login with an existing account.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/sign-in-with-google-angular/images/Capture1.png" alt="How to Implement Sign-in with Google in Angular and a REST API" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>First, click on &lt;code>create project&lt;/code> button near the top left corner and enter the name for your project and click save. Wait until the project has been created. Then, select the project you just created and go to the credentials of API and Services for the project by clicking on the menu icon on the top left corner, then select &lt;code>API and Services&lt;/code>, and then &lt;code>Credentials&lt;/code>.&lt;/p>
&lt;p>If it’s a new project, you won’t have any credentials on your screen. There are a few things you need to do here. The first thing is to configure your &lt;code>OAuth Consent Screen&lt;/code>. This is the screen users will see with your app name and logo as you ask for permission during the Sign in with Google Process. To configure the &lt;code>OAuth Consent Screen&lt;/code>, click on &lt;code>the OAuth Consent Screen&lt;/code> Tab (Refer to the image below) and fill in the requested details. The name of the App is mandatory.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/sign-in-with-google-angular/images/Capture2.png" alt="How to Implement Sign-in with Google in Angular and a REST API" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>Next, you need to create OAuth Credentials for your project. You should see a &lt;code>Create Credentials&lt;/code> button on the screen, either at the middle of the screen or on top of the Credentials tab, just beneath the toolbar of the window. Click on the &lt;code>Create Credential&lt;/code> Button, and select &lt;code>OAuth Client Id&lt;/code> option in the drop-down menu that follows. In the next page, select &lt;code>Web Application&lt;/code> from the options under &lt;code>Application Type&lt;/code>.&lt;/p>
&lt;p>And then provide the name of the credentials and click &lt;code>Create&lt;/code> button. You might want to restrict the authorized domain names in the restriction section before creating the credentials. Here you will get the &lt;code>Client Id&lt;/code> and the &lt;code>Client Secret&lt;/code>, store them securely as you will need them for the steps that will follow.&lt;/p>
&lt;h2 id="add-sign-in-with-google-to-your-angular-application">Add Sign-in with Google to your Angular Application&lt;/h2>
&lt;p>Assuming you have successfully created a project, let’s go on and add a Sign-in with Google button to your angular app. To achieve this, we will use &lt;a href="https://github.com/abacritt/angularx-social-login">&lt;code>angularx-social-login&lt;/code>&lt;/a> module. You can install it using NPM or Yarn:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install --save angular5-social-login
// Or use yarn
yarn add angularx-social-login
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then import the &lt;code>Angular Social Login module&lt;/code> into your app module as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> {
&lt;span style="color:#a6e22e">SocialLoginModule&lt;/span>,
&lt;span style="color:#a6e22e">AuthServiceConfig&lt;/span>,
&lt;span style="color:#a6e22e">GoogleLoginProvider&lt;/span>
} &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angularx-social-login&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then create a new file &lt;code>socialloginConfig.ts&lt;/code> in the root of your project and add a config file for social login:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> {
&lt;span style="color:#a6e22e">SocialLoginModule&lt;/span>,
&lt;span style="color:#a6e22e">AuthServiceConfig&lt;/span>,
&lt;span style="color:#a6e22e">GoogleLoginProvider&lt;/span>
} &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angularx-social-login&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#a6e22e">getAuthServiceConfigs() {&lt;/span>
&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">config&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">AuthServiceConfig&lt;/span>([
{
&lt;span style="color:#a6e22e">id&lt;/span>: &lt;span style="color:#66d9ef">GoogleLoginProvider.PROVIDER_ID&lt;/span>,
&lt;span style="color:#a6e22e">provider&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">GoogleLoginProvider&lt;/span>()&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">GoogleClientIdJHere&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>
}
]);
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">config&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB&lt;/strong>: Replace the &lt;code>GoogleClientIdHere&lt;/code> with your client id from the Google Project you created in the first step. Then import &lt;code>getAuthServiceConfigs&lt;/code> into your app modules:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">getAuthServiceConfigs&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./socialloginConfig &amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally import &lt;code>SocialLoginModule&lt;/code> and add providers for &lt;code>SocialLoginModule&lt;/code> as show below&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">SocialLoginModule&lt;/span>
],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">SocialLoginModule&lt;/span>.&lt;span style="color:#a6e22e">initialize&lt;/span>(&lt;span style="color:#a6e22e">getAuthServiceConfigs&lt;/span>)
],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ]
})
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="add-to-your-sign-in-page">Add to your Sign In Page&lt;/h3>
&lt;p>Then, on your sign in component, import the &lt;code>AuthService&lt;/code>, &lt;code>GoogleLoginProvider&lt;/code> as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AuthService&lt;/span>, &lt;span style="color:#a6e22e">GoogleLoginProvider&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angular5-social-login&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And Inject &lt;code>AuthService&lt;/code> into your component as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>( &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">socialAuthService&lt;/span>: &lt;span style="color:#66d9ef">AuthService&lt;/span> ) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, add a method to handle Sign-in with Google and a button to your component. The method will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">signinWithGoogle&lt;/span> () {
&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">socialPlatformProvider&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">GoogleLoginProvider&lt;/span>.&lt;span style="color:#a6e22e">PROVIDER_ID&lt;/span>;
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">socialAuthService&lt;/span>.&lt;span style="color:#a6e22e">signIn&lt;/span>(&lt;span style="color:#a6e22e">socialPlatformProvider&lt;/span>)
.&lt;span style="color:#a6e22e">then&lt;/span>((&lt;span style="color:#a6e22e">userData&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">//on success
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">//this will return user data from google. What you need is a user token which you will send it to the server
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">sendToRestApiMethod&lt;/span>(&lt;span style="color:#a6e22e">userData&lt;/span>.&lt;span style="color:#a6e22e">idToken&lt;/span>);
});
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then add a &lt;code>Sign in with Google&lt;/code> button as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">signinWithGoogle&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;Sign in with Google&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>sendToRestApiMethod&lt;/code> is a method that will use HTTP to post the data to your REST API. The Token Id (&lt;code>idToken&lt;/code>)received from Google should be either a parameter or form data depending on the HTTP method you use to send the data to the server.&lt;/p>
&lt;p>Here is an example:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">sendToRestApiMethod&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">post&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;url to google login in your rest api&amp;#34;&lt;/span>,
{
&lt;span style="color:#a6e22e">token&lt;/span>: &lt;span style="color:#66d9ef">token&lt;/span>
}
}).&lt;span style="color:#a6e22e">subscribe&lt;/span>(
&lt;span style="color:#a6e22e">onSuccess&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">//login was successful
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">//save the token that you got from your REST API in your preferred location i.e. as a Cookie or LocalStorage as you do with normal login
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }, &lt;span style="color:#a6e22e">onFail&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">//login was unsuccessful
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">//show an error message
&lt;/span>&lt;span style="color:#75715e">&lt;/span> }
);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="integrating-with-your-rest-api">Integrating with your REST API&lt;/h2>
&lt;p>My REST API will be using PHP, but you can use any language you are comfortable with. For further and detailed tutorials for other language am not covering, visit the official documentation from Google &lt;a href="https://developers.google.com/identity/sign-in/ios/backend-auth">here&lt;/a>. First, install &lt;a href="https://developers.google.com/api-client-library/php/start/installation">PHP Google SDK&lt;/a> using composer as shown below (For detailed installation instruction, visit this &lt;a href="https://developers.google.com/api-client-library/php/start/installation">link&lt;/a>):&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">composer require google/apiclient
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Once the installation is complete, go to your login script or method and call the Google OAuth endpoint to verify the Token Id (&lt;code>idToken&lt;/code>) and create an account or grant user access to server-side resources or something. First, initialize the Google SDK as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-php" data-lang="php">$client = new Google_Client([
&amp;#39;client_id&amp;#39; =&amp;gt; &amp;#39;&amp;lt;&lt;span style="color:#f92672">GOOGLE&lt;/span> &lt;span style="color:#a6e22e">CLIENT&lt;/span> &lt;span style="color:#a6e22e">ID&lt;/span> &lt;span style="color:#a6e22e">HERE&lt;/span>&amp;gt;&amp;#39;
]);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then send the Token Id (&lt;code>idToken&lt;/code>) to the server for verification as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-php" data-lang="php">$payload = $client-&amp;gt;verifyIdToken($idToken);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, compare the claim &lt;code>aud&lt;/code> value with your google client id to ensure that the &lt;code>idToken&lt;/code> you got from your app was meant for your client and its valid. If they don’t match, then the token id is not valid. The payload contains personal data from the user, here is what is included in the payload:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">{
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">These&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">six&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">fields&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">are&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">included&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">in&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">all&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Google&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">ID&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Tokens.&lt;/span>
&lt;span style="color:#f92672">&amp;#34;iss&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;https://accounts.google.com&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;sub&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;110169484474386276334&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//Unique&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Google&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Account&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">Id&lt;/span>
&lt;span style="color:#f92672">&amp;#34;azp&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;aud&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;iat&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;1433978353&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;exp&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;1433981953&amp;#34;&lt;/span>,
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">These&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">seven&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">fields&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">are&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">only&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">included&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">when&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">the&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">user&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">has&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">granted&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">the&lt;/span> &lt;span style="color:#f92672">&amp;#34;profile&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">and&lt;/span>
&lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">OAuth&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">scopes&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">to&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">the&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">application.&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;email&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;testuser@gmail.com&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;email_verified&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Test User&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;picture&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;given_name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Test&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;family_name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;User&amp;#34;&lt;/span>,
&lt;span style="color:#f92672">&amp;#34;locale&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;en&amp;#34;&lt;/span>
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, create an account or sign in the user if they already exist. The &lt;code>sub&lt;/code> key in the payload is the Account Id and you can use to check if the user already exists. I suggest you generate your own User Id and do not rely with Google unique user id.&lt;/p></description></item><item><title>Implementing Login with Facebook with Angular and REST API</title><link>https://codinglatte.com/posts/angular/facebook-login-angular-rest-api/</link><pubDate>Tue, 06 Feb 2018 12:32:52 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/facebook-login-angular-rest-api/</guid><description>&lt;p>Today, I am going to show you how to create an Angular App with a REST API that uses Facebook Login to sign in/up users. For this application, we are going to be using PHP in our backend, but this can work with any Framework or Language for the backend.&lt;/p>
&lt;h3 id="first-thing-first">First Thing First&lt;/h3>
&lt;p>The login flow of the app will work something like this: when a user clicks on &lt;code>Login with Facebook&lt;/code>, the user is redirected to Facebook to give your app permission. In return, your app will receive an Access Token and some other personal information from Facebook.&lt;/p>
&lt;p>But the Golden rule here is never trust anything that comes from the user. So, your app will only send the token received from Facebook to the REST API. Which in turn will verify with Facebook whether it is genuine and request personal information from Facebook.&lt;/p>
&lt;p>Once the REST API has verified the details as genuine, go ahead and check whether the user exists in the database. if the user exists, go ahead and log the user in. If the user is not signed up, go ahead and sign the user up and log the user in. You can also send a welcome/confirmation email at this point.&lt;/p>
&lt;h3 id="create-a-facebook-application">Create a Facebook Application&lt;/h3>
&lt;p>For this to work, you need a Facebook application. Head over to &lt;a href="https://developers.facebook.com/">Facebook Developers&lt;/a> portal and create an app as demonstrated by the YouTube video below:&lt;/p>
&lt;amp-youtube data-videoid="Z9nVdZX9PHw" layout="responsive" width="480" height="270">&lt;/amp-youtube>
&lt;h3 id="adding-login-with-facebook-button-to-your-app">Adding Login with Facebook Button to your App&lt;/h3>
&lt;p>Assuming you have successfully setup your Facebook App successfully, you should have an &lt;code>App Id&lt;/code> and &lt;code>App Secret&lt;/code>. For the angular application, we are going to only need the App Id, the app secret will be used by the REST API. For social login, we are going to be using &lt;a href="https://github.com/abacritt/angularx-social-login">angularx-social-login&lt;/a> npm module. You can install it using the command below&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install --save angular5-social-login 
// Or with yarn
yarn add angular5-social-login
&lt;/code>&lt;/pre>&lt;/div>&lt;p>After you have successfully installed the module, Import it in the &lt;code>app.modules.ts&lt;/code> in your project.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">SocialLoginModule&lt;/span>, &lt;span style="color:#a6e22e">AuthServiceConfig&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angular5-social-login&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">FacebookLoginProvider&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angular5-social-login&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then create a new file &lt;em>socialloginConfig.ts&lt;/em> in the root of your project and add a config file for social login:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> {
&lt;span style="color:#a6e22e">AuthServiceConfig&lt;/span>,
&lt;span style="color:#a6e22e">FacebookLoginProvider&lt;/span>
} &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angular5-social-login&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#a6e22e">getAuthServiceConfigs() {&lt;/span>
&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">config&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">AuthServiceConfig&lt;/span>([
{
&lt;span style="color:#a6e22e">id&lt;/span>: &lt;span style="color:#66d9ef">FacebookLoginProvider.PROVIDER_ID&lt;/span>,
&lt;span style="color:#a6e22e">provider&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">FacebookLoginProvider&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;{FACEBOOK_APP_ID_HERE}&amp;#39;&lt;/span>)
}
]);
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">config&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then import the config file into your app modules:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">getAuthServiceConfigs&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./socialloginConfig &amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally import &lt;code>SocialLoginModule&lt;/code> and declare providers for &lt;code>SocialLoginModule&lt;/code> as show below&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">/* ... */&lt;/span>
&lt;span style="color:#a6e22e">SocialLoginModule&lt;/span>
],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">/* ... */&lt;/span>
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">AuthServiceConfig&lt;/span>,&lt;span style="color:#a6e22e">useFactory&lt;/span>: &lt;span style="color:#66d9ef">getAuthServiceConfigs&lt;/span>
}
],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [ &lt;span style="color:#75715e">/* ... */&lt;/span>]
});
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="on-your-sign-in-component">On your Sign in Component&lt;/h4>
&lt;p>Then, on your sign in component (or wherever you wish to add this button), import the AuthService, FacebookLoginProvider as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> {
&lt;span style="color:#a6e22e">AuthService&lt;/span>,
&lt;span style="color:#a6e22e">FacebookLoginProvider&lt;/span>,
&lt;span style="color:#a6e22e">GoogleLoginProvider&lt;/span>
} &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angular5-social-login&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And Inject &lt;code>AuthService&lt;/code> into your component as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>( &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">socialAuthService&lt;/span>: &lt;span style="color:#66d9ef">AuthService&lt;/span> ) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Note&lt;/strong>: If you are like me, you may already have another &lt;code>AuthService&lt;/code> Service, you can import the new &lt;code>AuthService&lt;/code> as an ALIAS as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> {
&lt;span style="color:#a6e22e">AuthService&lt;/span> &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">SocialAuthService&lt;/span>,
&lt;span style="color:#a6e22e">FacebookLoginProvider&lt;/span>,
&lt;span style="color:#a6e22e">GoogleLoginProvider&lt;/span>
} &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;angular5-social-login&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then Inject &lt;code>SocialAuthService&lt;/code> into your component as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">constructor&lt;/span>( &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">socialAuthService&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#f92672">**&lt;/span>&lt;span style="color:#a6e22e">SocialAuthService&lt;/span> &lt;span style="color:#f92672">**&lt;/span>) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, it’s a simple matter off adding a Facebook login method and a button. The method should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">facebookLogin&lt;/span>() {
    &lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">socialPlatformProvider&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">FacebookLoginProvider&lt;/span>.&lt;span style="color:#a6e22e">PROVIDER_ID&lt;/span>;
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">socialAuthService&lt;/span>.&lt;span style="color:#a6e22e">signIn&lt;/span>(&lt;span style="color:#a6e22e">socialPlatformProvider&lt;/span>).&lt;span style="color:#a6e22e">then&lt;/span>(
      (&lt;span style="color:#a6e22e">userData&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
        &lt;span style="color:#75715e">//this will return user data from facebook. What you need is a user token which you will send it to the server
&lt;/span>&lt;span style="color:#75715e">&lt;/span>            &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">sendToRestApiMethod&lt;/span>(&lt;span style="color:#a6e22e">userData&lt;/span>.&lt;span style="color:#a6e22e">token&lt;/span>);
       }
    );
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>On success – the user has granted your app permission – then send the token from user data received to the REST API. There is no need to send other personal information such as email and name as the REST API will get that information for itself. Your &lt;code>sendToRestApiMethod()&lt;/code> should look like this.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">sendToRestApiMethod&lt;/span>(&lt;span style="color:#a6e22e">token&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span>) &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
    &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">post&lt;/span>(&lt;span style="color:#960050;background-color:#1e0010">“&lt;/span>&lt;span style="color:#a6e22e">url&lt;/span> &lt;span style="color:#a6e22e">to&lt;/span> &lt;span style="color:#a6e22e">facebook&lt;/span> &lt;span style="color:#a6e22e">login&lt;/span> &lt;span style="color:#a6e22e">here&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">”&lt;/span>, { &lt;span style="color:#a6e22e">token&lt;/span>: &lt;span style="color:#66d9ef">token&lt;/span> } }
        .&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">onSuccess&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
                       &lt;span style="color:#75715e">//login was successful
&lt;/span>&lt;span style="color:#75715e">&lt;/span>                       &lt;span style="color:#75715e">//save the token that you got from your REST API in your preferred location i.e. as a Cookie or LocalStorage as you do with normal login
&lt;/span>&lt;span style="color:#75715e">&lt;/span>               }, &lt;span style="color:#a6e22e">onFail&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
                       &lt;span style="color:#75715e">//login was unsuccessful
&lt;/span>&lt;span style="color:#75715e">&lt;/span>                       &lt;span style="color:#75715e">//show an error message
&lt;/span>&lt;span style="color:#75715e">&lt;/span>               }
        );
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>(You should put it inside an Authentication Service together with other related authentication services)&lt;/p>
&lt;p>And finally add the Login with Facebook button:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">facebookLogin&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;Login with Facebook&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="integrating-with-a-rest-api">Integrating with a REST API&lt;/h3>
&lt;p>And Finally, to the REST API. I will demonstrate this using PHP, but you can use any language you wish, you can get detailed support for your specific language &lt;a href="https://developers.facebook.com/docs/apis-and-sdks">here&lt;/a>. (&lt;em>Scroll to the section for Facebook Login and User Profiles)&lt;/em>.&lt;/p>
&lt;p>Since you already have a App Secret and App ID and Access Token (Sent from the Angular App), this one is rather straight forward. In your PHP Method/Script for handling Facebook login, add the following code:&lt;/p>
&lt;p>First, Initialize connection to Facebook API using the PHP SDK&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-php" data-lang="php">$fb = new FacebookFacebook([
    &amp;#39;app_id&amp;#39; =&amp;gt; &amp;#34;APP ID HERE&amp;#34;,
    &amp;#39;app_secret&amp;#39; =&amp;gt; &amp;#34;APP SECRET HERE&amp;#34;
    &amp;#39;default_graph_version&amp;#39; =&amp;gt; &amp;#39;v2.12&amp;#39;,
]);
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;em>Replace the &lt;code>APP ID HERE&lt;/code> and &lt;code>APP SECRET HERE&lt;/code> with your specific details from your Facebook app.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;p>And then, Send the access token received from the client app and request user id, name and email address of the user from Facebook. This will return those details if the access token is genuine and will fail if it isn’t.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-php" data-lang="php">try {
      $fbresponse = $fb-&amp;gt;get(&amp;#39;/me?fields=id,name,email&amp;#39;, &amp;#34;Access Token Here&amp;#34;);
} catch (FacebookExceptionsFacebookResponseException $e) {
//Handle this error, return a failed request to the app with either 401 or 500
} catch (FacebookExceptionsFacebookSDKException $e) {
//Handle this error, return a 500 error – something is wrong with your code
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And finally, do something with the data you received from Facebook. You can check if the user exists in your user database by both email and Facebook user Id, if they exist, sign them in and if they don’t exist sign them up. You can also check if the email address is associated with another user and if so, just associate the Facebook account to the account with the email address. This is all up to you, you can handle it any way you want. You can get the Facebook User &lt;code>Id, Names and Email&lt;/code> as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-php" data-lang="php">$me = $fbresponse-&amp;gt;getGraphUser();
$userId = $me-&amp;gt;getId();
$email = $me-&amp;gt;getEmail();  
$name = $user-&amp;gt;name()
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Search Engine Optimization with Angular</title><link>https://codinglatte.com/posts/angular/search-engine-optimization-angular/</link><pubDate>Tue, 30 Jan 2018 17:53:26 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/search-engine-optimization-angular/</guid><description>&lt;p>Today, I will show you how to optimize your Angular 5 and above for search engine and other crawlers. It is important to note that, pages behind a sign in page don’t need to be optimized and you should only concentrate on publicly accessible pages. We are going to take a few steps to prepare our app for search engine optimization like adding page title and meta tags to your pages.&lt;/p>
&lt;h2 id="adding-meta-tags-and-page-title">Adding Meta Tags and Page Title&lt;/h2>
&lt;p>The important part of Search Engine Optimization is to add a page title and some Metatags i.e. description, keywords, &lt;a href="https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started">&lt;code>twitter cards&lt;/code>&lt;/a> and &lt;a href="https://developers.facebook.com/docs/graph-api/">&lt;code>Facebook Graph&lt;/code>&lt;/a> tags if you wish. You need to add this to the different pages of your Angular app dynamically. To achieve this, you will embed them on to your routes inside your router. Add a new route property called data and then add some objects like page title and metatags to it as shown below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">[
&lt;span style="color:#75715e">// ... other routes
&lt;/span>&lt;span style="color:#75715e">&lt;/span> {
&lt;span style="color:#a6e22e">component&lt;/span>: &lt;span style="color:#66d9ef">AngularComponent&lt;/span>,
&lt;span style="color:#a6e22e">path&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Page Title&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">metatags&lt;/span>&lt;span style="color:#f92672">:&lt;/span> {
&lt;span style="color:#a6e22e">description&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Page Description or some content here&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">keywords&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;some, keywords, here, separated, by, a comma&amp;#39;&lt;/span>
}
}
}
&lt;span style="color:#75715e">// ... other routes
&lt;/span>&lt;span style="color:#75715e">&lt;/span>];
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: I have grouped all my metatags under one key, instead of spreading them at the root of data property. This will allow me to add them to the pages meta using a for-loop instead of adding each manually. This allows me to have varying number of metatags in different pages and the loop will add all of them.&lt;/p>
&lt;/blockquote>
&lt;h3 id="seo-service">SEO Service&lt;/h3>
&lt;p>Create a new service using &lt;a href="https://github.com/angular/angular-cli">Angular CLI&lt;/a> called SEOServices as shown below ng g service SEO Open the service and import the &lt;code>Title&lt;/code> and &lt;code>Meta&lt;/code> service from &lt;code>@angular/platform-browser&lt;/code> and &lt;code>Router&lt;/code> and &lt;code>NavigationEnd&lt;/code> from &lt;code>@angular/router modules.&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Title&lt;/span>, &lt;span style="color:#a6e22e">Meta&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/platform-browser&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Router&lt;/span>, &lt;span style="color:#a6e22e">NavigationEnd&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/router&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, initialize the services inside the constructor:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">constructor&lt;/span>(
    &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">titleService&lt;/span>: &lt;span style="color:#66d9ef">Title&lt;/span>,
    &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">metaService&lt;/span>: &lt;span style="color:#66d9ef">Meta&lt;/span>,
    &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">router&lt;/span>: &lt;span style="color:#66d9ef">Router&lt;/span>,
) {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, create a method to add metatags and the page title to the page as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">addSeoData&lt;/span>() &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
  &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">events&lt;/span>.&lt;span style="color:#a6e22e">filter&lt;/span>((&lt;span style="color:#a6e22e">event&lt;/span>: &lt;span style="color:#66d9ef">any&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">event&lt;/span> &lt;span style="color:#66d9ef">instanceof&lt;/span> &lt;span style="color:#a6e22e">NavigationEnd&lt;/span>).&lt;span style="color:#a6e22e">subscribe&lt;/span>(() &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
      &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">root&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">routerState&lt;/span>.&lt;span style="color:#a6e22e">snapshot&lt;/span>.&lt;span style="color:#a6e22e">root&lt;/span>;
      &lt;span style="color:#66d9ef">while&lt;/span> (&lt;span style="color:#a6e22e">root&lt;/span>) {
        &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">root&lt;/span>.&lt;span style="color:#a6e22e">children&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">root&lt;/span>.&lt;span style="color:#a6e22e">children&lt;/span>.&lt;span style="color:#a6e22e">length&lt;/span>) {
          &lt;span style="color:#a6e22e">root&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">root&lt;/span>.&lt;span style="color:#a6e22e">children&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>];
        } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">root&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">root&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#e6db74">&amp;#34;title&amp;#34;&lt;/span>]) {
          &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">titleService&lt;/span>.&lt;span style="color:#a6e22e">setTitle&lt;/span>(&lt;span style="color:#a6e22e">root&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#e6db74">&amp;#34;title&amp;#34;&lt;/span>] &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34; | App Name&amp;#34;&lt;/span>);
          &lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">tags&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">root&lt;/span>.&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#e6db74">&amp;#34;metatags&amp;#34;&lt;/span>];
          &lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">tag&lt;/span> &lt;span style="color:#66d9ef">in&lt;/span> &lt;span style="color:#a6e22e">tags&lt;/span>) {
            &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">metaService&lt;/span>.&lt;span style="color:#a6e22e">addTag&lt;/span>({ &lt;span style="color:#a6e22e">name&lt;/span>: &lt;span style="color:#66d9ef">tag&lt;/span>, &lt;span style="color:#a6e22e">content&lt;/span>: &lt;span style="color:#66d9ef">tags&lt;/span>[&lt;span style="color:#a6e22e">tag&lt;/span>] });
          }
          &lt;span style="color:#66d9ef">return&lt;/span>;
        } &lt;span style="color:#66d9ef">else&lt;/span> {
         &lt;span style="color:#66d9ef">return&lt;/span>;
        }
      }
    });
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above function loops through your hierarchy of roots until it finds the lowest root with a page title and meta tags, then adds the particulars to the page header. So, you can have a page title and meta tags to a parent root that all its children will inherit. Finally, call the service from the root component of your application (somewhere else is fine too).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">constructor&lt;/span> (&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">seoService&lt;/span>: &lt;span style="color:#66d9ef">SEOService&lt;/span>)
{
      &lt;span style="color:#a6e22e">seoService&lt;/span>. &lt;span style="color:#a6e22e">addSeoData&lt;/span>()
}
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Remember to follow all the search engine optimization best practices for both metatags and the content. This just gives a way of achieving that but it’s not a comprehensive guide for Search Engine Optimization.&lt;/p>
&lt;/blockquote>
&lt;h2 id="prerendering-of-content">Prerendering of Content&lt;/h2>
&lt;p>We have now taken care of Metadata and Page Titles, now let’s take care of the big issue. Single page applications are rendered on the browser but Angular &lt;a href="https://codinglatte.com/tech/developers/angular/angular-5-hasbeen-released/">Introduced&lt;/a> Angular Server-Side Rendering or &lt;a href="https://universal.angular.io/overview/">Angular Universal&lt;/a> to render them on the server just like PHP or any server-side scripts. At the moment, only 2 backends support Angular Universal – NodeJS and ASP.NET. Support for PHP, Java and Python will come at a latter unspecified date.&lt;/p>
&lt;p>Instead of using Angular Universal, we are going to use a &lt;a href="https://prerender.io/">prerender.io&lt;/a> service that supports almost all backends out there. This will prerender and cache your live Angular Application and serve it to bots and crawlers. This allows you app to play nice with your users and at the same time with Search Engines.&lt;/p>
&lt;p>On top of that, if your app is small – less than 250 pages – you get to pay nothing and even if your app is large, their prices are quite reasonable. To get started, head over to their site and create an account, use this &lt;a href="https://prerender.io/signup">link&lt;/a> to signup.&lt;/p>
&lt;p>Make sure you confirm your email address and add some billing info just incase you go over their free limit. Then add your site, by clicking &lt;code>add url&lt;/code> button and wait for their service to crawl and generate prerendered version of your site.&lt;/p>
&lt;p>You can view the prerendered version of your app by clicking view raw html button next to your site, in the preview column. The only thing that’s remaining is integrating it with your server or backend so that it serves the prerendered version to bots and crawlers.&lt;/p>
&lt;p>If you head over &lt;a href="https://prerender.io/documentation">here&lt;/a>, you will notice it is has support for a very huge number of backends and servers. Scroll through the list and find the backend you are using to get instruction on how to integrate it with Prerender.&lt;/p>
&lt;h3 id="apache-server">Apache Server&lt;/h3>
&lt;p>I will show you how to add it to your apache server. Assuming you already are using Apache serve to server your Angular app, then you must have a .htaccess file to redirect all paths to index.html to avoid an error 404. Your htaccess resembles something like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">RewriteEngine on
RewriteRule ^ index.html [QSA,L]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Add the following to your .htaccess access file:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">#RequestHeader set X-Prerender-Token &amp;#34;YOUR_TOKEN&amp;#34;
&amp;lt;IfModule mod_proxy_http.c&amp;gt;
        RewriteCond %{HTTP_USER_AGENT} baiduspider|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator [NC,OR]
        RewriteCond %{QUERY_STRING} _escaped_fragment_   
       # Only proxy the request to Prerender if it&amp;#39;s a request for HTML
        RewriteRule ^(?!._?(.js|.css|.xml|.less|.png|.jpg|.jpeg|.gif|.pdf|.doc|.txt|.ico|.rss|.zip|.mp3|.rar|.exe|.wmv|.doc|.avi|.ppt|.mpg|.mpeg|.tif|.wav|.mov|.psd|.ai|.xls|.mp4|.m4a|.swf|.dat|.dmg|.iso|.flv|.m4v|.torrent|.ttf|.woff))(._) http://service.prerender.io/http://example.com/$2 [P,L]
&amp;lt;/IfModule&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: You can get the token from your account page next to the header. You can get the full .htaccess file &lt;a href="https://gist.github.com/thoop/8072354">here&lt;/a>. And voila, you have an angular application that has been optimized for search engines and bots without doing too much work.&lt;/p>
&lt;/blockquote></description></item><item><title>Deploying a PHP 7 App with MongoDB to AWS Elastic Beanstalk</title><link>https://codinglatte.com/posts/php/php-7-with-mongodb-to-elastic-beanstalk/</link><pubDate>Mon, 15 Jan 2018 11:29:07 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/php/php-7-with-mongodb-to-elastic-beanstalk/</guid><description>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>Over the weekend, I was working on a PHP REST API that is using Mongo DB as it’s database. I haven’t worked with MongoDB before, I have always used MySQL/MariaDB/PostgreSQL DB etc. for almost all my projects.  The reason am bringing the MongoDB is because you need PHP MongoDB Module to connect to the database. By default, AWS Elastic Beanstalk PHP preconfigured environment doesn’t ship with the module, hence the need to install it during deployment.&lt;/p>
&lt;p>If you are not aware, Elastic Beanstalk applications needs to be stateless. Your application needs to be able to setup everything automatically on its own using &lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/ebextensions.html">EB Extensions&lt;/a>. EB Extensions are used to modify a deployment environment so that you can install missing packages, setup configurations and do other stuff that will help your application run smoothly. All this is done automatically without your input as per the EB extensions.&lt;/p>
&lt;p>You can learn more about EB Extensions &lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/ebextensions.html">here&lt;/a>.&lt;/p>
&lt;h2 id="installing-pear-and-php-pear-extensions">Installing PEAR and PHP PEAR Extensions&lt;/h2>
&lt;p>In my case, I needed to install the PHP MongoDB Module and Setup Composer. The second bit is straight forward but the first one is where I ran into a lot of difficulties. Almost every resource I found over the internet was working for any one not using PHP 7 and above. This is because commands used for PHP 5 for PEAR (Installing PEAR itself and Installing PEAR Packages) have changed for some reason in Amazon Linux. You need to add a 7 at the end now. For instance, to instal PEAR use the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">sudo yum -y install php7-pear php70-devel gcc
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And to install a PEAR Package you need the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">sudo pecl7 install mongodb
&lt;/code>&lt;/pre>&lt;/div>&lt;p>(Notice the highlighted parts.) You could connect to your EC2 instance and install packages manually, but It’s not recommended. This is where EB Extensions come into play. In the root of your project, create a new folder called &lt;code>.ebextensions&lt;/code> and add two files: &lt;code>packages.config&lt;/code> and &lt;code>php.config&lt;/code>. The first one will install all the packages (From yum and other Linux package managers) while the second one will install all PHP PEAR packages. In the first file – &lt;code>packages.config&lt;/code> – you need to add the following content.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">packages&lt;/span>:
&lt;span style="color:#66d9ef">yum&lt;/span>:
        &lt;span style="color:#66d9ef">php7-pear&lt;/span>: []
        &lt;span style="color:#66d9ef">php71-devel&lt;/span>: []
        &lt;span style="color:#66d9ef">gcc&lt;/span>: []
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This tells Elastic Beanstalk to install PHP7-pear, PHP70-devel and GCC compiler. Feel free to add extra packages as you need them. You can learn more about Packages config &lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html#linux-packages">here&lt;/a>. In the second file – &lt;code>php.config&lt;/code> – add the following content:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="color:#66d9ef">commands&lt;/span>:
  &lt;span style="color:#66d9ef">install_mongo_driver&lt;/span>:
    &lt;span style="color:#66d9ef">command&lt;/span>: pecl7 install mongodb
    &lt;span style="color:#66d9ef">test&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;php -r &amp;#34;&lt;/span>&lt;span style="color:#66d9ef">exit(extension_loaded(&amp;#39;mongodb&amp;#39;) ? 1 &lt;/span>: &lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will first test whether PHP mongodb module exists and if it doesn’t it will install mongodb extension using PEAR. You can learn more about commands configs &lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers-ec2.html#linux-commands">here&lt;/a>.&lt;/p>
&lt;h2 id="final-thoughts">Final Thoughts&lt;/h2>
&lt;p>While this post has primarily focused on MongoDB Module for PHP, it will work with any other PHP Module available on PEAR. You can search for PEAR packages &lt;a href="https://pear.php.net/packages.php">here&lt;/a>. Just remember to use pecl7 instead of just pecl during the installation process. In case of further updates, I will be sure to update this post with new information.&lt;/p></description></item><item><title>Adaptive Layout Design - Angular Flex Layout</title><link>https://codinglatte.com/posts/angular/adaptive-layout-design-angular-flex-layout/</link><pubDate>Sun, 07 Jan 2018 20:53:59 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/adaptive-layout-design-angular-flex-layout/</guid><description>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>You probably have heard about Responsive Layout design but let me remind you anyway. Responsive layout is where components and elements of a web page change size and position based on different breaking points – Web apps that adapt to any screen size.&lt;/p>
&lt;p>Unlike &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-better-than-bootstrap/">responsive layout&lt;/a>, in Adaptive Layouts different components and elements are displayed or hidden on different screen sizes. While responsive design is amazing at what it does, it also has it limits especially trying to fit the same components in a large screen size and an extra small screen size. Sometimes you just want to have different components and elements for different screen sizes.&lt;/p>
&lt;h2 id="how-it-works">How it works&lt;/h2>
&lt;p>Angular Flex Layout provides you with the tools for Adaptive Layout design – &lt;code>fxHide&lt;/code>, &lt;code>fxShow&lt;/code> and &lt;code>ngIf&lt;/code>. As you may have already guessed both &lt;code>fxHide&lt;/code> and &lt;code>fsShow&lt;/code> directives are used for hiding elements while &lt;a href="https://angular.io/api/common/NgIf">&lt;code>ngIf&lt;/code>&lt;/a> adds or removes components by using DOM (Direct Object Manipulation).&lt;/p>
&lt;p>DOM manipulation may be useful at some instance by reducing the footprint of your Angular application on the browser thus reducing the resources used by your app. You can use a combination of the directives with the different breakpoint to hide and show elements on your angular application. Angular Flex Layout has four breakpoint aliases – xs, sm, md and lg. To show a component only on XS devices, you do the following:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-component-name&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;false&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">xs&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-component-name&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Note the &lt;code>fxShow&lt;/code> Directive with the dot notation followed by the preferred breakpoint alias. The first &lt;code>fxShow=&amp;quot;hide&amp;quot;&lt;/code> is used to hide the component on all screen sizes so that you can show it on a specific screen using the second &lt;code>fxShow.xs=&amp;quot;true&amp;quot;&lt;/code>. To show a component on all screens sizes above small, you can use the &lt;code>gt-sm (greater than small)&lt;/code> alias as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-component-name&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;false&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">gt-sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-component-name&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will show the components on all screen sizes starting md (medium screen size) and above. You can get a list of all breakpoints below.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/adaptive-layout-design-angular-flex-layout/images/screens-sizes.png" alt="Adaptive Layout Design - Angular Flex Layout" width="500" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>Unfortunately, you can not do that with &lt;code>*ngIf&lt;/code>, am not sure whether support will be coming – it’s not clear on their site. it would be amazing if you could use it as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">app-component-name&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">gt-sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">app-component-name&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Fortunately, there’s a workaround for this, while not as nice as the one above, it requires you to add some code to your typescript file of your component. As shown below:&lt;/p>
&lt;h3 id="component">&lt;strong>Component&lt;/strong>&lt;/h3>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#75715e">//import obersavable media
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">ObservableMedia&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/flex-layout&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@Component&lt;/span>({
&lt;span style="color:#a6e22e">selector&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;app-component&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">template&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;app-component.html&amp;#39;&lt;/span>
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppComponent&lt;/span> {
&lt;span style="color:#75715e">//declare a public variable of observable media
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">media&lt;/span>: &lt;span style="color:#66d9ef">ObservableMedia&lt;/span>) {}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now you can use &lt;code>*ngIf&lt;/code> in your component template as shown below&lt;/p>
&lt;h3 id="template">&lt;strong>Template&lt;/strong>&lt;/h3>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;media.isActive(&amp;#39;xs&amp;#39;)&amp;#34;&lt;/span>&amp;gt;
This content is only shown on extra small devices
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;media.isActive(&amp;#39;sm&amp;#39;)&amp;#34;&lt;/span>&amp;gt;
This content is only shown on small devices
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">*&lt;/span>&lt;span style="color:#a6e22e">ngIf&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;media.isActive(&amp;#39;md&amp;#39;) || media.isActive(&amp;#39;lg&amp;#39;)&amp;#34;&lt;/span>&amp;gt;
This content is only shown on medium devices and large devices
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>Adaptive Layout design is a very important tool in a developer’s arsenal. If used wisely in combination with responsive layout design, it can produce some magical results. If used poorly, it can lead to a bloated Angular app with poor performance. This is due to increased number of component that do essentially the same thing. If you have any question regarding this topic or any other feel free to drop a comment  below.&lt;/p></description></item><item><title>Visual Studio Code - Top 5 Extensions for PHP</title><link>https://codinglatte.com/posts/php/visual-studio-code-top-5-extensions-php/</link><pubDate>Sun, 17 Dec 2017 21:57:01 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/php/visual-studio-code-top-5-extensions-php/</guid><description>&lt;p>Visual Studio Code is one of the best free text editors out there. Right out of the box, Visual Studio Code offers basic &lt;a href="https://codinglatte.com/tech/developers/php/php-frameworks-vs-microframeworks/">PHP&lt;/a> support but nothing more than that. To enjoy a fruitful PHP development, you need to install PHP extensions. Today, I am going to highlight 5 extensions you might want to consider. If you would like to try out Visual Studio Code, you can download it &lt;a href="https://code.visualstudio.com/download">here&lt;/a>.&lt;/p>
&lt;h2 id="phpcs-php-codesniffer--ioannis-kappas">PHPCS (PHP CodeSniffer) – Ioannis Kappas&lt;/h2>
&lt;p>This extension offers an interface for &lt;a href="https://pear.php.net/package/PHP_CodeSniffer/">PHP CodeSniffer&lt;/a>. PHP CodeSniffer scans the PHP files in your workspace to detect and offer suggestions and fixes for violations of a defined set of PHP standards. It’s an excellent extension that will ensure you strictly follow standard for PHP.&lt;/p>
&lt;p>You can learn more about PHP standard &lt;a href="http://www.php-fig.org/psr/">here&lt;/a>. For you to use this extension, you need to install PHP CodeSniffer globally into your development machine. You can install PHP CodeSniffer using either &lt;a href="https://pear.php.net/index.php">PEAR&lt;/a> or &lt;a href="https://getcomposer.org/">Composer&lt;/a> as shown below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">// PEAR
pear install PHP_CodeSniffer
// Composer:
composer require --dev squizlabs/php_codesniffer
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To install PHPCS, press F1 on Visual Studio and type the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ext install phpcs
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about this extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=ikappas.phpcs">here&lt;/a>.&lt;/p>
&lt;h2 id="php-intellisense-crane--hvy-industries">PHP Intellisense Crane – Hvy Industries&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/12/a9j3V9u.gif" alt="Visual Studio Code - Top 5 Extensions for PHP"> To use the creator’s words, PHP Intellisense Crane is a productivity enhancement extension for Visual Studio Code that provides code-completion for PHP. It has zero dependencies and largely works with projects of any size. The extension is active in development and you can raise issues and make feature suggestion on &lt;a href="https://github.com/HvyIndustries/crane/issues">GitHub&lt;/a>. This extension offers the following features: Code Completion, Go To and Peek Definition on classes, interfaces and traits and document workspace symbol provides. To install PHP Intellisense Crane, press F1 on Visual Studio Code, and type the command below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ext install crane
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Once installation is complete, wait for it to parse all PHP files in your workspace. You will see a progress bar at the status bar.&lt;/p>
&lt;p>You can learn more about PHP Intellisense Crane &lt;a href="https://marketplace.visualstudio.com/items?itemName=HvyIndustries.crane">here&lt;/a>.&lt;/p>
&lt;h2 id="php-intelephense--ben-mewburn">PHP Intelephense – Ben Mewburn&lt;/h2>
&lt;p>This is one of the best PHP Extension I have ever used. It provides a tonne of useful features without affecting negatively the performance of Visual Studio Code. It also has no external dependencies. It has the following features:&lt;/p>
&lt;ul>
&lt;li>Fast camel/underscore case code completion (IntelliSense), offering detailed suggestions for document, workspace and built-in symbols and keywords.&lt;/li>
&lt;li>Detailed signature (parameter) help for document, workspace and built-in constructors, methods, and functions.&lt;/li>
&lt;li>Rapid workspace wide go to definition support.&lt;/li>
&lt;li>Workspace wide find all references.&lt;/li>
&lt;li>Fast camel/underscore case workspace symbol search.&lt;/li>
&lt;li>Full document symbol search.&lt;/li>
&lt;li>Multiple parse error diagnostics for open files via an error tolerant parser.&lt;/li>
&lt;li>Lossless PSR-2 compatible document and range formatting.&lt;/li>
&lt;li>Convenient command to add use declarations and condense referenced names.&lt;/li>
&lt;li>HTML request forwarding allowing for a full HTML/Javascript/CSS/PHP development experience.&lt;/li>
&lt;/ul>
&lt;p>To install this extension, press F1 and type in the command below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ext install bmewburn.vscode-intelephense-client
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about this extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client">here&lt;/a>.&lt;/p>
&lt;h2 id="php-intellisense--felix-becker">PHP Intellisense – Felix Becker&lt;/h2>
&lt;p>Just like the name suggests, it offers Intellisense autocompletion for PHP. This extension depends on &lt;a href="https://github.com/felixfbecker/php-language-server">PHP Language Server&lt;/a> to work. The extension just provides an interface to the PHP Language Server. To use this extension, first install the PHP Language Server using composer as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">composer require felixfbecker/language-server
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you have multiple projects, you can install PHP Language Server globally as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">composer global require felixfbecker/language-server
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You also need to have PHP7 installed in your system. Then go ahead and install the extension on Visual Studio Code. Press F1 and type in the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ext install php-intellisense
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can learn more about the extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-intellisense">here&lt;/a>.&lt;/p>
&lt;h2 id="php-debug--felix-becker">PHP Debug – Felix Becker&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/12/demo-1024x810.gif" alt="Visual Studio Code - Top 5 Extensions for PHP">&lt;/p>
&lt;p>This extension is an adapter for &lt;a href="https://xdebug.org/">XDebug&lt;/a> extension for PHP. XDebug is an extension for PHP that assists with debugging and development of PHP projects. To use this application, you need to install XDebug and PHP into your system.&lt;/p>
&lt;p>You can follow the instruction found in the extension page &lt;a href="https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug">here&lt;/a>. To install this extension, press F1 and type in the command below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ext install php-debug.
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Angular Material Icons Components with Angular 5</title><link>https://codinglatte.com/posts/angular/material-icons-angular-5/</link><pubDate>Wed, 13 Dec 2017 11:43:03 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/material-icons-angular-5/</guid><description>&lt;p>Icons are a necessity when building modern-day web apps and sometimes they can be frustrating. While icon sets like &lt;a href="http://fontawesome.io/">Font Awesome&lt;/a> and &lt;a href="https://material.io/icons/">Material&lt;/a> Icons have made it easier, there is always an icon you need that is always missing. A good example is lack of social media icons in Material Icons for whatever reason.&lt;/p>
&lt;p>To avoid this problem, you can use multiple icon sets or mix between an icon set and your own set of image icons. This introduces the issue of lack of consistency on your icons. To solve this problem, &lt;a href="https://codinglatte.com/tech/developers/angular/what-i-learned-when-i-switched-to-angular-material/">Angular material&lt;/a> uses &lt;a href="https://material.angular.io/components/icon/overview">Angular material Icon Component&lt;/a>. Let’s look at how to use &lt;strong>mat-icons&lt;/strong> with different icon sets.&lt;/p>
&lt;h2 id="how-to-setup-the-mat-icon-component">How to Setup the Mat-Icon Component&lt;/h2>
&lt;p>To use this component, import the &lt;code>MatIconModule&lt;/code> from &lt;code>@angular/material&lt;/code> in your &lt;code>app module&lt;/code> as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MatIconModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/material&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
&lt;span style="color:#75715e">// ...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">MatIconModule&lt;/span> &lt;span style="color:#75715e">//...
&lt;/span>&lt;span style="color:#75715e">&lt;/span> ],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="using-material-icons-font">Using Material Icons (Font)&lt;/h2>
&lt;p>This one is relatively easy. I would recommend one of two approaches. Approach 1, include the Google Material Font link from Google Font CDN in the header of your &lt;code>index.html&lt;/code> in your application. Then after that, the Angular Material component – &lt;code>mat-icon&lt;/code> – will recognize all material font icons by default. You can go ahead and use the icons as shown below. First, include the following in your index html header&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">link&lt;/span>
&lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">[https://fonts.googleapis.com/icon?family=Material+Icons](https://fonts.googleapis.com/icon?family=Material+Icons)&lt;/span>
&lt;span style="color:#a6e22e">rel&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;stylesheet&amp;#34;&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, you can simply use material icons as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-icon&lt;/span>&amp;gt;icon_name&amp;lt;/&lt;span style="color:#f92672">mat-icon&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>i.e. &lt;code>&amp;lt;mat-icon&amp;gt;home&amp;lt;/mat-icon&amp;gt;&lt;/code> for home icon&lt;/p>
&lt;p>The second approach is to self-host the font icons on your own servers. You can install the icons using either npm and yarn as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install material-design-icons@latest
//for yarn
yarn add material-design-icons@latest
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Assuming you have successfully installed the &lt;code>material-design-icons@^3.0.1&lt;/code> package, then, go ahead and import the CSS stylesheet located here: &lt;code>../node_modules/material-design-icons/iconfont/material-icons.css&lt;/code> into your angular project inside your &lt;code>angular-cli.json&lt;/code>, under the styles, as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [
      &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
      &lt;span style="color:#e6db74">&amp;#34;../node_modules/material-design-icons/iconfont/material-icons.css&amp;#34;&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">//icon.css&lt;/span>
      &lt;span style="color:#e6db74">&amp;#34;scss/styles.scss&amp;#34;&lt;/span>,
      &lt;span style="color:#960050;background-color:#1e0010">//&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">...&lt;/span>
    ]&lt;span style="color:#960050;background-color:#1e0010">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Assuming you have successfully imported the stylesheet into your project, you can go ahead and start using the material icons. You can also use CSS font-size property to vary the size of the icons, as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-css" data-lang="css">.&lt;span style="color:#a6e22e">material-icons&lt;/span>.&lt;span style="color:#a6e22e">md-14&lt;/span> {
 &lt;span style="color:#66d9ef">font-size&lt;/span>: &lt;span style="color:#ae81ff">14&lt;/span>&lt;span style="color:#66d9ef">px&lt;/span>;
}
.&lt;span style="color:#a6e22e">material-icons&lt;/span>.&lt;span style="color:#a6e22e">md-18&lt;/span> {
 &lt;span style="color:#66d9ef">font-size&lt;/span>: &lt;span style="color:#ae81ff">18&lt;/span>&lt;span style="color:#66d9ef">px&lt;/span>;
}
.&lt;span style="color:#a6e22e">material-icons&lt;/span>.&lt;span style="color:#a6e22e">md-24&lt;/span> {
 &lt;span style="color:#66d9ef">font-size&lt;/span>: &lt;span style="color:#ae81ff">24&lt;/span>&lt;span style="color:#66d9ef">px&lt;/span>;
}
.&lt;span style="color:#a6e22e">material-icons&lt;/span>.&lt;span style="color:#a6e22e">md-36&lt;/span> {
 &lt;span style="color:#66d9ef">font-size&lt;/span>: &lt;span style="color:#ae81ff">36&lt;/span>&lt;span style="color:#66d9ef">px&lt;/span>;
}
.&lt;span style="color:#a6e22e">material-icons&lt;/span>.&lt;span style="color:#a6e22e">md-48&lt;/span> {
 &lt;span style="color:#66d9ef">font-size&lt;/span>: &lt;span style="color:#ae81ff">48&lt;/span>&lt;span style="color:#66d9ef">px&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then just include the &lt;code>md-*&lt;/code> in your &lt;code>mat-icon&lt;/code> to vary the size of the icons. The icons may be vertically aligned on top, this keeps them out of line with the content. To solve this problem, align them in the middle vertically as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-css" data-lang="css">.&lt;span style="color:#a6e22e">material-icons&lt;/span> {
     &lt;span style="color:#66d9ef">vertical-align&lt;/span>: &lt;span style="color:#66d9ef">middle&lt;/span>;
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="using-svg-icons">Using SVG Icons&lt;/h2>
&lt;p>If you have a set of SVG Icons for your angular application, you can register them with the Angular Material Icon module. This allows you to reference them anywhere in your application with ease and apply styles to your icons just like normal font icons. I use this method to include icons that are missing from the icon set am using. To register your SVG icons, follow the steps below: Identify the first component of your application (in most cases it will be the &lt;code>app.component.ts&lt;/code>) and them import the &lt;code>MatIconRegistry&lt;/code> module as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MatIconRegistry&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/material&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">DomSanitizer&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/platform-browser&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>DomSanitizer&lt;/code> is there to mark paths to the SVG icons as trusted resources and ensure they are loaded. Then, create a constructor class to register new icons as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">constructor&lt;/span> (
    &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">domSanitizer&lt;/span>: &lt;span style="color:#66d9ef">DomSanitizer&lt;/span>,
    &lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">matIconRegistry&lt;/span>: &lt;span style="color:#66d9ef">MatIconRegistry&lt;/span>) {
    &lt;span style="color:#75715e">//add custom material icons
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#a6e22e">matIconRegistry&lt;/span>.&lt;span style="color:#a6e22e">addSvgIcon&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;iconName&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">domSanitizer&lt;/span>.&lt;span style="color:#a6e22e">bypassSecurityTrustResourceUrl&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;/path/to/your/svg/icon.svg&amp;#39;&lt;/span>));
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, you can go ahead and use the icons anywhere in angular application as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-icon&lt;/span> &lt;span style="color:#a6e22e">svgIcon&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;iconName&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">mat-icon&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please note that in this case I have used the &lt;code>svgIcon=iconName&lt;/code> to reference to the icon.&lt;/p>
&lt;blockquote>
&lt;p>NOTE: The icons are loaded via &lt;code>XmlHttpRequest&lt;/code> and due to the same-origin policy, their URLs must be on the same domain as the containing page, or their servers must be configured to allow cross-domain access.&lt;/p>
&lt;/blockquote>
&lt;h2 id="using-class-based-icons-font-awesome-and-similar-icons">Using Class Based Icons (Font Awesome and Similar Icons)&lt;/h2>
&lt;p>You can also use Font Awesome and other icon sets that use CSS Classes to load font with Mat-Icon Component. And just like SVG Icons, you must register the parent class first in your application. To use Font-Awesome, follow the steps below. Identify the first component of your application (in most cases it will be the &lt;code>app.component.ts&lt;/code>) and them import the &lt;code>MatIconRegistry&lt;/code> module as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MatIconRegistry&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/material&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then register the font-awesome class – &lt;code>fa&lt;/code> – under the component constructor.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#66d9ef">constructor&lt;/span> (&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#a6e22e">matIconRegistry&lt;/span>: &lt;span style="color:#66d9ef">MatIconRegistry&lt;/span>) {
    &lt;span style="color:#75715e">//add custom material icons
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#a6e22e">matIconRegistry&lt;/span>.&lt;span style="color:#a6e22e">registerFontClassAlias&lt;/span> (&lt;span style="color:#e6db74">&amp;#39;fa&amp;#39;&lt;/span>);
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then set the fontIcon to the class of the icon you wish to show, as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-icon&lt;/span> &lt;span style="color:#a6e22e">fontIcon&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;fa-home&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">mat-icon&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please note that in this case I have used the &lt;code>fontIcon=iconName&lt;/code> to reference to the icon. Adding Font-Awesome to your Angular Project First, install font-awesome using either NPM or Yarn as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install --save font-awesome
//for yarn
yarn add font-awesome
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, if you using are SASS, include this on your &lt;code>styles.scss&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-scss" data-lang="scss">&lt;span style="color:#66d9ef">@import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;variables&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;../node_modules/font-awesome/scss/font-awesome&amp;#39;&lt;/span>; &lt;span style="color:#75715e">//path to font awesome SCSS
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then create a &lt;code>_variables.scss&lt;/code> and add the path to the fonts in the &lt;code>$fa-font-path&lt;/code> variable:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-scss" data-lang="scss">$fa-font-path&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;../node_modules/font-awesome/fonts&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you are using &lt;code>CSS&lt;/code>, include the path to the font-awesome CSS in your &lt;code>angular-cli.json&lt;/code> as show below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-json" data-lang="json">&lt;span style="color:#e6db74">&amp;#34;styles&amp;#34;&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> [  
&lt;span style="color:#e6db74">&amp;#34;../node_modules/font-awesome/css/font-awesome.css&amp;#34;&lt;/span>
]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please note, the methods described in this post are not the only way to accomplish this. Thank you.&lt;/p></description></item><item><title>Responsive Navbar with Angular Flex Layout</title><link>https://codinglatte.com/posts/angular/responsive-navbar-angular-flex-layout/</link><pubDate>Thu, 07 Dec 2017 21:58:29 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/responsive-navbar-angular-flex-layout/</guid><description>&lt;p>Today, we are going to create a responsive Navbar using &lt;a href="https://material.angular.io/components/toolbar/overview">Toolbar&lt;/a> and &lt;a href="https://material.angular.io/components/sidenav/overview">Sidenav&lt;/a> Components from &lt;a href="https://material.angular.io/">Angular Material&lt;/a> together with &lt;a href="https://github.com/angular/flex-layout/wiki">Angular Flex Layout&lt;/a>. We will be trying to replicate the behavior of Navbar in where it collapses on small screen and is fully displayed in Large screen.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/responsive-navbar-angular-flex-layout/images/demo.gif" alt="Responsive Navbar with Angular Flex Layout" width="100" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>If you are not aware, &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-better-than-bootstrap/">Angular Flex Layout&lt;/a> provides a responsive Layout API with CSS flexbox and media query for Angular application. This post assumes you have knowledge in &lt;a href="https://angular.io/">Angular 2+ applications&lt;/a> and will not cover the basics. If you are new to Angular, you can learn how to get started &lt;a href="https://angular.io/guide/quickstart">here&lt;/a>. Let’s get started:&lt;/p>
&lt;h2 id="installation-and-initial-setup">Installation and Initial Setup&lt;/h2>
&lt;h3 id="angular-material">Angular Material&lt;/h3>
&lt;p>To install and setup Angular Material, you can follow the detailed instruction &lt;a href="https://material.angular.io/guide/getting-started">here&lt;/a> from the official guide.&lt;/p>
&lt;h3 id="angular-flex-layout">Angular Flex Layout&lt;/h3>
&lt;p>Installing Angular flex layout is simple. Use the following commands:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install @angular/flex-layout –save
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Or&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add @angular/flex-layout
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then import the Flex Layout Module in your app.module.ts as show below&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/flex-layout&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>NB:&lt;/strong> Don’t forget to include FlexLayoutModule in the list of imports in ngModule imports.&lt;/p>
&lt;/blockquote>
&lt;p>Assuming you have successfully installed and setup both Angular Material and Angular Flex Layout, let’s move on and create a responsive navigation bar.&lt;/p>
&lt;h2 id="creating-a-toolbar-and-a-sidenav">Creating a Toolbar and a Sidenav&lt;/h2>
&lt;p>This is rather a straightforward process. We will create a toolbar at the top of the window and a side navigation bar with the same content as the toolbar. The toolbar will have a menu item that will open the Sidenav. This item will only be shown on small screen when the rest of the menu is hidden and vice versa. To create a toolbar, you use the following code below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-toolbar&lt;/span> &lt;span style="color:#a6e22e">color&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;primary&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span>&amp;gt;Responsive Navigation&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt; &amp;lt;&lt;span style="color:#f92672">span&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;example-spacer&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 1&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt; &amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 2&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 3&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt; &amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 4&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 5&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt; &amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 6&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-toolbar&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you see, this is Just a normal material toolbar without any responsive capabilities. Next, lets create a Sidenav with the same items.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">mat-sidenav-container&lt;/span> &lt;span style="color:#a6e22e">fxFlexFill&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;example-container&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-sidenav&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mode&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;side&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">opened&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;false&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 1&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 2&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 3&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 4&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 5&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 6&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-sidenav&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-sidenav-content&lt;/span> &lt;span style="color:#a6e22e">fxFlexFill&lt;/span>&amp;gt; Main content&amp;lt;/&lt;span style="color:#f92672">mat-sidenav-content&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-sidenav-container&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now that we have both a Sidenav and a toolbar working, let&amp;rsquo;s work on making them responsive.&lt;/p>
&lt;h2 id="adding-responsiveness-using-angular-flex-layout">Adding Responsiveness using Angular Flex Layout&lt;/h2>
&lt;p>To add responsiveness to our navbar, we will use Angular Flex Layout to hide and show the toolbar menu items based on screen size. To do this, we enclose the menu items on a div container and then use &lt;a href="https://github.com/angular/flex-layout/wiki/Responsive-API">&lt;code>fxHide&lt;/code> and &lt;code>fxShow&lt;/code>&lt;/a> directive to hide and show the menu items. Example: To hide some content on small screens only:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;”true”&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxHide&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;”true”&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To hide some content on both small and extra small screens only:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;”true”&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxHide&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">lt-md&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;”true”&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Simple? Now, let’s add this to our menu item:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;height: 100vh;&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-toolbar&lt;/span> &lt;span style="color:#a6e22e">color&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;primary&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span>&amp;gt;Responsive Navigation&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt; &amp;lt;&lt;span style="color:#f92672">span&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;example-spacer&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxHide&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">lt-md&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- The following menu items will be hidden on both SM and XS screen sizes --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 1&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 2&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 3&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 4&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 5&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 6&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-toolbar&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, if you resize the browser width to small size, the menu items are hidden instead of being squeezed. But, we need to show a menu icon to reveal or draw the Sidenav on small screens. This will work similarly to the above code but have the opposite effect: Show on small screen, hide on large screens.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxHide&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">gt-sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&amp;gt;&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span>&amp;gt;Show Side Menu&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you can see, instead of hiding on lt-md (less than medium screen size) we are showing the single menu item on gt-sm(great than small screen size). You can use the table below for various breaking points of Angular Flex Layout Responsive API.&lt;/p>
&lt;div class="column">
&lt;div class="amp-image">
&lt;amp-img src="https://codinglatte.com/posts/angular/responsive-navbar-angular-flex-layout/images/screens-sizes.png" alt="Responsive Navbar with Angular Flex Layout" width="500px" class="contain" layout="fill">
&lt;/amp-img>
&lt;/div>
&lt;/div>
&lt;p>Now let’s add the code on the “Show Side Menu” menu item so that it reveals the Sidenav menu items.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxHide&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">gt-sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">sidenav&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">toggle&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;Show Side Menu&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="final-code">Final Code&lt;/h2>
&lt;p>The whole code for a responsive navbar menu will look like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;height: 100vh;&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-toolbar&lt;/span> &lt;span style="color:#a6e22e">color&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;primary&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span>&amp;gt;Responsive Navigation&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">span&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;example-spacer&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">span&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxHide&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">lt-md&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&amp;gt;
&lt;span style="color:#75715e">&amp;lt;!-- The following menu items will be hidden on both SM and XS screen sizes --&amp;gt;&lt;/span>
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 1&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 2&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 3&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 4&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 5&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 6&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxShow&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">fxHide&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">gt-sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">sidenav&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">toggle&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;Show Side Menu&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-toolbar&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-sidenav-container&lt;/span> &lt;span style="color:#a6e22e">fxFlexFill&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;example-container&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-sidenav&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">#&lt;/span>&lt;span style="color:#a6e22e">sidenav&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">sidenav&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">toggle&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Close&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 1&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 2&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 3&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 4&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 5&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">a&lt;/span> &lt;span style="color:#a6e22e">href&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;#&amp;#34;&lt;/span> &lt;span style="color:#a6e22e">mat-button&lt;/span>&amp;gt;Menu Item 6&amp;lt;/&lt;span style="color:#f92672">a&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-sidenav&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">mat-sidenav-content&lt;/span> &lt;span style="color:#a6e22e">fxFlexFill&lt;/span>&amp;gt;Main content&amp;lt;/&lt;span style="color:#f92672">mat-sidenav-content&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">mat-sidenav-container&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can get the whole project on &lt;a href="https://github.com/MainaWycliffe/Responsive-Navbar-with-Angular-Material-and-Angular-Flex-Layout/tree/master">github&lt;/a>.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>This is a simple example of how you can use Angular Material and Angular Flex Layout to create a nice responsive navigation bar for your own application. If you have any question regarding anything I covered in this article, feel free to raise it in the comment section below and I will get back to you. You can also make suggestion on how to improve this simple navbar and other topics you would like me to cover.&lt;/p></description></item><item><title>5 Visual Studio Code Extensions for Angular</title><link>https://codinglatte.com/posts/angular/angular-extensions-visual-studio-code/</link><pubDate>Fri, 24 Nov 2017 22:13:40 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-extensions-visual-studio-code/</guid><description>&lt;p>Visual Studio Code or VSCode is one of the best text editors out there. It is feature rich out of the box and has a lot of extensions which are easy to install. If you are an Angular developer using Visual Studio Code, you might want to consider the following extensions:&lt;/p>
&lt;h1 id="angular-language-service">Angular Language Service&lt;/h1>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/R67RcGftRS.gif" alt="5 Visual Studio Code Extensions for Angular">&lt;/p>
&lt;p>I have been using this extensions for a couple of weeks now and it has improved my coding experience. It relies on both &lt;code>@angular/language-service&lt;/code> and &lt;code>typescript&lt;/code> to provide completions list, and provide AOT (Ahead of Time) Diagnostic messages. It also offers Quick Info and Go to definition options.&lt;/p>
&lt;p>Basically, all variables you have declared inside your typescript files are provided inside the template – be it an inline template or an external template. It also warns about errors that will brought up by the AOT compiler inside the Angular CLI – Such as using undefined variables inside your template and unimported or undeclared modules inside your project. Angular Language service also works nicely with Angular material, warning you if you use unimported material. It is a handy tool to have in your list of plugins.&lt;/p>
&lt;p>&lt;a href="https://marketplace.visualstudio.com/items?itemName=Angular.ng-template">Get Angular Language Service here&lt;/a>.&lt;/p>
&lt;h1 id="tslint-typescript-lint">TSLint (Typescript Lint)&lt;/h1>
&lt;p>Angular relies on &lt;a href="https://www.typescriptlang.org/">Typescript&lt;/a> -  a superset of JavaScript. While you can still use JavaScript or something else like &lt;a href="https://www.dartlang.org/">Dart&lt;/a> or &lt;a href="http://coffeescript.org/">CoffeeScript&lt;/a>, a lot of developers rely on Typescript for their applications. TSLint for VSCode integrates &lt;a href="https://github.com/palantir/tslint">TSLint Tool&lt;/a> into visual studio code.&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;TSLint is an extensible static analysis tool that checks TypeScript code for readability, maintainability, and functionality errors. It is widely supported across modern editors &amp;amp; build systems and can be customized with your own lint rules, configurations, and formatters.&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;p>For this extension to work, it requires both TSLint and Typescript to be installed either locally or globally. To install TSLint and typescript globally you can use the following command: npm install -g tslint typescript.&lt;/p>
&lt;p>&lt;a href="https://marketplace.visualstudio.com/items?itemName=eg2.tslint">Get TSLint Here&lt;/a>.&lt;/p>
&lt;h1 id="angular-5-snippets">Angular 5 Snippets&lt;/h1>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/ngComponentSnippet.gif" alt="5 Visual Studio Code Extensions for Angular">&lt;/p>
&lt;p>This extension provides snippets for TypeScript, Html, &lt;a href="https://codinglatte.com/tech/developers/angular/what-i-learned-when-i-switched-to-angular-material/">Angular Material&lt;/a>, ngRx, RxJS and &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-better-than-bootstrap/">Flex Layout&lt;/a>. Although it requires some effort to learn how to use this extension, it can save you sometime if you learn how to use it. It is also extremely useful to developers who do not use Angular CLI as it will take some task off their hands like creating new components, services etc.&lt;/p>
&lt;p>&lt;a href="https://marketplace.visualstudio.com/items?itemName=Mikael.Angular-BeastCode">Get Angular 5 Snippets here&lt;/a>.&lt;/p>
&lt;h1 id="angular-essentials">Angular Essentials&lt;/h1>
&lt;p>Technically, this is not an extension but rather a pack of extensions. It is packed with multiple extensions for Angular in Visual Studio Code, some already discussed in this list. It contains: Angular 5 Snippets, Angular Language Service, Editor Config, Tslint, Chrome Debugger, Path Intellisense, Angular Inline, Winter is Coming theme and Prettier Formatting extension. If you wanted all angular extensions, install this extension pack and you will get most of them if not all.&lt;/p>
&lt;p>&lt;a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular-essentials">Get Angular Essentials Here&lt;/a>.&lt;/p>
&lt;h1 id="angular-inline">Angular Inline&lt;/h1>
&lt;p>If you use inline stylesheet and templates, you might want to consider Angular Inline. This extension provides Syntax highlighting and Code completion and hover information for inline html. It only works when you wrap your content using the backtrack character (`) which is kind of odd.&lt;/p>
&lt;p>&lt;a href="https://marketplace.visualstudio.com/items?itemName=natewallace.angular2-inline">Get Angular Inline here&lt;/a>&lt;/p></description></item><item><title>What I learned when I switched to Angular Material from Bootstrap</title><link>https://codinglatte.com/posts/angular/what-i-learned-when-i-switched-to-angular-material/</link><pubDate>Tue, 21 Nov 2017 12:32:11 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/what-i-learned-when-i-switched-to-angular-material/</guid><description>&lt;p>A couple months ago, I was having a debate on whether I should switch from Bootstrap to Angular Material. I have used Bootstrap for a very long time and was totally comfortable using it on all my projects. If you are not aware, Angular material is a set of components implementing Google Material Design language on angular applications. You can learn more &lt;a href="https://material.angular.io/">here&lt;/a>.&lt;/p>
&lt;p>What attracted me to Angular Material was the User Experience of its component. How intuitive to user action they were as compared to Bootstrap own components. Yes, you could probably have the same effect by applying a Bootstrap theme, but is it really the same? That’s a discussion for another day. So, I finally made the decision to get out of my comfort zone and implement Angular Material on my first angular app and here is what I learned:&lt;/p>
&lt;h2 id="transition-step-by-step">Transition Step by Step&lt;/h2>
&lt;p>If you decide to make the switch, don’t remove bootstrap at the beginning but at the end, when you have made the switch successfully. This is because Angular Material doesn’t provide a responsive layout by default like bootstrap. It can be very frustrating when your nicely build app falls apart because you decided to remove bootstrap at the beginning.&lt;/p>
&lt;p>Instead, rely on bootstrap for responsive design first or switch to another responsive design library before removing bootstrap. I rememberred that before I fully committed to making the switch, I had to discard all the changes I made to the project several times. To avoid getting frustrated and most likely giving up, focus first on changing the Bootstrap components and then later you can decide on which responsive layout to use.&lt;/p>
&lt;h2 id="responsive-design-isnt-easy-with-angular-material">Responsive Design isn’t Easy with Angular Material&lt;/h2>
&lt;p>Like I said in the point above, Angular Material doesn’t provide a responsive layout by default. While this can be frustrating to some, it is done this way so that it can be easy to optimize when building your app.&lt;/p>
&lt;p>If you want an Angular based solution for responsive layout, you will have to rely on &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-better-than-bootstrap/">Angular Flex Layout&lt;/a>. It has a steep learning curve as compared to bootstrap but if you get used to it, it’s amazing and very robust.&lt;/p>
&lt;h2 id="do-not-import-all-modules-just-include-what-you-need">Do not import all Modules, Just Include what you need&lt;/h2>
&lt;p>If you were to google, you will easily find a list of all Angular Material Components. Most people instinct is to import all modules, so that they can stop worrying about unimported modules while adding new components. While this will work, you will end up with so many unused modules (unless you are using all of them) in your app which will affect its performance.&lt;/p>
&lt;p>It is easier to just import only the modules you need. This is because Angular CLI will always throw an error in case you forgot to import a module you are using. All you will have to do is simply add to your list of imported modules. Angular Material has been optimized for Angular and will only include modules you are using to the final build of your app, leaving out unused features and modules.&lt;/p>
&lt;h2 id="you-will-miss-some-things-in-bootstrap">You will miss some things in Bootstrap&lt;/h2>
&lt;p>Bootstrap is an amazing and one of the most complete front-end framework out there. It has a lot of thing that are still missing from Angular Material. While some can still be added later, some might not even be added. One thing I miss most about bootstrap are the very many helper classes it has: padding, margin, text alignment, font-weight, border, background colors and so many others. May be someone, or even me should port all the helper classes from bootstrap for Angular Material.&lt;/p>
&lt;p>I know these are small things, but they are still very important. Also, when it comes to component, there are some found in Bootstrap not found in Angular Material and vice versa. This can be disappointing especially if you rely on them. You can check my component by component comparison of both Angular Material and Bootstrap &lt;a href="https://codinglatte.com/tech/developers/angular-material-and-bootstrap-framework-components-comparison/">here&lt;/a>.&lt;/p>
&lt;h2 id="its-still-not-officially-released">It’s still not officially released&lt;/h2>
&lt;p>Why is this important? It may not be stable for use in production apps. While as of the time of writing, it is in Release Candidate 1 (released yesterday), which is much more stable as compared to when it was in beta. Still there can be changes that can break your app easily, so be careful when using it. Before updating, you take a look at the &lt;a href="https://github.com/angular/material2/blob/master/CHANGELOG.md">changelog&lt;/a> first so that you don’t break your app. Here is a list some of the planned features for Angular Material:&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/Capture3.png" alt="What I learned when I switched to Angular Material from Bootstrap">&lt;/p></description></item><item><title>Components Comparison Between Angular Material and Bootstrap Framework</title><link>https://codinglatte.com/posts/angular/angular-material-and-bootstrap-framework-components-comparison/</link><pubDate>Fri, 17 Nov 2017 23:09:39 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-material-and-bootstrap-framework-components-comparison/</guid><description>&lt;p>Today, we are going to compare the components in Angular Material and Bootstrap Framework. This comparison is meant to help you decide on whether to go with bootstrap or angular material for your application. Bootstrap provides a nice looking, simple, clean user interface while Angular material looks to provide an enhanced user experience. While this comparison might be useful to most people, to others it might be a matter of preference. Let’s get started:&lt;/p>
&lt;h2 id="common-components">Common Components&lt;/h2>
&lt;p>First, we will look at common components between Angular Material and Bootstrap. By comparing the common components, we get to see which is better or more suitable for your project.&lt;/p>
&lt;h2 id="buttons--button-group">Buttons &amp;amp; Button group&lt;/h2>
&lt;p>Both Angular Material and Bootstrap implement this feature quite similarly. Angular provides less color options for button – Basic, Primary, Accent, Warn, Disabled and Link. On the other hand, Bootstrap provides about 9 color options: Primary, Secondary, Success, Danger, Info, Dark, Warning and Link. Angular material takes this further by providing different types of button: Fab Buttons, Icon Buttons, Raised and Basic (not raised – link like) Buttons. The icon buttons and Fab Buttons are good for small screen devices.&lt;/p>
&lt;h3 id="card">Card&lt;/h3>
&lt;p>I don’t have much to say about cards in both Angular material and Bootstrap. I could not find much difference and I found it straight forward to use either. That said, bootstrap provides more color options as compared to the plain card provided by Angular Material. Maybe it’s because I haven’t dug dipper into the card API in Angular Material, but I would say bootstrap has small advantage here. You can easily fix this issue with CSS.&lt;/p>
&lt;h3 id="collapse-or-expansion-panel">Collapse or Expansion Panel?&lt;/h3>
&lt;p>While both Bootstrap and Angular Material might be using different names for these components, I did not find any significant difference between them. You can choose either and you will not be disappointed. May be the &lt;a href="https://getbootstrap.com/docs/4.0/components/collapse/">collapse&lt;/a> from bootstrap looks a bit dated but that could be easily taken care by some CSS Styling.&lt;/p>
&lt;h3 id="forms--input">Forms &amp;amp; Input&lt;/h3>
&lt;p>These is a group of components for forms found in both Angular Material and Bootstrap. These are the controls you would require for your forms such as text input, checkbox, radio button, text area etc. In this case, Angular has more controls out of the box as compare to Bootstrap. This includes a Date Picker, a Slider, a Slider Toggle and AutoComplete field – Searchable select control. So, in this case Angular Material is much preferable as compared to bootstrap.&lt;/p>
&lt;h3 id="modal-or-dialog">Modal or Dialog?&lt;/h3>
&lt;p>This a case of naming difference for the same component. Having used both, I would be hard pressed to say which one is better. But if you were just interested with a modal window only, then go with angular material as you can import that component only. The same applies to all angular material components.&lt;/p>
&lt;h3 id="menus-components">Menus Components&lt;/h3>
&lt;p>Both Angular Material and Bootstrap have menus components but with different implementation. Angular Material has a toolbar which is equivalent to Bootstraps own navbar component. Angular has a unique sidebar component which has no equivalent in Bootstrap. Bootstrap provides an easy way to create a responsive navbar as compared to Angular Material. In angular you have to rely on &lt;a href="https://github.com/angular/flex-layout">Angular Flex Layout&lt;/a> for a responsive toolbar which can be difficult. Both Angular Material and Bootstrap provide components for normal menu and drop-down menu.&lt;/p>
&lt;h3 id="lists-components">Lists Components&lt;/h3>
&lt;p>The angular material &lt;a href="https://material.angular.io/components/list/overview">list component&lt;/a> is much better compared to the bootstrap &lt;a href="https://getbootstrap.com/docs/4.0/components/list-group/">list group component&lt;/a>. The bootstrap component has more color alternative as compare to Angular material but that can be solved by some CSS styling. Other Components&lt;/p>
&lt;ol>
&lt;li>Pagination&lt;/li>
&lt;li>Progress&lt;/li>
&lt;li>Tooltips&lt;/li>
&lt;/ol>
&lt;h2 id="bootstrap-unique-components">Bootstrap Unique Components&lt;/h2>
&lt;p>Just like they have some common components, this two have their differences. There are some components found on Bootstrap but not found in Angular Material. It is important to note these components can still be added to Angular Material or vice versa on a latter release. These is a list of components that are currently found Bootstrap but not Angular Material.&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://getbootstrap.com/docs/4.0/components/alerts/">Alerts&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://getbootstrap.com/docs/4.0/components/breadcrumb/">Breadcrumb&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://getbootstrap.com/docs/4.0/components/carousel/">Carousel&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://getbootstrap.com/docs/4.0/components/collapse/">Collapse&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://getbootstrap.com/docs/4.0/components/jumbotron/">Jumbotron&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://getbootstrap.com/docs/4.0/components/popovers/">Popovers&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://getbootstrap.com/docs/4.0/components/scrollspy/">Scrollspy&lt;/a>&lt;/li>
&lt;/ol>
&lt;h2 id="angular-material-unique-components">Angular Material Unique Components&lt;/h2>
&lt;p>Here is a list of components currently found in Angular Material but not in Bootstrap:&lt;/p>
&lt;ol>
&lt;li>Date picker&lt;/li>
&lt;li>Slider&lt;/li>
&lt;li>Slide toggle&lt;/li>
&lt;li>Toolbar&lt;/li>
&lt;li>Grid list&lt;/li>
&lt;li>Stepper&lt;/li>
&lt;li>Chips&lt;/li>
&lt;li>Icon&lt;/li>
&lt;li>Progress spinner&lt;/li>
&lt;li>Snackbar&lt;/li>
&lt;li>Sort header&lt;/li>
&lt;/ol>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>Both Angular Material and Bootstrap have lots of amazing components. While in the case of bootstrap there is more than just component, it has utilities and a lot of helper classes and responsive grid design all rolled up in one. On the other hand, Angular material does have some helper classes and better integration with &lt;a href="https://material.angular.io/components/icon/overview">Material Icons&lt;/a>. On its own, it doesn’t provide responsive web design but can be used together with &lt;a href="https://github.com/angular/flex-layout">Angular Flex Layout&lt;/a> to achieve that. If you decide to go with Angular material, you might want to have a look at &lt;a href="https://codinglatte.com/tech/developers/angular/angular-flex-better-than-bootstrap/">Angular Flex&lt;/a> for responsive design. In case you decide to go with Bootstrap, here is a &lt;a href="https://codinglatte.com/tech/developers/using-angular-4-bootstrap-4/">guide&lt;/a> to assist you get started with bootstrap in your Angular project.&lt;/p></description></item><item><title>Is Angular Flex Layout (with Angular Material) Better than Bootstrap for Responsive Layout?</title><link>https://codinglatte.com/posts/angular/angular-flex-better-than-bootstrap/</link><pubDate>Wed, 15 Nov 2017 00:06:51 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-flex-better-than-bootstrap/</guid><description>&lt;p>First before I can say anything else, I want to express my huge respect and love for Bootstrap. I am not writing this to bash bootstrap in any way, in fact bootstrap is one of the most robust frontend framework I have ever used. A few years ago, Google announced a new designed language when they released Android 5 (Marshmallow) and since then, it has been spreading like wildfire. If you wanted to use Material design in Angular, you use &lt;a href="https://material.angular.io/">Angular Material&lt;/a>. Angular Material is in simple terms is a set of components (i.e. Date Picker, Cards, Toolbar etc.)  with the material design aesthetic. On its own, Angular Material can not provide a responsive design like bootstrap does. And that’s where Angular Flex Layout comes in and that’s what I want to focus on.&lt;/p>
&lt;h1 id="angular-flex-layout">Angular Flex Layout&lt;/h1>
&lt;p>Bootstrap has a simple grid system divided into 12 sections for different screen sizes – Extra Small (xs), small (sm), medium (md) and large (lg). The extra small (xs) has been removed in Bootstrap 4. Angular Flex Layout on the other hand provides a more robust grid system which relies with CSS flex. The issue with relying on flex is browser compatibility. While most browsers support flex CSS in their latest versions, some earlier versions don’t. This may be problematic if your users have an old incompatible version of browser. In that case, stick with bootstrap. It has 5 regions but with different breaking points for different screen sizes as compared to Bootstrap. Refer to the image below:&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/screen-sizes.png" alt="Is Angular Flex Layout (with Angular Material) Better than Bootstrap for Responsive Layout?">&lt;/p>
&lt;p>The beauty of Angular Flex Layout approach is how you define the layout regions in relationship to each other. It is not also limited to 12 regions like bootstrap but rather you can include any unit of measure to define a region. You can use percentage points, pixels, inches to define width, height, margin and its extremely easy to do so. It makes using CSS flex very easy, although coming from bootstrap it took time getting used to it. A good example of this is: Let’s say you want to create a layout with 3 unequal columns:&lt;/p>
&lt;h2 id="in-bootstrap">In bootstrap&lt;/h2>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-sm-6&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-sm-4&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-sm-2&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="in-angular-flex-layout">In Angular Flex Layout&lt;/h3>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">flex&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;50&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;33&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;17&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>As you can see from the sample code, they produce much similar codes but with flex you can use percentage or pixels or anything else for sizes. You can now manipulate the above code for different screen sizes like, arranging them vertically for small devices as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">flex&lt;/span> &lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**&lt;/span>&lt;span style="color:#a6e22e">fxLayout&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">lt-sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;column&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;50&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;33&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">fxFlex&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;27&amp;#34;&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can achieve the same with bootstrap, but that mean repeating the class on all divs as follows:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;row&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-md-6 **col-sm-12&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-md-4 **col-sm-12&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">class&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;col-md-2 **col-sm-12&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To get a feeling of what Angular Flex Layout can do, visit the following live demo &lt;a href="https://tburleson-layouts-demos.firebaseapp.com/#/docs">here&lt;/a>. With Angular Flex Layout, you can apply specific classes, styles and directives on specific screen sizes or a range of screen sizes as defined &lt;a href="https://github.com/angular/flex-layout/wiki/Responsive-API">here&lt;/a>. For example, to apply a class to only small devices, all you have to do is add a .sm to the end of the ngClass name as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**&lt;/span>&lt;span style="color:#a6e22e">ngClass&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">.&lt;/span>&lt;span style="color:#a6e22e">sm&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;class-for-small-devices&amp;#34;&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">**&lt;/span>&amp;gt;&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>I am not saying it’s perfect, in fact, it’s far from that. But for a library still in beta it works very well. There are somethings I like in bootstrap like helper classes for boldening text, aligning text, padding, margin among others. But that won’t stop me from switching from Bootstrap to using both Angular Material and Angular Flex Layout.&lt;/p>
&lt;h2 id="requirements">Requirements&lt;/h2>
&lt;p>Requirement part is a bit confusing in the official documents because they have stated the following:&lt;/p>
&lt;ul>
&lt;li>requires Angular v4.1.x or higher.&lt;/li>
&lt;li>is currently only available for Angular (v2.x or higher) Applications.&lt;/li>
&lt;/ul>
&lt;p>I don’t know which one is which. If you have the latest version of Angular, you are good to go. But, for those still using v2 or v4.0 – please give it a go and comment below on whether It works.&lt;/p>
&lt;h2 id="how-to-get-started">How to Get Started&lt;/h2>
&lt;p>To install Angular Flex Layout, you can use either &lt;a href="https://codinglatte.com/tech/developers/angular/setup-angular-touse-yarn-package-manager/">Yarn&lt;/a> or NPM with the following commands&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">yarn add @angular/flex@latest
npm install @angular/flex@latest
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then, you have to remember to import it into your project in the app.module.ts&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">FlexLayoutModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/flex-layout&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And remember to add it to your list of imports imports. After that you are can use angular/flex for in your projects.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>To conclude, Angular Material and Angular Flex Layout are better than bootstrap. This is not to say you shouldn’t use bootstrap, but you should consider using both libraries. Of course, you can still use either independently if you wish to, Angular Material for the nice-looking UI component and Angular Flex Layout for responsive design.&lt;/p></description></item><item><title>NgRev – Analyze and Profile your Angular App</title><link>https://codinglatte.com/posts/angular/ngrev-analyze-profile-angular-app/</link><pubDate>Mon, 13 Nov 2017 15:29:27 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/ngrev-analyze-profile-angular-app/</guid><description>&lt;p>NgRev is a graphical tool designed to reverse engineer your Angular application. It is not a browser extension like &lt;a href="https://codinglatte.com/tech/developers/angular/augury-debug-profile-angular-app/">Augury&lt;/a>, but a standalone software available for MacOS, Windows and Linux. It does a static code analysis of your application and doesn’t require your application to be built (compiled) to use it. The tool allows you to navigate in the structure of your application and observe the relationship between the different modules, providers and directives. This can be helpful if you wish to get up to speed on a new project by seeing how it build.&lt;/p>
&lt;p>The one downside I found was that it &lt;a href="https://github.com/mgechev/ngrev/issues/23">stopped working&lt;/a> with my application when I upgraded to &lt;a href="https://codinglatte.com/tech/developers/angular/how-to-upgrade-your-angular-4-app-to-angular-5-0/">Angular 5&lt;/a> application. I have used it on several of my projects in Angular 4 and it was working fine though. May be an update will be released soon to make it compatible with Angular 5 and Angular CLI 1.5. You can follow the issue raised on the apps Github page &lt;a href="https://github.com/mgechev/ngrev/issues/23">here&lt;/a>.&lt;/p>
&lt;p>If you would like to try out NgRev, please go to &lt;a href="https://github.com/mgechev/ngrev/releases">this&lt;/a> link and download the app for your operating system. Install the downloaded application, if you are stuck with installation, follow &lt;a href="https://github.com/mgechev/ngrev">these detailed instructions&lt;/a> located on their &lt;a href="https://github.com/mgechev/ngrev">github page&lt;/a>.&lt;/p>
&lt;h2 id="how-it-works">How it works&lt;/h2>
&lt;p>First, your application needs to be compatible with Angular AOT (Ahead of Time) Compiler. When using Angular, some people compile their application without AOT. It is faster but also ignores lots of errors – I learned that the hard way. To build with AOT, all you need to do is add the -aot flag when serving or building your app.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng server -aot or ng build -aot
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If your app is compatible follow the following instruction (Works for both Angular CLI and Angular Seed Project):&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/ngrev.png" alt="ngRev - Start Window">&lt;/p>
&lt;ol>
&lt;li>Open the ngRev Application&lt;/li>
&lt;li>Click on the open project button (big large blue button at the center of the application)&lt;/li>
&lt;li>Navigate to your project folder and select tsconfig.json located inside the src folder inside the project folder.&lt;/li>
&lt;li>Now you can navigate through your project graphically.&lt;/li>
&lt;/ol></description></item><item><title>PHP: Frameworks vs Microframeworks</title><link>https://codinglatte.com/posts/php/php-frameworks-vs-microframeworks/</link><pubDate>Sun, 12 Nov 2017 22:18:37 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/php/php-frameworks-vs-microframeworks/</guid><description>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>A PHP Framework in simple terms is a platform used by developers to create web applications – obviously made by PHP.  They help developers concentrate on their applications – the bigger picture – instead of some small details like creating a database connection. Instead you can concentrate on how best to query your data. They make it easier to develop PHP applications rapidly and take care of thing like security and enforce coding standards or style of coding. Frameworks tend to be bloated with many libraries a developer may never use.&lt;/p>
&lt;p>A good example for this are databases. There are so many databases you can use with your application such as MySQL, MSSQL, Oracle etc. A PHP framework will have libraries and ability to connect to all this database and if you are just using one, then you don’t need the rest of the database libraries. And that’s why we have microframeworks.&lt;/p>
&lt;p>A microframework is a framework in its own light but with barebone libraries and functionality with modular support – they are skeletons of frameworks. A microframework only has the libraries you need to get started and then you can add modules for what you need to do. Microframeworks have a small code footprint. It also improves their performance.&lt;/p>
&lt;p>Good examples of a microframeworks are &lt;a href="https://www.slimframework.com/">Slim&lt;/a> and &lt;a href="https://lumen.laravel.com/">lumen&lt;/a> among others. While examples of frameworks are &lt;a href="https://laravel.com/">Laravel&lt;/a>, &lt;a href="https://framework.zend.com/">Zend&lt;/a> and &lt;a href="https://symfony.com/">Symphony&lt;/a>.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/Symfony.png" alt="PHP: Frameworks vs Microframeworks">&lt;/p>
&lt;h2 id="when-to-use-frameworks">When to use Frameworks?&lt;/h2>
&lt;p>The world is large enough for both Frameworks and Microframeworks. The thing is, you need to know when to use a framework and when to use a microframework. Frameworks can be used on projects of all kinds, especially when you are on tight deadline.  Frameworks are good for building large PHP application that will utilize the large number of libraries that come with them.&lt;/p>
&lt;h2 id="when-to-use-microframeworks">When to use Microframeworks&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/slim-discourse-logo-1024x234.png" alt="PHP: Frameworks vs Microframeworks">&lt;/p>
&lt;p>Unlike frameworks, Microframeworks are not for every web application. They are suitable to small PHP applications like REST APIs. These applications perform specific functions and hence require just a few libraries which leads to a small footprint. They also provide developers with the freedom of choosing their own libraries to achieve what they want.&lt;/p>
&lt;p>You can still use a microframework instead of a framework and vice versa but I would not recommend it. This is because if you were to use a microframework in place of a framework, you would end up adding a lot of libraries found in frameworks and hence end up with a framework. On the other hand, if you used a framework in place of a microframework, you would have a lot of libraries that are unnecessary. This would affect the performance of your application negatively.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>When it comes to choosing a framework or microframework or even whether to use a framework, personal preferences come into play. But if you were looking for some guide on which framework to use, please read the &lt;a href="https://medium.com/@elitechsystems/the-most-popular-php-frameworks-in-2017-a90a1189405e">following detailed analysis&lt;/a>.&lt;/p>
&lt;p>On a personal note though, I would recommend Laravel or Symphony for a framework and Slim or Lumen for a microframework. Lumen is microframework from Laravel and hence if you are already acquainted with Laravel, then Lumen is the obvious choice.&lt;/p></description></item><item><title>Augury – A Tool to Debug and Profile your Angular App</title><link>https://codinglatte.com/posts/angular/augury-debug-profile-angular-app/</link><pubDate>Fri, 10 Nov 2017 22:39:33 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/augury-debug-profile-angular-app/</guid><description>&lt;p>Augury is an open source &lt;a href="https://augury.angular.io/">tool&lt;/a> available to Google Chrome that was developed by Google in conjunction with &lt;a href="https://rangle.io/">Rangle.IO&lt;/a> for debugging and profiling your Angular application. Augury will provide detailed insights of your application structure and how different app building blocks relate to each other. These building blocks are: Components, Services, Routes, Modules, Dependencies, Injectors, Data bindings, Events and Object properties. Augury helps Angular developers to visualize their application through component trees and debugging tools. For Augury to work your app must be in development mode and won’t work on when in development mode.&lt;/p>
&lt;h1 id="features">Features&lt;/h1>
&lt;p>It has the following features that are useful to your application:&lt;/p>
&lt;h2 id="dependency-injection">Dependency Injection&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/properties.png" alt="Augury - Component Tree">&lt;/p>
&lt;p>Augury Provides a hierarchical view of the structure of your Angular App. You can view components and how they relate to each other in the application – Parent – child component relationship. It will provide more information on the property tab (located on the right) if you select a component. This will display the state and the title of the component. You can also view the source code of a component by selecting view source on the property tab.&lt;/p>
&lt;p>Please note if a source map doesn’t exist for your application, you will see minified JS source instead of your beautifully crafted TypeScript code Also, you can view the app dependencies inside the state property under the property tab. This information is also provided visually using the injector graph tab just next to the property tab. It provides a visual representation of component dependencies instead of using the source code to do the same. You can learn more about this &lt;a href="https://augury.angular.io/pages/guides/dependency-injection.html">here&lt;/a>.&lt;/p>
&lt;h2 id="module-list">Module List&lt;/h2>
&lt;p>This will provide you with information about all the modules in your application starting with appModule. This feature provides a list of imports, exports, providers, declarations found in the module. This includes all angular modules you have used in your application such as BrowserModule, httpModule etc. and all your feature modules that you have created yourself. You can learn more about this &lt;a href="https://augury.angular.io/pages/guides/module-list.html">here&lt;/a>.&lt;/p>
&lt;h2 id="routes-tree">Routes Tree&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/unnamed.png" alt="Augury - Router Tree">&lt;/p>
&lt;p>Router tree displays all the defined routes that are currently loaded in the application in a hierarchical tree manner. It starts from the &lt;code>AppComponent&lt;/code> which is the root components going all the way to the last component in the root. It will show you the name of the component and the router path if you hover on a route in the route tree. You can more about augury routes feature &lt;a href="https://augury.angular.io/pages/guides/routes.html">here&lt;/a>.&lt;/p>
&lt;h2 id="installation">Installation&lt;/h2>
&lt;p>You can get augury in the Google Chrome Webstore &lt;a href="https://chrome.google.com/webstore/detail/augury/elgalmkoelokbchhkhacckoklkejnhcd">here&lt;/a>. Then click on &lt;code>add to chrome&lt;/code> and wait for the process to complete. There are other browser that accept chrome extensions but I have not tested whether augury works on them.&lt;/p>
&lt;h2 id="using-augury">Using Augury&lt;/h2>
&lt;p>You must have an angular application in development mode to use Augury. Then open the developers’ tools (DevTools) in chrome by pressing &lt;code>Ctrl + Shift + I&lt;/code> in windows or &lt;code>Cmd + Opt + I&lt;/code> in Mac OS X. Then locate the Augury tab on the far right.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/devtools.png" alt="Augury – A Tool to Debug and Profile your Angular App">&lt;/p>
&lt;p>You can get augury tutorials and detailed demos &lt;a href="https://augury.angular.io/pages/guides/">here&lt;/a>.&lt;/p></description></item><item><title>Angular 5 – Handling Token Based Authentication</title><link>https://codinglatte.com/posts/angular/angular-5-token-based-authentication/</link><pubDate>Thu, 09 Nov 2017 00:28:59 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-5-token-based-authentication/</guid><description>&lt;p>Token based authentication is popular for single page applications. A token is a security code issued by a server for authenticating and identifying users. When a user login to the system or application, the servers issues a token that expires after a specified period. The use of token eliminates the need for the app or system to remember or store the user’s credentials. You can learn more about token based authentication &lt;a href="https://scotch.io/tutorials/the-ins-and-outs-of-token-based-authentication">here&lt;/a>. When creating an app that uses Token Based Authentication in Angular, you need to make the following considerations:&lt;/p>
&lt;ol>
&lt;li>Where will you store the token?&lt;/li>
&lt;li>How will you send them to the server with every request?&lt;/li>
&lt;li>How will you handle unauthorized (Status 401) response?&lt;/li>
&lt;li>How will you handle token refreshes?&lt;/li>
&lt;/ol>
&lt;p>To break it down, let’s look at the 4 considerations:&lt;/p>
&lt;h2 id="where-will-you-store-the-token">Where will you store the token?&lt;/h2>
&lt;p>Web browsers usually offer 3 types of storage: Cookie, Session Storage and Local Storage. Each storage method has its own advantages and disadvantages. I would recommend using a Session Cookie to store your token. Why? Local storage does not get cleared when the user closes their browser and it would be difficult to clear the data on all circumstances. Session Storage on the other hand is limited to one tab per session, hence if a user opens more tabs they would have to login on each occasion (unless that’s exactly what you want).
This leaves cookies, as a method of storage and not for maintaining sessions. A session cookie will be shared across all tabs and windows in the browser and will be deleted once the user closes the browser. This cookie would have to be set and be readable by the app, so no Http-only flag. And since sending the cookie to the server has no effect, set the path to a non-existent path to prevent that. To set a session cookie don’t set an expiry date to the cookie and the browser will know to clear the cookies when it’s closed. To set cookies using angular, use &lt;a href="https://www.npmjs.com/package/ngx-cookie-service">&lt;code>ngx-cookie-service&lt;/code>&lt;/a> component.&lt;/p>
&lt;h2 id="how-will-you-send-tokens-to-the-server-with-every-request">How will you send tokens to the server with every request?&lt;/h2>
&lt;p>You will need to send the token to the server with every request. Failure to do so, the server will not be able to identify and authenticate you hence will reject your request. To do this, you can use the authorization header and attach the token as the value of the header. The server will then read the header and get the token to authenticate your request. To do this, you will require to intercept all http requests and attach the header automatically. You can learn how to create a http interceptor &lt;a href="https://codinglatte.com/tech/developers/angular/building-http-interceptor-angular-5/">here&lt;/a>. Then with every request you can add the authorization header inside the http request as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">Authorization&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">authService&lt;/span>.&lt;span style="color:#a6e22e">getToken&lt;/span>(); &lt;span style="color:#75715e">//read the token from storahe
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">authReq&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({
&lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;authorization&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">Authorization&lt;/span>)
}); &lt;span style="color:#75715e">// Clone the request to add the authorization header.
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">authReq&lt;/span>); &lt;span style="color:#75715e">// Pass on the cloned request instead of the original request.
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>(NB: I have just used a simple header name, you can use the method of your choice like &lt;a href="https://swagger.io/docs/specification/authentication/bearer-authentication/">Bearer Authentication scheme&lt;/a>) You have now managed to send the token with every request to the server.&lt;/p>
&lt;h2 id="how-will-you-handle-unauthorized-http-status-401-response">How will you handle unauthorized (HTTP Status 401) response?&lt;/h2>
&lt;p>The other consideration is handling unauthorized responses from the server. A server returns unauthorized response (HTTP Status 401) if there is an issue with the credentials i.e. invalid or if they don’t exist. The server could also return this option if the token is expired and a refresh is required (We will discuss this in the next step). It’s important to note that unauthorized response is different form forbidden (HTTP Status 403) which means you have the correct credentials but you are forbidden from accessing a specific resource. Since the server was unable to authenticate the user, you could redirect them to the login page or show a login modal form. To achieve this, you need to catch all error responses from the server and check for those returning status 401. Then you could redirect them to the login page as shown below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">authReq&lt;/span>)
.&lt;span style="color:#66d9ef">catch&lt;/span>((&lt;span style="color:#a6e22e">error&lt;/span>, &lt;span style="color:#a6e22e">caught&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">error&lt;/span>.&lt;span style="color:#a6e22e">status&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#ae81ff">401&lt;/span>) {
&lt;span style="color:#75715e">//logout users, redirect to login page
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">authService&lt;/span>.&lt;span style="color:#a6e22e">removeTokens&lt;/span>();
&lt;span style="color:#75715e">//redirect to the signin page or show login modal here
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">router&lt;/span>.&lt;span style="color:#a6e22e">navigate&lt;/span>(&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>[&lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">auth&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">signin&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>]); &lt;span style="color:#75715e">//remember to import router class and declare it in the class
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>.&lt;span style="color:#66d9ef">throw&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>);
} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>.&lt;span style="color:#66d9ef">throw&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>);
}
}
) &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will simply redirect all status codes 401 to the sign in page.&lt;/p>
&lt;h2 id="how-will-you-handle-token-refreshes">How will you handle token refreshes?&lt;/h2>
&lt;p>It would be a bad precedent to set the token expiration to too long or have the user login to the system every few minutes because a token expired. A good compromise is coming with a way of refreshing an expired token. For instance, you could have a refresh token that last longer than the other authorization token but can only be used once. Then you can set the authorization token to expire in a few minutes and the refresh token to expire a little bit longer like a couple of hours.
This way, even when the authorization token expires you can ask for a new one from the server transparently. What I like to do is have the server return a status code that is not defined by the HTTP standard. A good example is 419 or 490. Then the interceptor can catch all 419s and attempt to refresh the authorization token. If successful, it should resend the original request with the new authorization header. If it fails, redirect the user to the login page. The refresh method would look something like this:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">refreshToken&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">string&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
    &lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">refreshAuth&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">getRefreshToken&lt;/span>(); &lt;span style="color:#75715e">//get refresh token from storage
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    &lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">url&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">BASE_URL&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34;auth/refresh&amp;#34;&lt;/span>;
    &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#a6e22e">url&lt;/span>, {
      &lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">HttpHeaders&lt;/span>().&lt;span style="color:#a6e22e">set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshAuthorization&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">refreshAuth&lt;/span>),
      &lt;span style="color:#a6e22e">observe&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;response&amp;#39;&lt;/span>
    }).&lt;span style="color:#a6e22e">map&lt;/span>(&lt;span style="color:#a6e22e">refreshResponse&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
      &lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">authToken&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">refreshResponse&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;authorizationToken&amp;#39;&lt;/span>);
      &lt;span style="color:#66d9ef">let&lt;/span> &lt;span style="color:#a6e22e">refreshToken&lt;/span>: &lt;span style="color:#66d9ef">string&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">refreshResponse&lt;/span>.&lt;span style="color:#a6e22e">headers&lt;/span>.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;refreshToken&amp;#39;&lt;/span>);
      &lt;span style="color:#75715e">//add token to storage
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">createToken&lt;/span>(&lt;span style="color:#a6e22e">authToken&lt;/span>, &lt;span style="color:#a6e22e">refreshToken&lt;/span>); &lt;span style="color:#75715e">// method for adding token to cookie storage
&lt;/span>&lt;span style="color:#75715e">&lt;/span>      &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">authToken&lt;/span>; &lt;span style="color:#75715e">//return the new authorization token
&lt;/span>&lt;span style="color:#75715e">&lt;/span>    });
  }
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now you can intercept all responses with status code 419 for expired tokens and attempt to refresh the tokens. The code below shows how to handle refreshing of tokens with a custom http code 419. It should be inside the catch block of the http interceptor.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">error&lt;/span>.&lt;span style="color:#a6e22e">status&lt;/span> &lt;span style="color:#f92672">===&lt;/span> &lt;span style="color:#ae81ff">419&lt;/span>) {
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">authService&lt;/span>.&lt;span style="color:#a6e22e">refreshToken&lt;/span>().&lt;span style="color:#a6e22e">flatmap&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">inflightAuthRequest&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">null&lt;/span>;
&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">authReq&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({ &lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;authorization&amp;#39;&lt;/span>, &lt;span style="color:#a6e22e">t&lt;/span>) });
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">authReq&lt;/span>); &lt;span style="color:#75715e">//refresh was success, resend the original request
&lt;/span>&lt;span style="color:#75715e">&lt;/span> });
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will try and refresh the token and incase it fails, it will redirect the user to the login page. Now you have a simple token based authentication system in Angular. &lt;a href="https://github.com/MainaWycliffe/angular-simple-token-basedauthentication-interceptor/blob/master/httpinteceptorclass.ts">Here&lt;/a> is the full code for the http interceptor.&lt;/p></description></item><item><title>How to build a HTTP Interceptor in Angular 5</title><link>https://codinglatte.com/posts/angular/building-http-interceptor-angular-5/</link><pubDate>Wed, 08 Nov 2017 00:20:16 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/building-http-interceptor-angular-5/</guid><description>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>A HTTP Interceptor enables you to catch HTTP requests and responses so that you can modify them. It is very useful especially when you want to add extra headers to all outgoing requests or catch error responses from the server. One use case scenario for an interceptor is adding authorization header for authentication to all request.&lt;/p>
&lt;p>You could add an authorization header manually to all requests but that would be a lot of work. Or you could automatically intercept and append the header before sending the request to the server. Another use case scenario is handling errors and caching of content. You can use an interceptor to catch errors and log them or serve cached content to the user instead of getting content from the server.&lt;/p>
&lt;p>We are going to build a simple Interceptor that will catch-all outgoing requests and incoming responses and log them in console. You can view the console of your browser by opening the developers’ tools.&lt;/p>
&lt;h2 id="getting-started">Getting Started&lt;/h2>
&lt;p>First, we are going to create a new &lt;a href="https://codinglatte.com/tech/developers/angular/angular-5-hasbeen-released/">Angular 5&lt;/a> Application using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng new httpinterceptor
&lt;/code>&lt;/pre>&lt;/div>&lt;p>A new directory will be created known as &lt;code>httpinterceptor&lt;/code>. This is the location of your newly created project. You can run the application and the output would look like this: &lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/Capture1.png" alt="How to build a HTTP Interceptor in Angular 5"> We shall use &lt;a href="https://jsonplaceholder.typicode.com/">JSON PlaceHolder&lt;/a> as our endpoint to make our http requests. This is a Fake Online REST API for Testing and Prototyping. It has several variations of http requests which we can call expecting different results, it’s also free. To make any http requests we need to import the &lt;code>HttpClientModule&lt;/code> into our application in the &lt;code>app.module.ts&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">BrowserModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/platform-browser&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">HttpClientModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/common/http&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AppComponent&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app.component&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">BrowserModule&lt;/span>, &lt;span style="color:#a6e22e">HttpClientModule&lt;/span>],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we need to add two buttons in our &lt;code>app.component.html&lt;/code> file. The two buttons will call different methods on click. The first method will call an genuine URL while the second one will call a bogus URL that doesn’t exist hence triggering an error. Replace everything in the file with the following:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-html" data-lang="html">&amp;lt;&lt;span style="color:#f92672">div&lt;/span> &lt;span style="color:#a6e22e">style&lt;/span>&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;text-align:center&amp;#34;&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">h1&lt;/span>&amp;gt;Click one of the two buttons&amp;lt;/&lt;span style="color:#f92672">h1&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">method1Call&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;Method 1&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;&lt;span style="color:#f92672">button&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">(&lt;/span>&lt;span style="color:#a6e22e">click&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">)=&amp;#34;&lt;/span>&lt;span style="color:#a6e22e">method2Call&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">()&amp;#34;&lt;/span>&amp;gt;Method 1&amp;lt;/&lt;span style="color:#f92672">button&lt;/span>&amp;gt;
&amp;lt;/&lt;span style="color:#f92672">div&lt;/span>&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now that we have a user interface, we need to add the two methods to our &lt;a href="https://github.com/MainaWycliffe/angular-httpinterceptor/blob/master/src/app/app.component.ts">&lt;code>app.component.ts&lt;/code>&lt;/a> and import &lt;code>HTTPClient&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Component&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">HttpClient&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/common/http&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@Component&lt;/span>({
&lt;span style="color:#a6e22e">selector&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;app-root&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">templateUrl&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app.component.html&amp;#39;&lt;/span>,
&lt;span style="color:#a6e22e">styleUrls&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#e6db74">&amp;#39;./app.component.css&amp;#39;&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppComponent&lt;/span> {
&lt;span style="color:#a6e22e">title&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;app&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">constructor&lt;/span>(&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">httpClient&lt;/span>: &lt;span style="color:#66d9ef">HttpClient&lt;/span>) {}
&lt;span style="color:#a6e22e">method1Call&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">httpClient&lt;/span>
.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;https://jsonplaceholder.typicode.com/users&amp;#39;&lt;/span>)
.&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">success&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;Successfully Completed&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">success&lt;/span>);
});
}
&lt;span style="color:#a6e22e">method2Call&lt;/span>()&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> {
&lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">httpClient&lt;/span>
.&lt;span style="color:#a6e22e">get&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;https://jsonplaceholder.typicode.com/user12&amp;#39;&lt;/span>)
.&lt;span style="color:#a6e22e">subscribe&lt;/span>(&lt;span style="color:#a6e22e">success&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;Successfully Completed&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">success&lt;/span>);
});
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>We expect the first request to succeed but the 2nd one to fail. Instead of using the fail method inside a subscribe method, we will use the interceptor to catch the errors and log them. Here are the results so far.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/results-1.png" alt="How to build a HTTP Interceptor in Angular 5">&lt;/p>
&lt;h2 id="adding-a-http-interceptor">Adding a HTTP Interceptor&lt;/h2>
&lt;p>To add an interceptor, create a new class using Angular CLI.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng g class my-http-interceptor
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And then import the following modules (&lt;code>HttpEvent&lt;/code>, &lt;code>HttpInterceptor&lt;/code>, &lt;code>HttpHandler&lt;/code>, &lt;code>HttpRequest&lt;/code>) from &lt;code>HTTPClientModule&lt;/code>. Then create an interceptor method as &lt;a href="https://github.com/MainaWycliffe/angular-httpinterceptor/blob/master/src/app/httpinterceptor.ts">follows&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Injectable&lt;/span>, &lt;span style="color:#a6e22e">Injector&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> {
&lt;span style="color:#a6e22e">HttpEvent&lt;/span>,
&lt;span style="color:#a6e22e">HttpInterceptor&lt;/span>,
&lt;span style="color:#a6e22e">HttpHandler&lt;/span>,
&lt;span style="color:#a6e22e">HttpRequest&lt;/span>
} &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/common/http&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Observable&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;rxjs/Rx&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;rxjs/add/observable/throw&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> &lt;span style="color:#e6db74">&amp;#39;rxjs/add/operator/catch&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@Injectable&lt;/span>()
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">MyHttpInterceptor&lt;/span> &lt;span style="color:#66d9ef">implements&lt;/span> &lt;span style="color:#a6e22e">HttpInterceptor&lt;/span> {
&lt;span style="color:#66d9ef">constructor&lt;/span>() {}
&lt;span style="color:#a6e22e">intercept&lt;/span>(
&lt;span style="color:#a6e22e">req&lt;/span>: &lt;span style="color:#66d9ef">HttpRequest&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;span style="color:#a6e22e">next&lt;/span>: &lt;span style="color:#66d9ef">HttpHandler&lt;/span>
)&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">HttpEvent&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#a6e22e">any&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span> {
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;intercepted request ... &amp;#39;&lt;/span>);
&lt;span style="color:#75715e">// Clone the request to add the new header.
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">authReq&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">clone&lt;/span>({
&lt;span style="color:#a6e22e">headers&lt;/span>: &lt;span style="color:#66d9ef">req.headers.set&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;headerName&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;headerValue&amp;#39;&lt;/span>)
});
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;Sending request with new header now ...&amp;#39;&lt;/span>);
&lt;span style="color:#75715e">//send the newly created request
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">next&lt;/span>.&lt;span style="color:#a6e22e">handle&lt;/span>(&lt;span style="color:#a6e22e">authReq&lt;/span>).&lt;span style="color:#66d9ef">catch&lt;/span>((&lt;span style="color:#a6e22e">error&lt;/span>, &lt;span style="color:#a6e22e">caught&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {
&lt;span style="color:#75715e">//intercept the respons error and displace it to the console
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;Error Occurred&amp;#39;&lt;/span>);
&lt;span style="color:#a6e22e">console&lt;/span>.&lt;span style="color:#a6e22e">log&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>);
&lt;span style="color:#75715e">//return the error to the method that called it
&lt;/span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Observable&lt;/span>.&lt;span style="color:#66d9ef">throw&lt;/span>(&lt;span style="color:#a6e22e">error&lt;/span>);
}) &lt;span style="color:#66d9ef">as&lt;/span> &lt;span style="color:#a6e22e">any&lt;/span>;
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now you have an interceptor but it won’t work because the application doesn’t know it exists. Open the &lt;code>app.modules.ts&lt;/code> and modify it to include the interceptor by: Importing the interceptor class from your class and import the &lt;code>HTTP_INTERCEPTORS&lt;/code> from &lt;code>@angular/common/http&lt;/code> as shown below.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">HttpClientModule&lt;/span>, &lt;span style="color:#a6e22e">HTTP_INTERCEPTORS&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/common/http&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MyHttpInterceptor&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./httpinterceptor&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then add a new &lt;code>HTTP_INTERCEPTOR&lt;/code> &lt;code>provider&lt;/code> to your &lt;code>app.modules.ts&lt;/code>. This will enable your app to recognize and use the new interceptor. This should be added inside the &lt;code>@NgModules&lt;/code> below the &lt;code>imports&lt;/code> as illustrated below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">HTTP_INTERCEPTORS&lt;/span>,
&lt;span style="color:#a6e22e">useClass&lt;/span>: &lt;span style="color:#66d9ef">MyHttpInterceptor&lt;/span>,
&lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
}
],
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Your new &lt;code>app.modules.ts&lt;/code> should &lt;a href="https://github.com/MainaWycliffe/angular-httpinterceptor/blob/master/src/app/app.module.ts">look like this&lt;/a> now:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">BrowserModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/platform-browser&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/core&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">HttpClientModule&lt;/span>, &lt;span style="color:#a6e22e">HTTP_INTERCEPTORS&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@angular/common/http&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">MyHttpInterceptor&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./httpinterceptor&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">AppComponent&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./app.component&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
&lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>],
&lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">BrowserModule&lt;/span>, &lt;span style="color:#a6e22e">HttpClientModule&lt;/span>],
&lt;span style="color:#a6e22e">providers&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [
{
&lt;span style="color:#a6e22e">provide&lt;/span>: &lt;span style="color:#66d9ef">HTTP_INTERCEPTORS&lt;/span>,
&lt;span style="color:#a6e22e">useClass&lt;/span>: &lt;span style="color:#66d9ef">MyHttpInterceptor&lt;/span>,
&lt;span style="color:#a6e22e">multi&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
}
],
&lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the results will look as follows for a working interceptor:&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/method1.png" alt="Method 1 : No Error, Success Message is logged in console">&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/method2.png" alt="When Method 2: It results to an error which is logged inside console">&lt;/p>
&lt;p>Any new http request you make from this project will all pass through the interceptor. You can find the whole source code of this project on Github &lt;a href="https://github.com/MainaWycliffe/angular-httpinterceptor">here&lt;/a>. Thank you.&lt;/p></description></item><item><title>Image Sliders and Carousels for Angular 4</title><link>https://codinglatte.com/posts/angular/angular-module-image-slider-carousel/</link><pubDate>Sun, 05 Nov 2017 23:39:28 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-module-image-slider-carousel/</guid><description>&lt;p>Web developers require from time to time to create different types of images sliders and carousel in their apps. Most developers coming from jQuery and other plugin tend to want to use the tools they are already familiar with – like that amazing jQuery plugin you used before. But doing that would make your app bloated if you imported an extra library that you will be under using. It would be much better if you used an Angular carousel module to achieve this. So, today I have decided to do some research and test out 5 carousel modules for Angular (Not AngularJS) and above.&lt;/p>
&lt;h2 id="1-bootstrap-carousel">1. Bootstrap Carousel&lt;/h2>
&lt;p>&lt;a href="https://getbootstrap.com/docs/4.0/getting-started/introduction/">Bootstrap&lt;/a> is one of the most popular frontend frameworks out there. It has component for almost everything and its well designed and easy to use. It relies mainly on jQuery to function. The reason am suggesting you use it, it’s because you can replace jQuery with Angular module so that bootstrap works without jQuery. This module is known as &lt;a href="https://ng-bootstrap.github.io/#/components/carousel/examples">&lt;code>ng-boostrap&lt;/code>&lt;/a>. You can learn how to setup Bootstrap 4 in your Angular 4 app &lt;a href="https://codinglatte.com/tech/developers/using-angular-4-bootstrap-4/">here&lt;/a>. You can use the Bootstrap carousel component to make a nice image slider for your app with ng-bootstrap using the following &lt;a href="https://ng-bootstrap.github.io/#/components/carousel/examples">instructions&lt;/a>. Ng-bootstrap has some nice tutorials on how to use it with bootstrap &lt;a href="https://ng-bootstrap.github.io/#/getting-started">here&lt;/a>.&lt;/p>
&lt;h2 id="2-angular4-carousel">2. Angular4 Carousel&lt;/h2>
&lt;p>&lt;a href="https://codinglatte.com/wp-content/uploads/2017/11/1.png">Angular Module for Image Slider and Carousel&lt;/a>&lt;/p>
&lt;p>This is a simple image carousel for an Angular app. It doesn’t do more than that or less, it does simply what it says it does – be an image slide. If you are already too deep in your application, this can be a simple, quick solution for you. Learn more about this image carousel &lt;a href="https://www.npmjs.com/package/angular4-carousel">here&lt;/a> and demo &lt;a href="http://angular4-carousel.bitballoon.com/">here&lt;/a>.&lt;/p>
&lt;h2 id="3-ngx-carousel">3. ngx-carousel&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/ngx-carousel.png" alt="Angular Module for Image Slider and Carousel">&lt;/p>
&lt;p>This is a light image slider with multiple options. It offers options such as Banner image slider and tile image slider with and without loop. The only downside with this carousel is that it doesn’t contain any CSS hence you will need to add on your own. If you are not experience this might be a problem. The upside is that it supports gestures and touch controls using &lt;a href="https://hammerjs.github.io/">&lt;code>hammerjs&lt;/code>&lt;/a>. You can view a demo &lt;a href="https://sheikalthaf.github.io/ngx-carousel/">here&lt;/a> and installation for instructions &lt;a href="https://www.npmjs.com/package/ngx-owl-carousel">here&lt;/a>.&lt;/p>
&lt;h2 id="4-ngx-slick">4. ngx-slick&lt;/h2>
&lt;p>Another image slider for Angular that does just what it says. It is simple just like Angular4 carousel. You can view an example &lt;a href="https://embed.plnkr.co/fblxzfPneL66950A4VDM/">here&lt;/a> and checkout the instructions to install it &lt;a href="https://github.com/devmark/ngx-slick">here&lt;/a>. It has the option to have a banner image slider or tile image slider. It’s a decent image slider module to have in your arsenal.&lt;/p>
&lt;h2 id="5-angular2-draggable-carousel">5. Angular2+ Draggable Carousel&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/ezgif.com-resize.gif" alt="Angular Module for Image Slider and Carousel">&lt;/p>
&lt;p>4th on this list is a different kind of image slider. It offers two options: An image slider (tile and banner images) as illustrated in the image above and scroll bars for large single images. This can be suitable for adding large image on a page without taking large chunk of space or as simple image slider. And likes it names says, it also offers the option to drag through the images in the slider. Here is a &lt;a href="https://github.com/bfwg/angular2-drag-scroll">demo&lt;/a> and &lt;a href="https://bfwg.github.io/angular2-drag-scroll/">instruction&lt;/a> on how to use it.&lt;/p></description></item><item><title>How to upgrade your Angular 4 App to Angular 5.0</title><link>https://codinglatte.com/posts/angular/how-to-upgrade-your-angular-4-app-to-angular-5-0/</link><pubDate>Sat, 04 Nov 2017 19:56:11 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/how-to-upgrade-your-angular-4-app-to-angular-5-0/</guid><description>&lt;p>Angular 5 was finally released earlier this week after several delays. It brings a lot of improvements over Angular 4 and new features as discussed in my previous post &lt;a href="https://codinglatte.com/tech/developers/angular/angular-5-hasbeen-released/">here&lt;/a>. On top of Angular 5, Angular CLI v1.5 was also released. So, today I will show you how to upgrade your angular 4 app to Angular 5. Before you can get started with this process, it is important that you backup your app. Also, I would advise you to create an upgrade branch on git instead of working on your master or dev app. This will help you have a working app just in case the upgrade doesn’t work.&lt;/p>
&lt;h1 id="upgrade-angular-cli-to-version-15">Upgrade Angular CLI to version 1.5&lt;/h1>
&lt;p>First and foremost, we need an up to date Angular CLI to take advantages of Angular 5 build optimizer among other features. If you are not using angular CLI, you can skip this step. I am assuming you have installed Angular CLI globally and as such you need to upgrade the global version. If you are using NPM, you need to use the sequence of the commands below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm uninstall -g angular-cli
npm cache clean npm install -g @angular/cli@latest
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first command will uninstall Angular CLI globally, while the second command will clear the cache. The last command will install the latest version of Angular CLI. For those using &lt;a href="https://codinglatte.com/tech/developers/angular/setup-angular-touse-yarn-package-manager/">Yarn Packager Manager&lt;/a>, follow the following command&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn global upgrade @angular/cli@latest
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To confirm that your Angular CLI has been updated to the latest version (v1.5), use the following command.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng -v
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will show you the current version of Angular CLI as indicated in the image below.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/ngv.png" alt="How to upgrade your Angular 4 App to Angular 5.0">&lt;/p>
&lt;h1 id="upgrade-your-angular-4-app">Upgrade Your Angular 4 App&lt;/h1>
&lt;h2 id="preliminary-steps">Preliminary Steps&lt;/h2>
&lt;p>First, run through the checklist below and modify your app accordingly. Do this to avoid breaking your app after you upgrade (Please note, If you started with Angular 4 you might not have to change anything here):&lt;/p>
&lt;ol>
&lt;li>Stop using DefaultIterableDiffer, KeyValueDiffers#factories, or IterableDiffers#factories&lt;/li>
&lt;li>Rename your template tags to ng-template&lt;/li>
&lt;li>Replace OpaqueTokens with InjectionTokens.&lt;/li>
&lt;li>If you call DifferFactory.create(&amp;hellip;) remove the ChangeDetectorRef argument.&lt;/li>
&lt;li>Stop passing any arguments to the constructor for ErrorHandler&lt;/li>
&lt;li>If you use ngProbeToken, make sure you import it from @angular/core instead of @angular/platform-browser&lt;/li>
&lt;li>If you use TrackByFn, instead use TrackByFunction&lt;/li>
&lt;li>If you import any animations services or tools from @angular/core, you should import them from @angular/animations&lt;/li>
&lt;li>Replace ngOutletContext with ngTemplateOutletContext.&lt;/li>
&lt;li>Replace CollectionChangeRecord with IterableChangeRecord&lt;/li>
&lt;li>Anywhere you use Renderer, now use Renderer2&lt;/li>
&lt;li>Switch from HttpModule and the Http service to HttpClientModule and the HttpClient service. HttpClient simplifies the default ergonomics (You don&amp;rsquo;t need to map to JSON anymore) and now supports typed return values and interceptors. Read more on &lt;a href="https://angular.io/guide/http">io&lt;/a>&lt;/li>
&lt;li>If you use DOCUMENT from @angular/platform-browser, you should start to import this from @angular/common&lt;/li>
&lt;li>If you use preserveQueryParams, instead use queryParamsHandling&lt;/li>
&lt;li>If you rely on the date, currency, decimal, or percent pipes, in 5 you will see minor changes to the format. For apps using locales other than en-us you will need to import it and optionally locale_extended_fr from @angular/common/i18n_data/locale_fr and registerLocaleData(local).&lt;/li>
&lt;li>Do not rely on gendir, instead look at using skipTemplateCodeGen. Read more&lt;/li>
&lt;li>If you created a custom form control with min and max input properties, you will need to adapt to the new behavior by renaming them or using the native validators.&lt;/li>
&lt;/ol>
&lt;h2 id="how-to-update">How to Update&lt;/h2>
&lt;p>Now, I believe you are ready to upgrade your app to Angular 5. If you are using NPM, use the commands below to do the upgrade:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install @angular/animations@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/common@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/compiler@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/compiler-cli@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/core@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/forms@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/http@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/platform-browser@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/platform-browser-dynamic@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/platform-server@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/router@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> typescript@2.4.2 rxjs@&lt;span style="color:#e6db74">&amp;#39;^5.5.2&amp;#39;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install typescript@2.4.2 --save-exact
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And if you are using Yarn Package Manager, use the command below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add @angular/animations@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/common@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/compiler@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/compiler-cli@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/core@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/forms@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/http@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/platform-browser@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/platform-browser-dynamic@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/platform-server@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> @angular/router@&lt;span style="color:#e6db74">&amp;#39;^5.0.0&amp;#39;&lt;/span> typescript@2.4.2 rxjs@&lt;span style="color:#e6db74">&amp;#39;^5.5.2&amp;#39;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>And there you have it, your Angular 4 app has been successfully upgraded. You can run your application to make sure everything is working fine If you have any question, you can contact me through social media on &lt;a href="https://twitter.com/mwycliffe_dev">Twitter&lt;/a> or on &lt;a href="https://www.linkedin.com/in/mainawycliffe/">LinkedIn&lt;/a>. Thank you.&lt;/p></description></item><item><title>The Most Disliked Programming Languages</title><link>https://codinglatte.com/posts/programming/themost-disliked-programming-languages/</link><pubDate>Fri, 03 Nov 2017 22:51:04 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/programming/themost-disliked-programming-languages/</guid><description>&lt;p>Stackoverflow has published a study on their &lt;a href="https://stackoverflow.blog/2017/10/31/disliked-programming-languages/">blog&lt;/a> for the most disliked programming languages. To come up with this list, stackoverflow studied developer inputs for stackoverflow &lt;a href="https://stackoverflow.com/jobs?utm_source=so-owned&amp;amp;utm_medium=blog&amp;amp;utm_campaign=gen-blog&amp;amp;utm_content=blog-link&amp;amp;utm_term=polarizing-languages">jobs&lt;/a>.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/DevStory-753x675.png" alt="The Most Disliked Programming Languages">&lt;/p>
&lt;p>When developers are creating their stories to showcase their achievements and skills, stackoverflow provides an option for developers to choose which languages they would like to work with and which they would not. This provides an accurate metric for both disliked and liked languages by developers on the stackoverflow site.&lt;/p>
&lt;blockquote>
&lt;p>This offers us an opportunity to examine the opinions of hundreds of thousands of developers. There are many ways to measure the popularity of a language; for example, we’ve often used stackoverflow visits or question views to measure such trends. But this dataset is a rare way to find out what technologies people tend to dislike, when given the opportunity to say so on their CV.&lt;/p>
&lt;/blockquote>
&lt;h2 id="method-of-measure">Method of Measure&lt;/h2>
&lt;p>To measure which is the most disliked languages, stackoverflow came up with the following formula: They compared the fraction of time a disliked tag appeared in someone else liked or disliked tags. If it’s 50%, it means equal people liked and disliked it while it’s 1% means 99 liked the language as compared to just 1 who disliked it.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/languages-1-900x675.png" alt="The Most Disliked Programming Languages">&lt;/p>
&lt;h2 id="most-disliked-programming-languages">Most Disliked Programming Languages&lt;/h2>
&lt;p>Based on the above methodology, here are the 10 most disliked programming languages:&lt;/p>
&lt;ol>
&lt;li>Perl – 19%&lt;/li>
&lt;li>Delphi – 19%&lt;/li>
&lt;li>VBA – 17%&lt;/li>
&lt;li>PHP – 9%&lt;/li>
&lt;li>Objective-C – 9%&lt;/li>
&lt;li>Coffeescript – 8%&lt;/li>
&lt;li>Ruby – 7%&lt;/li>
&lt;li>C# (C-Sharp) – 5%&lt;/li>
&lt;li>Java – 4%&lt;/li>
&lt;li>C++ - 3%&lt;/li>
&lt;/ol>
&lt;h2 id="least-disliked-programming-languages">Least Disliked Programming Languages&lt;/h2>
&lt;p>Also, here is a list of the least disliked languages from the study.&lt;/p>
&lt;ol>
&lt;li>R&lt;/li>
&lt;li>Kotlin&lt;/li>
&lt;li>Typescript&lt;/li>
&lt;li>Rust&lt;/li>
&lt;li>Bash&lt;/li>
&lt;li>Clojure&lt;/li>
&lt;li>Swift&lt;/li>
&lt;li>Python&lt;/li>
&lt;li>JavaScript&lt;/li>
&lt;li>Go&lt;/li>
&lt;/ol>
&lt;p>All least disliked languages had a percentage of approximately less than 2. On top of that, the least disliked languages are also the fastest growing languages. Kotlin has been gaining popularity since Google adopted it as first language for android. It got android developer attention in the Google I/O event earlier this year. Typescript on the other hand is seen as the future of JavaScript and been widely accepted by developers especially in &lt;a href="https://codinglatte.com/tech/developers/angular/angular-5-hasbeen-released/">Angular JavaScript Framework&lt;/a>.&lt;/p></description></item><item><title>Angular 5 has been released</title><link>https://codinglatte.com/posts/angular/angular-5-hasbeen-released/</link><pubDate>Wed, 01 Nov 2017 23:39:23 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-5-hasbeen-released/</guid><description>&lt;p>Angular 5 was finally released after several delays yesterday, November 1, 2017. It was also accompanied by Angular CLI 1.5. This is a major release and in line with Angular team promise of major releases twice a year. It focusses on making Angular application smaller, faster and easier to use.&lt;/p>
&lt;h1 id="how-to-upgrade">How to upgrade&lt;/h1>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/Capture2.png" alt="Angular Update Guide - 2.0 -> 5.0 for Basic Apps">&lt;/p>
&lt;p>The Angular Team has built a tool to guide you through the upgrade process from any version of Angular. The tool can be found &lt;a href="https://angular-update-guide.firebaseapp.com/">here&lt;/a>.&lt;/p>
&lt;h1 id="whats-new">What’s new?&lt;/h1>
&lt;h2 id="httpclient">HTTPClient&lt;/h2>
&lt;p>Angular introduced HTTPClient in Angular 4.3 found inside &lt;code>@angular/common&lt;/code>. The team has marked the original &lt;code>@angular/http&lt;/code> for deprecating in Angular 5. If you will upgrade to Angular 5, you will need to update your http to the new one found in &lt;code>@angular/common&lt;/code> which is better than the deprecated one.&lt;/p>
&lt;h2 id="build-optimizer">Build Optimizer&lt;/h2>
&lt;p>This will be turned on by default in Angular 5. Build optimizer is included in Angular CLI for making your application bundle much smaller by understanding your application. This is done by removing unnecessary parts of your application while also retaining all the necessary parts. It also removes Angular decorators from your application’s runtime code. Decorators are used by the compiler, and aren’t needed at runtime and can be removed. Each of these jobs decrease the size of your JavaScript bundles, and increase the boot speed of your application for your users.&lt;/p>
&lt;h2 id="compiler-improvements">Compiler Improvements&lt;/h2>
&lt;p>The Angular team has made improvements to Angular compiler to support incremental compilation. This in turn increases the speed of rebuilds especially for productions and build using AOT flag. Also, Angular compiler operates as typescript transform, increasing the rebuilds speeds when using TypeScript 2.3.  You can take advantage of this by using the AOT flag.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng serve -AOT
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>“When performing an incremental AOT build of &lt;a href="https://angular.io">https://angular.io&lt;/a>, the new compiler pipeline saves 95% of the build time (from more than 40 seconds to less than 2 seconds on our development machines).”&lt;/p>
&lt;/blockquote>
&lt;p>Large projects with over 1000 components might not benefit from incremental compilation, it’s a known issue. This will be turned on by default to everyone on future versions of Angular CLI as soon as its evident that everyone can benefit from the increased speeds. On top of all that, you can now choose whether you want whitespaces in your application can be preserved on not. The norm has been to preserve them faithfully. You can specify this as part of each component’s decorator, where it currently defaults to true.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">@Component&lt;/span>({
  &lt;span style="color:#a6e22e">templateUrl&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#39;about.component.html&amp;#39;&lt;/span>,
  &lt;span style="color:#a6e22e">preserveWhitespaces&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
}
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AboutComponent&lt;/span> {}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="improved-decorator-support">Improved Decorator Support&lt;/h2>
&lt;p>Angular now support expression lowering in decorators for lambdas and the value of useValue, useFactory and data in an object literal. This allows you to use values that can only be calculated at runtime in decorators for expressions that are lowered. You can now use a lambda instead of a named function, meaning you can execute code without affecting your d.ts or your public API.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/11/Capture.png" alt="Angular 5 has been released">&lt;/p>
&lt;h2 id="internationalized-number-date-and-currency-pipes">Internationalized Number, Date, and Currency Pipes&lt;/h2>
&lt;p>Angular will stop relying on the browser API to provide international numbers, dates and currency formatting. This forced developers to rely on polyfill to ensure consistency across all browsers. Instead, the Angular Team has created its own implementation relying on &lt;a href="http://cldr.unicode.org/">CLDR&lt;/a> to provide extensive locale support and configurations for any locales you want to support. You can learn more about this &lt;a href="https://docs.google.com/spreadsheets/d/12iygt-_cakNP1VO7MV9g4lq9NsxVWG4tSfc98HpHb0k/edit#gid=0">here&lt;/a>.&lt;/p>
&lt;h2 id="angular-universal-state-transfer-api-and-dom-support">Angular Universal State Transfer API and DOM Support&lt;/h2>
&lt;p>Angular universal is a project focused on helping developers perform server-side rendering (SSR). This means you can use your server to render your application and then bootstrap on top of the generated code. This is good news to developers as you can now add support for scrappers and crawlers that don’t support JavaScript. It can also boost your application speed leveraging your server capabilities and use of a cache to avoid re-rendering of static pages on request. On top of that, Angular team has added ServerTransferStateModule and BrowserTransferStateModule.&lt;/p>
&lt;p>This module will allow you to generate information as part of your rendering with platform-server, and then transfer it to the client side so that this information does not need to be regenerated. This is useful for cases such as when your application fetches data over HTTP. By transferring state from the server, this means developers do not need to make a second HTTP request once the application makes it to the client.&lt;/p>
&lt;p>The documentation for this will come soon. Also, the Angular Universal Team has added &lt;a href="https://github.com/fgnass/domino">domino&lt;/a> to platform server. Domino adds more DOM manipulations out of the box in the server side and has improved Angular support for 3rd party JS and components that are not server side aware.&lt;/p>
&lt;h2 id="other-changes">Other Changes&lt;/h2>
&lt;ol>
&lt;li>Replaced the ReflectiveInjector with StaticInjector&lt;/li>
&lt;li>Zone speed improvements&lt;/li>
&lt;li>Added support for multiple names for your components / directives.&lt;/li>
&lt;li>You can now run validation and value updates on &lt;code>blur&lt;/code> or on &lt;code>submit&lt;/code>, instead of on every input event.&lt;/li>
&lt;li>Angular is now compatible with RxJS 5.5 – The latest version&lt;/li>
&lt;li>Added new lifecycle events to the router, allowing developers to track the cycle of the router from the start of running guards through to completion of activation.&lt;/li>
&lt;/ol>
&lt;p>For more information, visit the official blog announcement &lt;a href="https://blog.angular.io/version-5-0-0-of-angular-now-available-37e414935ced">here&lt;/a>.&lt;/p></description></item><item><title>How to setup Yarn Package Manager for Angular (Updated)</title><link>https://codinglatte.com/posts/angular/setup-angular-touse-yarn-package-manager/</link><pubDate>Tue, 31 Oct 2017 07:46:10 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/setup-angular-touse-yarn-package-manager/</guid><description>&lt;p>Last week, I briefly touched on Yarn Package Manager in my post about &lt;a href="https://codinglatte.com/tech/angular-musthave-tools/">5 must have tools for angular developer&lt;/a>. Yarn Package Manager – simply referred to as Yarn – was developed by Facebook as a replacement for Node Package Manager (NPM). Yarn has been widely adopted by Facebook for its core Projects: main Facebook app and website, Instagram, Oculus, and WhatsApp.&lt;/p>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/10/yarn-lock-file.png" alt="How to setup Yarn Package Manager and Angular CLI">&lt;/p>
&lt;p>To put it simply, Yarn is a better version of NPM. It offers speed, security and reliability over NPM. I have been using Yarn for a couple months now and I will not switch back to NPM anytime soon. Yarn has the same packages as NPM, you don’t have to worry about lack of packages. To install any package from NPM, just copy the name of the package and install it as follows (replace package-name with the name of the package):&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add package-name
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="is-it-compatible-with-angular-cli">Is it Compatible with Angular CLI?&lt;/h2>
&lt;p>Angular CLI is another tool that helps you manage your angular project. It helps you create, build, generate components, services and others for your project. By default, it uses NPM for package management but it also supports Yarn.&lt;/p>
&lt;h3 id="how-to-install-yarn-package-manager">How to Install Yarn Package Manager&lt;/h3>
&lt;p>To install yarn package manager, you need to head to the following &lt;a href="https://yarnpkg.com/en/docs/install">webpage&lt;/a>. Download and follow the instruction specific to your Operating System.&lt;/p>
&lt;p>Yarn is available for Windows, Linux and MacOS. Once you have successfully installed Yarn. (You can test by running the command below, it will give you the yarn version number)&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn -v
&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can now set Angular CLI to use yarn by running the command below. This will change the default package manager from NPM to yarn globally. For Angular 5 and below, use the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng set --global packageManager&lt;span style="color:#f92672">=&lt;/span>yarn
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: For Angular 6 and above, use the following command:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng config -g cli.packageManager yarn
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, any new project you start with Angular CLI will be using Yarn instead of NPM. If you have an existing project and would like to switch to yarn, you will need to install all NPM packages into yarn lock file. Just run the command below, it won’t interfere with your NPM packages as it depends on them.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn install
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/10/21387025_521873481481873_7498979389481156608_n.jpg" alt="How to setup Yarn Package Manager for Angular">&lt;/p>
&lt;h2 id="installing-packages-using-yarn">Installing Packages Using yarn&lt;/h2>
&lt;p>To install packages using Yarn is rather simple. Find or take any NPM package name and add it using yarn add command as indicated below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add package-name-1 package-name-2 …
&lt;/code>&lt;/pre>&lt;/div>&lt;p>i.e.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add @ng-bootstrap/ng-bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="other-commands">Other Commands&lt;/h2>
&lt;h5 id="starting-a-new-project">Starting a new project&lt;/h5>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn init
&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="adding-a-dependency">Adding a dependency&lt;/h5>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span>
yarn add &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span>@&lt;span style="color:#f92672">[&lt;/span>version&lt;span style="color:#f92672">]&lt;/span>
yarn add &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span>@&lt;span style="color:#f92672">[&lt;/span>tag&lt;span style="color:#f92672">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="adding-a-dependency-to-different-categories-of-dependencies">Adding a dependency to different categories of dependencies&lt;/h5>
&lt;blockquote>
&lt;p>Add to devDependencies, peerDependencies, and optionalDependencies respectively:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span> --dev
yarn add &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span> --peer
yarn add &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span> --optional
&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="upgrading-a-dependency">Upgrading a dependency&lt;/h5>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn upgrade &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span>
yarn upgrade &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span>@&lt;span style="color:#f92672">[&lt;/span>version&lt;span style="color:#f92672">]&lt;/span>
yarn upgrade &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span>@&lt;span style="color:#f92672">[&lt;/span>tag&lt;span style="color:#f92672">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="removing-a-dependency">Removing a dependency&lt;/h5>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn remove &lt;span style="color:#f92672">[&lt;/span>package&lt;span style="color:#f92672">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="installing-all-the-dependencies-of-project">Installing all the dependencies of project&lt;/h5>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn or yarn install
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="revert-to-npm">Revert to NPM&lt;/h2>
&lt;p>In case you are unimpressed with yarn or you find the change of command hard to take, you can revert to NPM with the command below. For Angular 5 and below:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng set --global packageManager&lt;span style="color:#f92672">=&lt;/span>npm
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>NB: For Angular 6 and above:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">ng config -g cli.packageManager npm
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Terms of Use</title><link>https://codinglatte.com/policies/terms-of-use/</link><pubDate>Mon, 30 Oct 2017 11:34:03 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/policies/terms-of-use/</guid><description>&lt;h2 id="terms">Terms&lt;/h2>
&lt;p>By accessing the website at &lt;a href="codinglatte.com">https://codinglatte.com&lt;/a>, you are agreeing to be bound by these terms of service, all applicable laws and regulations, and agree that you are responsible for compliance with any applicable local laws. If you do not agree with any of these terms, you are prohibited from using or accessing this site. The materials contained in this website are protected by applicable copyright and trademark law.&lt;/p>
&lt;h2 id="use-license">Use License&lt;/h2>
&lt;ol>
&lt;li>Permission is granted to temporarily download one copy of the materials (information or software) on Coding Latte&amp;rsquo;s website for personal, non-commercial transitory viewing only. This is the grant of a license, not a transfer of title, and under this license you may not:
&lt;ol>
&lt;li>modify or copy the materials;&lt;/li>
&lt;li>use the materials for any commercial purpose, or for any public display (commercial or non-commercial);&lt;/li>
&lt;li>attempt to decompile or reverse engineer any software contained on Coding Latte&amp;rsquo;s website;&lt;/li>
&lt;li>remove any copyright or other proprietary notations from the materials; or&lt;/li>
&lt;li>transfer the materials to another person or &amp;ldquo;mirror&amp;rdquo; the materials on any other server.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>This license shall automatically terminate if you violate any of these restrictions and may be terminated by Coding Latte at any time. Upon terminating your viewing of these materials or upon the termination of this license, you must destroy any downloaded materials in your possession whether in electronic or printed format.&lt;/li>
&lt;/ol>
&lt;h2 id="disclaimer">Disclaimer&lt;/h2>
&lt;ol>
&lt;li>The materials on Coding Latte&amp;rsquo;s website are provided on an &amp;lsquo;as is&amp;rsquo; basis. Coding Latte makes no warranties, expressed or implied, and hereby disclaims and negates all other warranties including, without limitation, implied warranties or conditions of merchantability, fitness for a particular purpose, or non-infringement of intellectual property or other violation of rights.&lt;/li>
&lt;li>Further, Coding Latte does not warrant or make any representations concerning the accuracy, likely results, or reliability of the use of the materials on its website or otherwise relating to such materials or on any sites linked to this site.&lt;/li>
&lt;/ol>
&lt;h2 id="limitations">Limitations&lt;/h2>
&lt;p>In no event shall Coding Latte or its suppliers be liable for any damages (including, without limitation, damages for loss of data or profit, or due to business interruption) arising out of the use or inability to use the materials on Coding Latte&amp;rsquo;s website, even if Coding Latte or a Coding Latte authorized representative has been notified orally or in writing of the possibility of such damage. Because some jurisdictions do not allow limitations on implied warranties, or limitations of liability for consequential or incidental damages, these limitations may not apply to you.&lt;/p>
&lt;h2 id="accuracy-of-materials">Accuracy of materials&lt;/h2>
&lt;p>The materials appearing on Coding Latte website could include technical, typographical, or photographic errors. Coding Latte does not warrant that any of the materials on its website are accurate, complete or current. Coding Latte may make changes to the materials contained on its website at any time without notice. However Coding Latte does not make any commitment to update the materials.&lt;/p>
&lt;h2 id="links">Links&lt;/h2>
&lt;p>Coding Latte has not reviewed all of the sites linked to its website and is not responsible for the contents of any such linked site. The inclusion of any link does not imply endorsement by Coding Latte of the site. Use of any such linked website is at the user&amp;rsquo;s own risk.&lt;/p>
&lt;h2 id="modifications">Modifications&lt;/h2>
&lt;p>Coding Latte may revise these terms of service for its website at any time without notice. By using this website you are agreeing to be bound by the then current version of these terms of service.&lt;/p>
&lt;h2 id="governing-law">Governing Law&lt;/h2>
&lt;p>These terms and conditions are governed by and construed in accordance with the laws of Kenya and you irrevocably submit to the exclusive jurisdiction of the courts in that State or location.&lt;/p></description></item><item><title>Privacy Policy</title><link>https://codinglatte.com/policies/privacy-policy/</link><pubDate>Mon, 30 Oct 2017 10:58:23 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/policies/privacy-policy/</guid><description>&lt;p>&lt;strong>Last Updated on 2017-10-30&lt;/strong>&lt;/p>
&lt;p>This privacy policy has been compiled to better serve those who are concerned with how their &amp;lsquo;Personally Identifiable Information&amp;rsquo; (PII) is being used online. PII, as described in US privacy law and information security, is information that can be used on its own or with other information to identify, contact, or locate a single person, or to identify an individual in context. Please read our privacy policy carefully to get a clear understanding of how we collect, use, protect or otherwise handle your Personally Identifiable Information in accordance with our website.&lt;/p>
&lt;h3 id="what-personal-information-do-we-collect-from-the-people-that-visit-our-blog-website-or-app">What personal information do we collect from the people that visit our blog, website or app?&lt;/h3>
&lt;p>When ordering or registering on our site, as appropriate, you may be asked to enter your email address or other details to help you with your experience.&lt;/p>
&lt;h3 id="when-do-we-collect-information">When do we collect information?&lt;/h3>
&lt;p>We collect information from you when you subscribe to a newsletter or enter information on our site.&lt;/p>
&lt;h3 id="how-do-we-use-your-information">How do we use your information?&lt;/h3>
&lt;p>We may use the information we collect from you when you register, make a purchase, sign up for our newsletter, respond to a survey or marketing communication, surf the website, or use certain other site features in the following ways:&lt;/p>
&lt;ul>
&lt;li>To personalize your experience and to allow us to deliver the type of content and product offerings in which you are most interested.&lt;/li>
&lt;li>To administer a contest, promotion, survey or other site feature.&lt;/li>
&lt;li>To send periodic emails regarding your order or other products and services.&lt;/li>
&lt;/ul>
&lt;h3 id="do-we-use-cookies">Do we use &amp;lsquo;cookies&amp;rsquo;?&lt;/h3>
&lt;p>Yes. Cookies are small files that a site or its service provider transfers to your computer&amp;rsquo;s hard drive through your Web browser (if you allow) that enables the site&amp;rsquo;s or service provider&amp;rsquo;s systems to recognize your browser and capture and remember certain information. For instance, we use cookies to help us remember and process the items in your shopping cart. They are also used to help us understand your preferences based on previous or current site activity, which enables us to provide you with improved services. We also use cookies to help us compile aggregate data about site traffic and site interaction so that we can offer better site experiences and tools in the future.&lt;/p>
&lt;p>&lt;strong>We use cookies to:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Keep track of advertisements.&lt;/li>
&lt;li>Compile aggregate data about site traffic and site interactions in order to offer better site experiences and tools in the future. We may also use trusted third-party services that track this information on our behalf.&lt;/li>
&lt;/ul>
&lt;p>You can choose to have your computer warn you each time a cookie is being sent, or you can choose to turn off all cookies. You do this through your browser settings. Since browser is a little different, look at your browser&amp;rsquo;s Help Menu to learn the correct way to modify your cookies.&lt;/p>
&lt;p>If you turn cookies off, Some of the features that make your site experience more efficient may not function properly.It won&amp;rsquo;t affect the user&amp;rsquo;s experience that make your site experience more efficient and may not function properly.&lt;/p>
&lt;h3 id="third-party-disclosure">Third-party disclosure&lt;/h3>
&lt;h4 id="do-we-disclose-the-information-we-collect-to-third-parties">Do we disclose the information we collect to Third-Parties?&lt;/h4>
&lt;p>We sell,trade, or otherwise transfer to outside parties cookie number, ip address device serial #, unique device identifier, photo, video or audio file of child Personally Identifiable Information.&lt;/p>
&lt;h4 id="third-party-links">Third-party links&lt;/h4>
&lt;p>Occasionally, at our discretion, we may include or offer third-party products or services on our website. These third-party sites have separate and independent privacy policies. We therefore have no responsibility or liability for the content and activities of these linked sites. Nonetheless, we seek to protect the integrity of our site and welcome any feedback about these sites.&lt;/p>
&lt;h4 id="google">Google&lt;/h4>
&lt;p>Google&amp;rsquo;s advertising requirements can be summed up by Google&amp;rsquo;s Advertising Principles. They are put in place to provide a positive experience for users. &lt;a href="https://support.google.com/adwordspolicy/answer/1316548?hl=en">https://support.google.com/adwordspolicy/answer/1316548?hl=en&lt;/a>&lt;/p>
&lt;h4 id="we-use-google-adsense-advertising-on-our-website">We use Google AdSense Advertising on our website.&lt;/h4>
&lt;p>Google, as a third-party vendor, uses cookies to serve ads on our site. Google&amp;rsquo;s use of the DART cookie enables it to serve ads to our users based on previous visits to our site and other sites on the Internet. Users may opt-out of the use of the DART cookie by visiting the Google Ad and Content Network privacy policy.&lt;/p>
&lt;h4 id="we-have-implemented-the-following">We have implemented the following:&lt;/h4>
&lt;ul>
&lt;li>Remarketing with Google AdSense&lt;/li>
&lt;li>Google Display Network Impression Reporting&lt;/li>
&lt;li>Demographics and Interests Reporting&lt;/li>
&lt;li>DoubleClick Platform Integration&lt;/li>
&lt;/ul>
&lt;p>We, along with third-party vendors such as Google use first-party cookies (such as the Google Analytics cookies) and third-party cookies (such as the DoubleClick cookie) or other third-party identifiers together to compile data regarding user interactions with ad impressions and other ad service functions as they relate to our website.&lt;/p>
&lt;h4 id="opting-out">Opting out:&lt;/h4>
&lt;p>Users can set preferences for how Google advertises to you using the Google Ad Settings page. Alternatively, you can opt out by visiting the Network Advertising Initiative Opt Out page or by using the Google Analytics Opt Out Browser add on.&lt;/p>
&lt;h3 id="contacting-us">Contacting Us&lt;/h3>
&lt;p>If there are any questions regarding this privacy policy, you may contact us using the information below.&lt;/p>
&lt;p>&lt;a href="mailto:info@codinglatte.com">info@codinglatte.com&lt;/a>&lt;/p></description></item><item><title>How to use Angular 4 with Bootstrap 4</title><link>https://codinglatte.com/posts/angular/using-angular-4-bootstrap-4/</link><pubDate>Wed, 25 Oct 2017 10:48:37 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/using-angular-4-bootstrap-4/</guid><description>&lt;p>Angular and Bootstrap 4 are arguably the best frameworks out there, though will different purposes. Angular was developed by Google as a JavaScript framework while Bootstrap was developed by twitter as a CSS framework. The major huddle to using both is that Bootstrap uses jQuery. While you can use both jQuery and Angular in the same Application, it&amp;rsquo;s redundant. This is because jQuery has the lots of functionality overlapping with angular and you would end up with a bloated application.&lt;/p>
&lt;h2 id="why-use-bootstrap">Why use Bootstrap?&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/10/bootstrap-stack-300x252.png" alt="How to use Angular 4 with Bootstrap 4">&lt;/p>
&lt;p>Bootstrap 4 is the most complete CSS framework out there. It has 10s of component and utilities for you to use to make your site visually appealing. If you are looking for a great example that relies on Bootstrap, look no further than twitter.&lt;/p>
&lt;p>On top of the components and utilities, Bootstrap has also a theming capability. Themes give you the ability to change the look of your site without doing much coding. Bootstrap will save you hours or even days of creating CSS files for your website by giving you 90 - 95% of all the CSS code you need.&lt;/p>
&lt;h2 id="are-there-alternatives-to-bootstrap-4">Are there alternatives to Bootstrap 4?&lt;/h2>
&lt;p>Of course, especially when it comes to Angular. One good alternative is Google own &lt;strong>Material Design&lt;/strong> &lt;a href="https://material.angular.io/">ui-framework&lt;/a>. Material Design is a design language developed by Google in 2014. If you are looking for an example of material design in action look at almost all Google website like Google Drive. Its high responsive and looks great on smartphones.&lt;/p>
&lt;p>The advantage of this framework is that it easy to integrate with Angular but with a somewhat steep learning curve.&lt;/p>
&lt;h2 id="how-to-use-bootstrap-and-angular">How to use Bootstrap and Angular&lt;/h2>
&lt;p>First, I am making the assumptions that you know how to use Bootstrap. That said, if you want some nice Bootstrap tutorials check no further than the official Bootstrap &lt;a href="https://getbootstrap.com/docs/4.0/getting-started/introduction/">documentation&lt;/a>.&lt;/p>
&lt;p>To use Bootstrap with Angular, we are going to ditch jQuery – it has not place in our application. If you are just interested in using bootstraps classes – buttons, grids, cards – then that’s it for you. You don’t have to add anything on top. But like I said before, Bootstrap is one of the most complete framework and you might want to be able to use everything it has to offer – Modal, Popover, Carrousel etc.&lt;/p>
&lt;p>We are going to replace jQuery with an Angular module known as ng-bootstrap. This offers an alternative to all jQuery functionality in bootstrap with Angular directives. The goal of ng-bootstrap is to completely replace JavaScript implementation for components. Nor should you include other dependencies like jQuery or popper.js. It is not necessary and might interfere with ng-bootstrap code.&lt;/p>
&lt;h2 id="installation-and-first-time-setup">Installation and First Time Setup&lt;/h2>
&lt;p>Install ng-bootstrap using npm&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">npm install --save @ng-bootstrap/ng-bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>or install using yarn&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-bash" data-lang="bash">yarn add @ng-bootstrap/ng-bootstrap
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Once installed you need to import our main module.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">NgbModule&lt;/span> } &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@ng-bootstrap/ng-bootstrap&amp;#39;&lt;/span>;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>The only remaining part is to list the imported module in your root module and any additional application modules that make use of the components in this library. The exact method will be slightly different for the root (top-level) module for which you should end up with the code like (notice &lt;code>NgbModule.forRoot()&lt;/code>):&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-ts" data-lang="ts">&lt;span style="color:#66d9ef">import&lt;/span> {&lt;span style="color:#a6e22e">NgbModule&lt;/span>} &lt;span style="color:#a6e22e">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;@ng-bootstrap/ng-bootstrap&amp;#39;&lt;/span>;
&lt;span style="color:#66d9ef">@NgModule&lt;/span>({
  &lt;span style="color:#a6e22e">declarations&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>, ...],
  &lt;span style="color:#a6e22e">imports&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">NgbModule&lt;/span>.&lt;span style="color:#a6e22e">forRoot&lt;/span>(), ...],
  &lt;span style="color:#a6e22e">bootstrap&lt;/span>&lt;span style="color:#f92672">:&lt;/span> [&lt;span style="color:#a6e22e">AppComponent&lt;/span>]
})
&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AppModule&lt;/span> {
}
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="final-throughts">Final Throughts&lt;/h2>
&lt;p>Now that you have successfully integrated ng-bootstrap with your application. To learn about how to use all the bootstrap components in Angular, follow the guide &lt;a href="https://ng-bootstrap.github.io/#/components/alert/examples">here&lt;/a>. It has all components with examples on different scenarios and I could not have added it into this post without making it too long or too boring.&lt;/p></description></item><item><title>5 Must Have Tools for Angular Developers</title><link>https://codinglatte.com/posts/angular/angular-musthave-tools/</link><pubDate>Sun, 22 Oct 2017 11:25:27 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-musthave-tools/</guid><description>&lt;p>Whether you are a new or an experienced Angular developer there are several useful tools to help make your life much easier. Whether you are using versions 2, 4 or 5 (To be &lt;a href="https://codinglatte.com/tech/developers/angular-5/">released&lt;/a> on 23th of this month) it is important to have the necessary tools. Here is a list of tools for angular you might want to consider:&lt;/p>
&lt;h2 id="angular-cli">Angular CLI&lt;/h2>
&lt;p>Setting up a new angular project can be complicated and rather long process. Luckily, Angular Team saw that and decided to create an official tool to help – Angular &lt;a href="https://github.com/angular/angular-cli">CLI&lt;/a>. Angular CLI helps you create new project, new components, services, directives, guards among others without much work. This is especially useful to newbies trying angular for the first time or still learning their way around. But Angular CLI is more than that. It helps you build your application so that you can run it on a browser or for deployment. During this process, it will remove unnecessary code, remove comments and minify the project to make it lightweight. It will also detect errors on your code and let you correct them. I believe angular cli is a must for any angular developer, whether you are just getting started or experienced. You can learn how to install Angular CLI &lt;a href="https://github.com/angular/angular-cli#installation">here&lt;/a>.&lt;/p>
&lt;h2 id="yarn-package-manager">Yarn Package Manager&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/10/14658612_347000295637068_647258520764284928_n.gif" alt="5 Must Have Tools for Angular">&lt;/p>
&lt;p>&lt;a href="https://yarnpkg.com/en/">&lt;code>Yarn&lt;/code>&lt;/a> is a package manager developed by Facebook for speed and is supported by Angular CLI. Package managers make it easier to manage project dependencies. Instead of manually downloading JavaScript/CSS file for that great plugin you love, you let a package manager handle that for you. Package managers will handle adding, updating and removing project dependencies.&lt;/p>
&lt;p>By default, Angular uses &lt;a href="https://www.npmjs.com/">Node Package Manager&lt;/a>. And while it’s a capable package manager with countless packages under it, it’s not perfect. Yarn Package manager improves on node package manager by increasing its speed. It is up to 5 times faster than Node package manager. It’s also compatible with all node packages. If you are using NPM (Node Package Manager) to manage your angular packages, switching to yarn is easy. First install Yarn Package Manager into your system by following the instructions found &lt;a href="https://yarnpkg.com/en/docs/install">here&lt;/a>.&lt;/p>
&lt;p>Once you have installed it, open command prompt/PowerShell/terminal and navigate to your project folder (Example: &lt;code>cd path/to/project/folder&lt;/code>). Then run the following command:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng set --global packageManager=yarn
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This will set yarn as the global manager for your angular project. Then lastly, initiate yarn on your project by running yarn install command. This will create a yarn.lock file for your project from your package.json. Since yarn uses node module, your already existing dependencies won’t be re-downloaded. To install a new package, run:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">yarn add packagename
&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>(&lt;em>Package Name = any node package will do&lt;/em>) You can switch back to node package manager by running the following command:&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-fallback" data-lang="fallback">ng set --global packageManager=npm
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="augury">Augury&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/10/properties.png" alt="5 Must Have Tools for Angular">&lt;/p>
&lt;p>I have been using &lt;a href="https://augury.angular.io/">Augury&lt;/a> from the beginning to debug angular applications. It is a chrome extension that inspects your application on the web browser. It’s only available for Google chrome and any other browser that accepts chrome extensions (haven’t tried that). In fact, it is the most used Google Chrome Developer Tool extension for debugging and profiling Angular 2+ applications. It’s an opensource effort between &lt;a href="http://rangle.io/">Rangle.io&lt;/a> and Googles Angular team. Augury helps visualize the application through component trees and visual debugging tools. Developers get immediate insight into their application structure, change detection and performance characteristics. It’s important to note, augury only works on projects in development mode and not in production mode. To learn more about Augury visit their official guide &lt;a href="https://augury.angular.io/pages/guides/">here&lt;/a>.&lt;/p>
&lt;h2 id="ngrev">ngRev&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/10/68747470733a2f2f7331382e706f7374696d672e6f72672f6177336b35646d70352f322e706e67.png" alt="5 Must Have Tools for Angular">&lt;/p>
&lt;p>I came across this tool a few weeks ago and I have say am impressed. It’s a graphical user interface tool that reverses engineers your existing angular project and helps you view details about the project.  It allows you to navigate in the structure of your application and observe the relationship between the different modules, providers and directives. ngRev performs static code analysis which means that you don&amp;rsquo;t have to run your application to use it. It’s available for all major operating systems: Windows, Linux and Mac, and it’s very easy to learn how to use it. Learn more about ngRev &lt;a href="https://github.com/mgechev/ngrev">here&lt;/a>.&lt;/p>
&lt;h2 id="visual-studio-code">Visual Studio Code&lt;/h2>
&lt;p>&lt;img src="https://codinglatte.com/wp-content/uploads/2017/10/opengraph-home.png" alt="5 Must Have Tools for Angular">&lt;/p>
&lt;p>When it comes to rich text editors, everyone has his own preferences, from Sublime, Atom, Bracket, Visual Studio Code among others. What makes &lt;a href="https://code.visualstudio.com/">Visual Studio Code (VSCode)&lt;/a> standout is how it handles typescript out of the box. It provides intellisense, error detection and correction and code formatting straight out of the box, no extensions required. This is because both the language and the text editor are both developed by Microsoft.&lt;/p>
&lt;p>Angular 4 primarily uses typescript for development. Typescript is then compiled to JavaScript to run on the web browser. This makes it necessary for one to have a good typescript tool to develop angular apps while eliminating much guess work. Visual Studio code is also completely free. For me, it is one of the best text editors out there, if not the best.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>To conclude, these are just some of the tools that can enhance ones’ development experience. If you have an idea of any tool that I left out, please be sure to comment with your suggestion below this article. If you loved this article be sure to share with your friends and if you didn’t, make your feelings known in the comment box below. Thank you and have a lovely day.&lt;/p></description></item><item><title>What is new in Angular 5</title><link>https://codinglatte.com/posts/angular/angular-5/</link><pubDate>Thu, 19 Oct 2017 17:10:04 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/angular-5/</guid><description>&lt;p>If you are a fan of Angular, there is some good news, Angular 5.0 will be released on 23th October – that’s next week. If you are wondering whether this is too soon, don’t. Google has committed to releasing a new version of Angular every 6 months. Angular 6.0 will be released next year in March/April followed by Angular 7 in September/October.&lt;/p>
&lt;h1 id="what-does-this-mean-for-angular-4-users">What does this mean for Angular 4 Users?&lt;/h1>
&lt;p>In this front, there is good news for existing users. Angular 5 has been built with backward compatibility with previous versions. You can upgrade as soon as the new version has been released without fear of breaking your existing application. This means you can enjoy the advantages of Angular 5 without spending hours upgrading your existing application.&lt;/p>
&lt;blockquote>
&lt;p>“The primary goal of the backwards compatibility promise is to ensure that changes in the core framework and tooling don&amp;rsquo;t break the existing ecosystem of components and applications and don&amp;rsquo;t put undue upgrade/migration burden on Angular application and component authors.”&lt;/p>
&lt;/blockquote>
&lt;p>If you are moving from AngularJS to Angular4 or any version you can &lt;a href="https://codinglatte.com/tech/switching-angularjs-angular-4-0/">read the following post to learn from my own experience&lt;/a>.&lt;/p>
&lt;h1 id="whats-new-in-angular-5">What’s new in Angular 5?&lt;/h1>
&lt;p>First, before we list the features, it’s important to note that the Angular team focusses on gradual improvement on this great framework we all love. That said, this are the most notable features:&lt;/p>
&lt;h2 id="making-progressive-apps-easy-to-build">Making Progressive Apps Easy to Build&lt;/h2>
&lt;p>If you are unaware, progressive web apps are web apps build on CSS, JavaScript and CSS that behave in some ways like native applications. The whole app is cached at the browser making it snappy and highly responsive as compared to a tradition web application. Users can add shortcuts to your web app on their application home making it easier to access. In progressive apps, internet is required only during REST API calls because the app is stored on the user browser. Angular 5 wants to make it even easier to build such apps for all devices.&lt;/p>
&lt;h2 id="a-build-optimizer-to-remove-unnecessary-code">A Build Optimizer to Remove Unnecessary Code&lt;/h2>
&lt;p>Developers are always concerned about the size of their apps. If it’s too big, it takes longer to load which affects user experience negatively. Since Angular is a large framework, at any time there could be hundreds or thousands of lines of code that your app doesn’t need. Even with the best coding practice, a single mistake can import a large chunk of unnecessary code into your application. Angular 5 is looking to improve that by trying to eliminate any unnecessary code from your application. This results into a more compact application which could improve your app performance drastically.&lt;/p>
&lt;h2 id="making-material-design-components-compatible-with-server-side-rendering">Making Material Design components compatible with server-side rendering&lt;/h2>
&lt;p>[caption id=&amp;quot;attachment_708&amp;rdquo; align=&amp;quot;aligncenter&amp;rdquo; width=&amp;quot;1369&amp;rdquo;]&lt;img src="https://codinglatte.com/wp-content/uploads/2017/10/material-design.png" alt="What is new in Angular 5"> Angular Material Design[/caption] For a good number of developers, rendering is done on the browser or the client side. But some devs would like to do the rendering at the backend or server-side. If you have a large application, it would not be prudent to send it to the browser to do the rendering because you don’t know the capabilities of the users’ device. Instead, you could do is render it in bits needed by the users and send them to the user to view. Angular 5 is extending the same to Googles own &lt;a href="https://material.angular.io/">Material Design&lt;/a>.&lt;/p>
&lt;h2 id="performance-improvements-and-bug-fixes">Performance Improvements and Bug Fixes&lt;/h2>
&lt;p>To put it simply, expect Angular 5 to perform way better than Angular 4 or any previous versions. Also, the advantages of a new version is lots of bugs will get fixed in the process.&lt;/p>
&lt;h1 id="can-i-try-angular-today">Can I try Angular today?&lt;/h1>
&lt;p>Yes, you can try Angular 5 right away although it’s still in beta. Also, you can get the documentation of Angular 5 &lt;a href="https://next.angular.io/docs">here&lt;/a>. I would not advise you to use the beta version on a production app. This is because there could be unforeseen bugs which will be cleaned up before its released. That said, testing prerelease is good as you can help improve the framework before it has been released. Also, if your app is still in development, using Angular 5 can help you build a better app. Rather than waiting for it to be officially released before starting using it. Be sure to &lt;a href="https://github.com/angular/angular/blob/master/CONTRIBUTING.md">submit feedback&lt;/a> in case of any bugs or errors.&lt;/p></description></item><item><title>Switching from AngularJS to Angular 4</title><link>https://codinglatte.com/posts/angular/switching-angularjs-angular-4-0/</link><pubDate>Sat, 23 Sep 2017 14:03:11 +0000</pubDate><author>Maina Wycliffe</author><guid>https://codinglatte.com/posts/angular/switching-angularjs-angular-4-0/</guid><description>&lt;p>It’s been almost two weeks since I decided to switch to Angular 4 for my incomplete project from AngularJS. If you have seriously considered making the switch, you know it’s a not easy. The two versions are completely different, controllers and scopes are gone, now it revolves around components and directives.&lt;/p>
&lt;p>I never got to use components in AngularJS, introduced in version 1.5. The idea of using components scared the hell out of me and that was before I learned that I must use TypeScript instead of JavaScript. That almost turned me away but I made the change anyway.&lt;/p>
&lt;p>I have to admit this, TypeScript is a better version of JavaScript. Most importantly, it is not that different from other languages, I like how it tries to instill discipline to JavaScript, but today it not about TypeScript, it’s all about Angular. Here are the things I have learned over the last two weeks.&lt;/p>
&lt;h2 id="getting-started-is-complicated">Getting Started is Complicated&lt;/h2>
&lt;p>This seems obvious but creating a new project in angular is extremely complicated. But the folks who developed Angular knew this and provided a &lt;a href="https://github.com/angular/angular-cli">tool&lt;/a> known as Angular CLI. This tool will help you create new projects, generate components, services, guards, directives among others. Unless you want to make your life exceedingly difficult, please make use of this tool.&lt;/p>
&lt;h2 id="components-in-angular-are-directives-in-angularjs">Components in Angular are Directives in AngularJS&lt;/h2>
&lt;p>Yes, Angular has Directives and Components but if you are coming from AngularJS, components are more like directives. Everything you used to do in AngularJS with directives, you can do with components and more. I would not call myself an expert or claim to know the full extent of what directives can achieve in AngularJS, but with components, you get a feeling they can do more.&lt;/p>
&lt;h2 id="forget-about-ui-router-use-the-angular-router">Forget About UI-Router, use the Angular Router&lt;/h2>
&lt;p>The default Router is amazing to say the least. If you have ever used AngularJS, you know the default router sucks – no offense to the developers. When I made the switch, I spent several hours trying to make UI-Router work unsuccessfully. After that I went through the documentation on angular.io and I was impressed by what the default router can do. It did everything I wanted to do with UI-router and unless you have some specific UI-router feature you want to use, then forget about it.&lt;/p>
&lt;h2 id="i-still-dont-know-what-directives-do">I still don’t know what Directives Do&lt;/h2>
&lt;p>It’s been two weeks, while I have read everything I can on angular directives, I still haven’t figured out a use case for my custom directives. If you know a use case, feel free to inform me in the comments section below.&lt;/p>
&lt;h2 id="forget-about-controllers-and-scope">Forget about Controllers and Scope&lt;/h2>
&lt;p>Both Controllers and Scope were jettisoned as of Angular 2. And for the two weeks I have been using Angular 4, I don’t miss them at all. They made my code messy to say the least. That’s not to say my code won’t be messy with Angular 4 but I like my chances here. Those are few things I learned from my transition since I started two weeks ago. It isn’t much but hopefully it will help someone else decide on whether to make a switch and what to prepare for.&lt;/p>
&lt;p>Thank you.&lt;/p></description></item></channel></rss>