Angular Flex-Layout using MediaObserver

In the last post, we covered setting up and using the Angular Flex-Layout library. In that post, we looked at the responsive aspect of the library using directives and suffixing them with breakpoints where required.

To recap, add the fxLayout directive to a DOM element in the HTML. Then, add the abbreviated breakpoint depending on where the view size should change. For example, or etc…

This post covers how to use the MediaObserver service.

The mediaObserver is installed from the Angular Flex-Layout library as shown below. In the projects terminal window type:

npm install @angular/flexlayout

And then import it to our app.module.ts file.

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { AppComponent } from "./app.component";
import { FlexLayoutModule } from "@angular/flex-layout";
imports: [BrowserModule, FormsModule, FlexLayoutModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
export class AppModule {}
view raw app.module.ts hosted with ❤ by GitHub

The MediaObserver service is an Observable that exposes features to subscribe to mediaQuery changes. It also serves as an isActive() validator method to check if a mediaQuery is currently active.

The MediaObserver service has two API’s.
asObservable(): Observable<MediaChange>
isActive(query: string): boolean

We use Angular Dependency Injection to inject a reference to the MediaObserver as a constructor parameter to use this service.

import { Component, OnDestroy, OnInit } from '@angular/core';
import { MediaChange, MediaObserver } from '@angular/flex-layout';
import { Subscription } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
export class AppComponent implements OnInit, OnDestroy {
title = 'Angular Flex-Layout';
* @param mediaObserver
constructor(public mediaObserver: MediaObserver) {}
private mediaSubscription!: Subscription;
private activeMediaQuery: string = '';
ngOnInit(): void {
const getAlias = (MediaChange: MediaChange[]) => {
return MediaChange[0].mqAlias;
this.mediaSubscription = this.mediaObserver
(x: MediaChange[], y: MediaChange[]) => getAlias(x) === getAlias(y)
.subscribe((change) => {
change.forEach((item) => {
this.activeMediaQuery = item
? `'${item.mqAlias}' = (${item.mediaQuery})`
: '';
if (item.mqAlias === 'md') {
console.log('activeMediaQuery', this.activeMediaQuery);
ngOnDestroy(): void {
loadMobileContent() {
console.log('load mobile content');
// Do something special since the viewport is currently
// using mobile display sizes.

The current example on the Angular Flex-Layout’s wiki page is a little out of date. The media$ observable is now deprecated and replaced with mediaObserver. There appears to be a small bug when reporting the change detection as it duplicates the results, as shown below.

mediaObserver — showing duplicates

To get around this I’ve added a call to the distinctUntilChanged() RXJS operator (lines 29–31). The operator now only emits a single change.

Resize the browser to log the current breakpoint.

console.log of active breakpoint

Here the screen size is small (sm), but also shows us that the screen is less than medium (lt-md), less than large (lt-lg), less than extra-large (lt-xl), and greater than extra-small (gt-xs). In most cases, we really only need to know the actual size, but it’s good to know the others just in case.

So how do we use the MediaObserver?

When designing our applications, we need to know when the screen view size changes so that we can change our UI to make optimal use of the space. This might mean hiding an element or switching from rows to columns, for example:

<div fxLayout="row" fxLayoutGap="10px">
<div fxFlex="1 0 10" *ngIf="mediaObserver.isActive('md')"
id="boxone" style="background: red;">Box One</div>
<div fxFlex="1 0 10" id="boxtwo" style="background: blue;">Box Two</div>

When the browser hits the ‘md’ breakpoint, the DIV (starting on line 2) is removed from the DOM.

To use the mediaObserver in your HTML (as shown above) it needs to be accessed by a get() for it to be visible.

selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
export class AppComponent implements OnInit, OnDestroy {
title = 'Angular Flex-Layout';
get media() {
return this.mediaObserver;
view raw mediaGetter.ts hosted with ❤ by GitHub
Getter for accessing the mediaObserver

Let’s try out another example, you will need to install Angular Material for this to work:

import { Component, OnInit } from '@angular/core';
import { MediaChange, MediaObserver } from '@angular/flex-layout';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
export class AppComponent implements OnInit {
constructor(private mediaObserver: MediaObserver) {}
cols: Observable<any> | undefined;
ngOnInit(): void {
const grid = new Map([
['xs', 1],
['sm', 2],
['md', 3],
['lg', 4],
['xl', 5],
this.cols = this.mediaObserver.asObservable().pipe(
map((change: MediaChange[]) => {
return grid.get(change[0].mqAlias);

Let’s walk through the above code:

We inject the mediObserver into the constructor as before, then create a new Map of the breakpoints. We set up an observable to the mediaObserver using the asObservable(). When the browser is resized, we get the currently set breakpoint from mqAlias, get the matching value from the grid array, and assign all of this to the cols variable.

<mat-grid-list rowHeight="1:1" [cols]="cols | async" gutterSize="6px">
<mat-grid-tile> {{1}} </mat-grid-tile>
<mat-grid-tile> {{2}} </mat-grid-tile>
<mat-grid-tile> {{3}} </mat-grid-tile>
<mat-grid-tile> {{4}} </mat-grid-tile>
<mat-grid-tile> {{5}} </mat-grid-tile>

In the HTML we set up an Angular Material grid list component and use the async pipe operator to subscribe to the cols observable. The grid shrinks as the browser width decreases. Tile rows wrap to the row below until only one tile can fit on a page. When the browser width increases, the tiles move up to form one long row.

Output when the browser is resized.

The number we get back from the grid Map denotes the number of columns shown in our grid list, here the browser size is ‘md’ or ‘3’ columns.

Using the mediaObserver we now have an observable that we can subscribe to in our application and track when our viewport changes. The mediaObserver can be used in both the HTML or the Typescript code behind and we walked through a couple of examples in this post.

Thanks for reading.

The alternative layout library for Flex-box and CSS Grid

The alternative layout library for Flex-box and CSS Grid

If you’ve been looking for an alternative way to write Flexbox or CSS Grid, then Angular’s Flex-Layout might just be the library for you. This post will cover what Angular Flex-Layout is, how to set it up, and a basic overview of the Angular Flex-Layout library.

What is Angular Flex-Layout?

Angular Flex-Layout provides a layout API using Flexbox CSS and mediaQuery. This provides Angular developers with component layout features using a custom Layout API, mediaQuery observables, and injected DOM flexbox CSS Stylings.

The real power of Flex-Layout is the responsive engine. This responsive API enables developers to specify different layouts, sizing, visibilities and viewport sizes, and display devices.

Why choose Angular Flex-Layout?

As the name suggests [Angular Flex-Layout] is a library for laying out your components on your web page. The library does not provide a means for styling, fonts, or colours, as those tasks are delegated to traditional styling in your application. Angular Flex-Layout deals with component positioning and works well with or without Angular Material. It is also built by the Angular team and supported by the community.

Some of the main advantages for using Angular Flex-Layout are:

  • The library is a pure Typescript Layout engine.
  • Uses HTML markup to specify layout configurations.
  • Independent of Angular Material.
  • A responsive API can specify different layouts, sizing, visibilities, viewport sizes, and display devices.
  • Includes CSS Grid.
  • Requires no external stylesheets.

So, let’s have a look at Angular Flex-Layout.

Getting Started.

To install Angular Flex-Layout from the command line type the following into your project directory.

npm install @angular/flex-layout @angular/cdk

Next, we need to import this into app.module.ts. We have a couple of options, we can import both Flexbox and CSS Grid using the FlexLayoutModule or we can specify either FlexModule for Flexbox or GridModule for CSS Grid.

// Flexbox mode (only)
 import {FlexModule} from '@angular/flex-layout/flex';
 // CSS Grid mode (only)
 import {GridModule} from '@angular/flex-layout/grid';
 // Flexbox and CSS Grid (both)
 import {FlexLayoutModule} from '@angular/flex-layout';
     imports: [ FlexLayoutModule ],

In this post, we will use the FlexLayoutModule.

Import FlexLayoutModule from the @angular/flex-layout library in your app.module.ts file as shown below.

import { NgModule } from "@angular/core";
 import { BrowserModule } from "@angular/platform-browser";
 import { FormsModule } from "@angular/forms";
 import { AppComponent } from "./app.component";
 import { FlexLayoutModule } from "@angular/flex-layout";
   imports: [BrowserModule, FormsModule, FlexLayoutModule],
   declarations: [AppComponent],
   bootstrap: [AppComponent]
 export class AppModule {}

How does Angular Flex-Layout work?

Angular Flex-Layout works by dealing with one row or column at a time. Rows flow across the main axis and columns on the cross axis.

Note: remember that Flexbox is a single-dimensional layout (row or column), where CSS Grid is a two-dimensional layout (row and column).

We start by defining a row or column layout type using the Angular Flex-Layout directive fxLayout= “row” or fxLayout= “column”.

The options are:

API: fxLayout <direction> [wrap]
Allowed values: row | column | row reverse | column reverse
Wrap: is optional and can be applied regardless of the direction.

Content can be positioned on either axis by using another Angular Flex-Layout directive called fxLayoutAlign and this directive requires at least one value (main-axis).

API: fxLayoutAlign <main-axis><cross-axis>
Allowed values:
(main-axis): start* | center | end | space-around | space-between | space-evenly.
(cross-axis): start | center | end | stretch* | space-between | space-around | baseline.

*denotes the default values

The default for fxFlexLayoutAlign is “start stretch” (regardless of whether fxLayout is set to row or column), fxLayoutAlign= “start stretch” can also be shortened to fxLayoutAlign= “start”.

Flexbox — direction reference map

For a default Angular app using Angular Flex-Layout, add the following markup to the app.component.html file.

<div class="outerContainer">
  <div fxLayout="row" fxLayoutGap="10px" class="container">
    <div fxLayoutAlign="center center">1</div>
    <div fxLayoutAlign="center center">2</div>
    <div fxLayoutAlign="center center">3</div>
    <div fxLayoutAlign="center center">4</div>
.outerContainer {
  padding: 5px;
  border: 1px solid #b6b6b6;
  box-sizing: content-box;

div.container {
  color: #eeeeee;
  margin-bottom: 10px;

div.container > div {
  height: 50px;
  width: 50px;
  background-color: blue;

The above markup creates the four numbered boxes shown below in image 1. I’ve added the above CSS to make it easier to see. Let’s walk through the HTML code.

We start with the directive fxLayout= “row” this sets the layout direction to rows. Setting fxLayout to “column” would stack the boxes vertically as shown in image 2.

Next, fxLayoutGap=”10px” sets the margin-right property on the containing DIV elements. The margin-bottom property is set if the layout direction is by columns. This produces a 10pixel gap between each blue box. Each DIV has fxLayoutAlign= “center center” this aligns the content horizontally and vertically, in this instance, the content is the numbers within each DIV.

Image 1: fxLayout=”row”
Image 2: fxLayout= “column”

Flexbox is ideal for moving items or content around the page, but it’s also responsive, so when the browser changes its size the contents on the page change size automatically. Likewise, when the browser is on a smaller (or larger) device the content can be displayed accordingly to the screen size using breakpoints, these breakpoints coincide with CSS mediaQueries. For example:

  • lg = screen and (min-width: 1280px) and (max-width: 1919.99px)
  • lt-xl = screen and (max-width: 1919.99px)
  • gt-md = screen and (min-width: 1280px)
  • gt-sm = screen and (min-width: 960px)
  • gt-xs = screen and (min-width: 600px)
<div class="outerContainer">
  <div fxLayout="row""column" fxLayoutGap="10px" class="container">
    <div fxLayoutAlign="center center">1</div>
    <div fxLayoutAlign="center center">2</div>
    <div fxLayoutAlign="center center">3</div>
    <div fxLayoutAlign="center center">4</div>

In the above code, the directive triggers the small breakpoint. When the browser gets to a certain size, for example: screen and (min-width: 600px) and (max-width: 959px) the row of blue boxes now becomes a column of blue boxes. We can also add these breakpoints to other directives like:

  • fxFlexAlign — element-specific overrides on the cross axis.
  • fxLayoutGap — defines padding of child elements in a layout container.
  • fxLayoutAlign — defines the positioning of child elements along the main and cross axis in a layout container.
  • fxFlexOrder — configures the positional ordering of the element in a sorted layout container.
  • fxFlexOffset — configures the “margin-left” of the element in a layout container.

Each of the above directives can include one or more of the following breakpoints.

.xs, .sm, .md, .lg, .xl, .lt-sm, .lt-md, .lt-lg, .lt-xl, .gt-xs, .gt-sm, .gt-md, .gt-lg

For example fxLayout.xs There is a breakpoint to cover almost every possible display scenario.

The fxFlex directive resizes elements horizontally or vertically. We can specify this directive in one of two ways:

fxFlex= “<grow> <shrink> <basis>”

  • grow: defines how much an item should grow, if space is available.
  • shrink: defines how much an item should shrink if there is not enough space available.
  • basis: controls the default size of an element, before it is manipulated by other properties.

or using the shorthand method:

  • fxFlex= “” (or just fxFlex)
  • fxFlex= “1 1 5em”
  • fxFlex= “1 1 calc(5em + 5px)”
  • fxFlex= “1 1 auto”

Think of this shorthand version as MaxMin and Ideal.

As an example, we set the second DIV (line 4, in code below) to fxFlex= “2 1 auto”. This means that this DIV will take up twice the space as the other DIVs.

<div class="outerContainer">
  <div fxLayout="row" fxLayoutGap="1px""column" class="container">
    <div fxLayoutAlign="center center">1</div>
    <div fxFlex="2 1 auto" fxLayoutAlign="center center">2</div>
    <div fxLayoutAlign="center center">3</div>
    <div fxLayoutAlign="center center">4</div>

Image 3 using fxFlex

For the shrink, we have set this to one this means use the same space at all times, if we had set this to zero it wouldn’t shrink at all.

fxFlex=”2 0 auto”

The third value is set to ‘auto’ in the above example. The width or height of the content is used as the ideal size. This setting is shown in the following markup (line 4):

<div class="outerContainer">
  <div fxLayout="row" fxLayoutGap="1px""column" class="container">
    <div fxLayoutAlign="center center">1</div>
    <div fxFlex="0 0 auto" fxLayoutAlign="center center">2</div>
    <div fxLayoutAlign="center center">3</div>
    <div fxLayoutAlign="center center">4</div>

The default output appears below:

fxFlex=”0 0 auto”

We have covered most of the main directives in the Angular Flex-Layout library, there are a few others such as fxFlexOrderfxFlexFill, fxFlexOffset and fxFlexAlign which I may cover in a later post.


There is a lot more to the Angular Flex-Layout library than what I have covered here. The library also includes full CSS Grid support (though this is somewhat currently lacking in documentation, it is something I’m working to improve on). I will be doing a post on Angular Flex-Layout CSS Grid at a later date.

A Quick Guide to Website Security for Webflow Users

Written by: Cody McBride May 2021

High-profile security breaches are nothing new — they happen every day. But the results are the same: lost trust and potentially damaged systems. While large corporations have the time, staff, and money to put into repairing major cybersecurity snafus, most of us do not. If you are getting ready to move your website over to Webflow from WordPress or another platform, keep reading for a few tips on how to make your site as secure as possible.

Use experts to migrate and set up your new Webflow site.

First, understand that there are differences between each platform. Unless you plan to learn all of the nuances, it’s best to pay an expert when you’re ready to migrate to Webflow. A webflow developer utilizes their expertise along with tools designed to assist with migration and site development.

You may also want to bring in a cybersecurity pro to help evaluate your site and offer an extra layer of protection. Bear in mind, however, if you choose a freelancer, you’ll want to confirm not only their cost and delivery time, but also availability and customer satisfaction ratings by reading reviews.

Prevent comment spam.

Google and other search engines very much dislike spam comments. These are comments left on an article or blog post that are meant to draw your readers’ attention away so they click on a potentially dangerous link. Make sure your web developer uses Disqus or similar plug-ins/integration to automatically filter out malicious comments.

Block hackers with IP address monitoring.

Monitoring for repeated attempts at gaining access to your website is one of the best ways to prevent brute force attacks. An example of a brute force attack, according to Infosec Resources, is a dictionary attack. This is when a hacker uses software that attempts millions of passwords individually to gain access to your site. IP address monitoring is an important and prudent line of defence

Utilise AWS Shield.

Amazon Web services offer a host of excellent products that integrate seamlessly with Webflow sites. AWS Shield is one of these that protect against XSS cross-site scripting, as well as SQL injection attacks.

Add an SSL security certificate.

Webflow University explains that SSL hosting creates “an encrypted link between a web server and a browser.” SSL certificates are crucial any time customers input information into your website. It allows you to run an e-commerce store safely and provides a secure layer of encryption between your site and your users.

Don’t skip regular backups.

Regularly backing up your data is one of the most basic things you can do as a site owner. In the cloud, everything on your site can be backed up at regular intervals. This means you will always be able to access your data, even if cybercriminals block you from your actual site.

Upgrade to HTTP/2 — and get a bonus SEO boost!

HTTP/2 is like the younger, wiser, and faster brother of HTTP. It allows for expedient data flow in both directions, which reduces client/server exchange times. Further, HTTP/2 is automatically (but optionally) encrypted. As an added bonus, it looks great to the search engine crawlers and may give your website an advantage over similar sites that utilize the old HTTP.

Prioritize passwords on sensitive pages.

You already know that you should be using a password to log into your website, and so should your customers. Make sure that your passwords — plus those of your employees and website users — are, at minimum, seven characters long. Stronger passwords contain numbers and letters, potential misspellings, or a seemingly random string of letters.

While there is no guarantee that you will never be targeted, the tips above will act as a fence around your online real estate. Remember, however, that cybercriminals are smart, and they continue to gain knowledge each day. Make sure your website stays up to date, too, and that you continually scrutinize your security protocols.

Image via Pexels

For regular insight into software development and the developer experience, be sure to subscribe to the AngleBrackets blog.

How To Best Use The Angular Material Form Field?

Photo by Markus Winkler on Unsplash

Blog Post #010

Duncan Faulkner November 2020

What is a mat-form-field component?

The mat-form-field is part of the Angular Material library and is found in the @angular/material/form-field namespace.

{MatFormFieldModule} from '@angular/material/form-field';

So what is a mat-form-field component? By itself this component doesn’t do much, this component affects other components by applying common styles to components that are wrapped within a mat-form-field. Typically components like input, textarea, mat-select, and mat-chip-list are wrapped in a mat-form-field this is considered a best practice, for example:

    <input matInput>

Below is the results rendered in the browser.

figure 1: legacy input

The input now has an underline underneath it. Selecting the input moves the text from the placeholder to a floating label.

figure 2: input selected placeholder now becomes floating label

This is the default appearance of the <mat-form-field> and is called Legacy, the others are Standard, Fill and Outline.

<mat-form-field appearance="legacy">
    <input placeholder="application label" matInput>
<mat-form-field appearance="standard">
    <mat-label>application label</mat-label>
    <input matInput>
<mat-form-field appearance="fill">
    <mat-label>application label</mat-label>
    <input matInput>
<mat-form-field appearance="outline">
    <mat-label>application label</mat-label>
    <input matInput>
figure 3: image of all four form-field appearances.

Standard: is an updated version of Legacy to bring it inline with Fill and Outline, the changes are minor and mainly around the spacing.

Fill: adds a background to the input and the placeholder is middle aligned (more space between the placeholder and the bottom line), the floating label remains with in the background.

Outline: adds an outline all round the outer edge of the input and the placeholder is middle aligned (more space between the placeholder and the bottom line), and the floating label is now on top of the outline.

Placeholders: In the Legacy appearance, the placeholder is promoted to a floating label. In Standard, Fill and Outline however, it is just a regular label. If you want a floating label in Standard, Fill and Outline you need to include a <mat-label>.

matInput: this is an Angular Material directive that allows native HTML input components (input, textarea, select for example) to interact with Angular Material.

Hint messages: The mat-form-field has two ways to assign a hint message. A hint message is a message that appears underneath the underline. If the hintLabel attribute of the mat-form-field is used then the message is left aligned (for the hintLabel attribute left aligned is the only option).

If the mat-hint tag is used then these can be left or right aligned, by setting the align attribute to either start or end.

figure 4: hintLabel – left aligned
<mat-form-field hintLabel="hint message" appearance="standard">
    <mat-label>Standard Input</mat-label>
    <input matInput/>
figure 5: mat-hint – right aligned
<mat-form-field appearance="standard">
    <mat-label>Standard Input</mat-label>
    <input matInput/>
    <mat-hint align="end">hint message</mat-hint>

Hint message appear underneath the underline. The mat-form-field can have hint messages set either from the mat-form-field or the mat-hint. To set the hint message using the mat-form-field set the hintLabel attribute to a message. With this option the message is left aligned.

<mat-form-field hintLabel="hint message" appearance="standard">
    <input matInput>

Using the mat-hint element set a message and alignment, for example:

<mat-form-field appearance="standard">
    <input matInput>
    <mat-hint align="start">Message</mat-hint>
<mat-form-field appearance="standard">
    <input matInput>
    <mat-hint align="end">Message</mat-hint>

Adding error messages to a mat-form-field appear underneath the underline. To add an error message add the mat-error element and check the validity of the form control.

<mat-form-field appearance="standard">
    <input matInput [formControl]="control" required>
    <mat-error *ngIf="control.invalid">This is a required field.</mat-error>

The formControl is part of Angular’s forms module and is used to track the value and validity state of a control. Then in the mat-error we add an *ngIf to check to see if the formControl is invalid, if it we display the error message.

Hope you enjoyed this little tutorial, I will be writing up more articles on Angular Material, feel free to reach out to me on Twitter.

How To Best Update Angular To Include Angular Material?

Blog Post #009

Duncan Faulkner – August 2020

Adding Angular Material to a new or existing Angular project is a simple process. In the terminal, change the directory to your project and type:

ng add @angular/material

The Angular CLI will now install Angular Material, Angular CDK and Angular Animations and add these as a dependency to the project.

In previous versions of Angular (before v9) hammerjs was required for touch and gesture support.

npm install hammerjs

In the main.ts file in the imports at the top, include the following:

import 'hammerjs' // add this import
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
  .catch(err => console.log(err));

Starting with version 9 of Angular hammerjs is now optional, you no longer need to install this as a dependency, it is now part of @angular/platform-browser. To use it, add the HammerModule to the platform-browser import in the app.module.ts file and include it in the NgModule imports array.

import { HammerModule, BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
  declarations: [
  imports: [
    bootstrap: [AppComponent]
export class AppModule {

You can also create a custom class to override specific features of HammerModule.

import { Injectable } from '@angular/core';
import { BrowserModule,
from '@angular/platform-browser';
export class HammerConfig extends HammerGestureConfig {
    overrides = <any> {
       'pinch': {enable: true}
  declarations: [
  imports: [
      useClass: HammerConfiguration
   bootstrap: [AppComponent]
export class AppModule {

The other values that can be overridden are:
pan, pinch, press, rotate, swipe and tap.
Note: that pinch and rotate are disabled by default.

Thanks for reading enjoy…

How To Secure Your Azure App Services With An SSL?

Photo by Dayne Topkin on Unsplash

Blog Post #008

Duncan Faulkner – February 2020

Back in 2018, Scott Hanselman wrote this post on adding Let’s Encrypt SSL certificates to Azure App Services, click here to see Scott’s original post.

I’ve used Scott’s post to apply SSL certificates to my websites for a while now, but the Azure interface keeps changing and Scott’s post is difficult to follow because it has so changed so much. So while I was adding another SSL certificate, I thought I would write an update post as a reminder to myself but also to help others who find themselves trying to add an SSL certificate to Azure using the Lets Encrypt extension.

This post assumes you have a website setup and running and a domain name, this post just walks you through adding a Lets Encrypt certificate to the website.


Azure Storage connection string – You’ll need one for the extension to store state. If you haven’t got one setup configure this before you start.

App Service Hosting Plan and App Service Resource Group Name – your Azure plan (the VM your site runs on) and your site must be in the same resource group.

There are a number of ID’s and connection strings to copy and paste that will be required at the end, I suggest opening a text editor to copy these into as we go.

So open Azure and Login.

App Registration

From the Azure home page, select the App registrations menu item.

From the App Registrations page, select New Registration.

For the Name, my convention is to use: Let’s Encrypt – <website name>, where website name is the name of my website I’m adding the SSL to. Select your supported account type, for me this was the default and for the Redirect URI, select web and enter the full URL to your website.

Open the newly created resource, and copy to your text editor the Application (client) ID, Directory (tenant) ID, Object ID as you will need these later in the process.

In Certificates and Secrets, create a New Client Secret, set the Description to Login and set it to Never Expire. Before closing this page copy the value to your text editor for later.

Now go to the Resource Group, this is the same resource group that your website belongs to, I’ve tried having a different resource group and couldn’t get it to work.

Once in the Resource Group, select Access Control (IAM) from the menu, click Add a new Role Assignment, in the Role drop down select Contributor, in the Assign access to drop down select Azure AD User, group, or service Principal (the default) and in the Select drop down type in Let’s Encrypt – website name this refers to the App Registration from earlier. The Selected Members should now show the Let’s Encrypt website name, now click Save.

Now head over to your actual App Service (your website) and click Extensions, Click Add Extension, then Select Choose Extension. In the list of extensions, scroll down until you find Azure Let’s Encrypt SKJP, there are two versions select the first one (see image below).

Then accept the Terms and Conditions and click OK that to return to the App Service. The extension should now be installed.

Scroll back up to Configuration and in the Application Settings section add two Connection strings. These are AzureWebJobsDashboard and AzureWebJobsStorage – Don’t forget this step or it will work once but won’t renew in three months during the renewal.

Both of these should be set to your Azure Storage Account connection string, e.g. DefaultEndpointsProtocol=https;AccountName=[myaccount];AccountKey=[mykey];

Replace value with your Azure Storage Account connection string details.

Save the changes.

And that’s pretty much it for the Azure side of things, now we need to configure the Extension.

In a new browser tab enter: into the address bar, replacing YOURSITENAME with your actual website name.

This can take a while to resolve, so be patient. Once resolved you should see this.

Scroll down to the Automated Installation section.

Starting from the top.

Tenant – this is your Azure Active Directory URL, its the one ending

Subscription ID – this can be found in the Overview page of your website.

Client ID – this is the application (client) ID from the App Registration section.

Client Secret – this is the value of the Login from the Certificates and Secrets section.

Resource Group Name – is the name of the Resource group

Service Plan Resource Group Name – this is the resource group your service plan is in.

Note: Resource Group Name and Service Plan Resource Group Name are usually the same.
I tried to have a different resource group and service plan resource group, but I couldn’t get it to work. As soon as I moved them into the same resource group it all worked. I missed this when reading Scott’s blog post the first time, (it’s in the checklist section if you are wondering).

Use IP Based SSL – I’ve left this unchecked.

Web App Name – this will be pre-populated with your website name.

Site Slot name – I’ve left this blank.

Dashboard Connection String – this will be pre-populated from your connection string set earlier.

Storage Connection String – this will be pre-populated from your Azure Account Storage connection string.

Update Application Settings and Virtual Directory (if needed) – I’ve checked this box, this will update your site in Azure.

With all that information in place apply the settings, this will take a while to complete, so please be patient.

When this (eventually) returns it will list your website domain and any previous SSL certificates you may have. Click Next.

Select all the hostnames you want an SSL for (you can of course just select one domain as a test), enter a valid email address, as this is the first time creating an SSL for this website, I would recommend checking the staging check box. By using staging it allows you to generate unlimited test SSL certificates, when unchecked the limit is five and you will have to wait a whole month before you can generate any more (only made that mistake once). Just in case you have an issue when generating the certificate.

If the certificate generation is successful, then the certificates will be installed, as we ticked staging these won’t be valid in the browser, so click next again and repeat the steps, this time with staging unchecked.

You may need to refresh/restart your browser for the certificate to appear, especially if you have your site open.

And that’s all there is to it, in three months time this will auto renew your SSL certificates.

Check back into Azure and the websites TLS/SSL settings section you should see a TLS/SSL binding.

How To Best Use Drag ‘n’ Drop Angular Material Table?


Blog Post #007

Duncan Faulkner – February 2020

The Angular Material mat-table component probably has the most examples on the Angular Materials website. But I think we can squeeze one more in.

So here is a Drag ‘n’ Drop example.

I needed the ability to drag ‘n’ drop rows in a mat-table for a project I was working on and I thought this would make a good example of how easy it was to implement.

This example requires all the usual setup of an Angular application, rather than fill this post with all the steps to setup an Angular project. I have written a post here that goes through the steps. I will also create a another separate post on adding Angular Material, but for now here is how to add Angular Material to your Angular Project.

Project set up? Let’s add Angular Materials, from the terminal type:

ng add @angular/material

This will add the Angular Material dependencies to the project, next create a directory called shared and then add a new file called material.module.ts in this directory.

Then add the material imports, for this we just need MatTableModule.

// Other Material imports here
import { MatTableModule } from '@angular/material/table';
const MATERIALMODULES = [MatTableModule];
     imports: [...MATERIALMODULES],
     declarations: [],
     exports: [...MATERIALMODULES]
export class MaterialModule {}

Then import material.module.ts file into the app.module.ts file.

// default modules add when app.module.ts was created
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { HttpClientModule } from "@angular/common/http";
// Add these modules to import
import { MaterialModule } from "./shared/materials.module";
import { DragDropModule } from "@angular/cdk/drag-drop";
const MATERIALMODULE = [MaterialModule];
const APPCOMPONENT = [AppComponent];
  declarations: [...APPCOMPONENT],
  imports: [...IMPORTMODULES],
  exports: [...MATERIALMODULE],
  providers: [],
  bootstrap: [...APPCOMPONENT]
export class AppModule {}

The MaterialModule is the Angular Material file we just created a few moments ago and the DragDropModule is required to implement the drag and drop from the Angular Material CDK (more on this later).

In the app.component.html file remove any html and replace it with the following.

<table mat-table [dataSource]="dataSource" cdkDropList [cdkDropListData]="dataSource"
    (cdkDropListDropped)="drop($event)" class="mat-elevation-z8">
    <ng-container matColumnDef="drag">
        <th mat-header-cell *matHeaderCellDef> Drag </th>
        <td mat-cell *matCellDef="let element">
            <mat-icon cdkDragHandle svgIcon="dragVertical"></mat-icon>
    <!-- Position Column -->
    <ng-container matColumnDef="position">
        <th mat-header-cell *matHeaderCellDef> No. </th>
        <td mat-cell *matCellDef="let element"> {{element.position}} </td>
    <!-- Name Column -->
    <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let element"> {{}} </td>
    <!-- Weight Column -->
    <ng-container matColumnDef="weight">
        <th mat-header-cell *matHeaderCellDef> Weight </th>
        <td mat-cell *matCellDef="let element"> {{element.weight}} </td>
    <!-- Symbol Column -->
    <ng-container matColumnDef="symbol">
        <th mat-header-cell *matHeaderCellDef> Symbol </th>
        <td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;" cdkDragLockAxis="y" cdkDrag [cdkDragData]="row">

A mat-table component takes a datasource, but we also need to add cdkDropList, a cdkDropListData and cdkDropListDropped to the table. The cdkDropList is a container that wraps a set of draggable items. The cdkDropListData is the datasource to attach to this container. And the cdkDropListDropped emits an event when a user drops an item into the container.

The last <tr> section in the mat-table, needs the collection of columns this is the array containing the column names, and row refers to current row.

The cdkDragLockAxis restricts the dragged element to either vertical or horizontal, this stops the user dragging the item all over the screen if it doesn’t make sense to, for example if you are only dragging a list of items to sort them then locking the axis to the “y axis” would keep this within the boundary of the list. The cdkDrag refers to the item being dragged and cdkDragData is the data attached to this drag instance.

That’s the HTML section, now for the code section.

import { Component } from "@angular/core";
import { IconService } from "./services/icon.service";
import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop";
export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
const ELEMENT_DATA: PeriodicElement[] = [
  { position: 1, name: "Hydrogen", weight: 1.0079, symbol: "H" },
  { position: 2, name: "Helium", weight: 4.0026, symbol: "He" },
  { position: 3, name: "Lithium", weight: 6.941, symbol: "Li" },
  { position: 4, name: "Beryllium", weight: 9.0122, symbol: "Be" },
  { position: 5, name: "Boron", weight: 10.811, symbol: "B" },
  { position: 6, name: "Carbon", weight: 12.0107, symbol: "C" },
  { position: 7, name: "Nitrogen", weight: 14.0067, symbol: "N" },
  { position: 8, name: "Oxygen", weight: 15.9994, symbol: "O" },
  { position: 9, name: "Fluorine", weight: 18.9984, symbol: "F" },
  { position: 10, name: "Neon", weight: 20.1797, symbol: "Ne" }
 * @title Basic use of `<table mat-table>`
  selector: "app-root",
  styleUrls: ["app.component.scss"],
  templateUrl: "app.component.html"
export class AppComponent {
  constructor(private iconService: IconService) {
  displayedColumns: string[] = ["drag", "position", "name", "weight", "symbol"];
  dataSource = ELEMENT_DATA;
  drop(event: CdkDragDrop<PeriodicElement[]>) {
    moveItemInArray(this.dataSource, event.previousIndex, event.currentIndex);

The drop event takes a generic CdkDragDrop<> in this case it’s a array of type PeriodicElement, this refers to the row that is being dropped. The moveItemInArray takes a datasource, the previousIndex and the currentIndex. The dataSource is the array (in this example the ELEMENT_DATA), the previousIndex is where the item came (position 10) from and the currentIndex (position 1) is where the item is being dropped. This method does all the hard work of the sorting etc… we just need to write the code to persist this and update the view (I’ve not done that in this example). If you check the console.log at this point then we can see that the data has been reordered.

And that’s all there is to add Drag n Drop to a mat-table.

Tips On How To Write Good Git Commit Messages

Photo by Yancy Min on Unsplash

Blog Post #006

Duncan Faulkner – February 2020

This post is slightly off my usual topics of Angular and Angular Material though its loosely linked to Angular I felt it was worthy of a post as this is something we as developers do all the time.

I’ve been using Git for about five years or so now, and writing Git Commit messages can be hard (I would say this is just as hard as coming up with meaningful function and variable names in code), especially when trying to be consistent with the formatting of the message.

I’m sure we’ve all written commit messages like this, the way I have written them have all started like:

git commit -m "name-ticket-number - bug fix"
git commit -m "name-ticket-number - more work"
git commit -m "name-ticket-number - minor changes"
git commit -m "name-ticket-number - work on feature X"
git commit -m "name-ticket-number - updated Y on..."  

At first these don’t appear to look that bad, you get a rough idea of the change. But when faced with hundreds of commit messages (and from different developers), finding a specific Commit in the Git History becomes that much harder.

Up until quite recently I hadn’t realised that you can provide multiple -m flags with a commit to add multiple commit messages.

Why would you want to add multiple messages to a commit?

Surely we can just cram everything into one message?

By adding multiple messages you can provide much more detail and be more specific about the commit, it doesn’t need to be an abbreviated or cryptic message that only you can remember what the commit was for.

Now, when reading a commit message in say GitLab, the first message becomes the Subject, the second message is the Body, the third message is the Footer (I’ll come to this in a bit), their values are concatenated as separate paragraphs.

git commit -m "name-ticket-number - fixed..." -m "body/description..." -m "footer..."

So this is a little better, adds more detail to the commit message, but we could improve this further by following a convention.

Conventional Commit Standard (I didn’t know that was a thing either!). This is a set of guide lines for creating Git Commit messages that follow a particular format.

The format is:


Each commit message consists of a header, body and footer. The header is mandatory, scope is optional, subject is mandatory. When writing a commit message try and limit each line of the commit to a max of a 100 hundred characters, so it can be read easily on GitLab etc…

It is also acceptable to add the project name or a ticket number in square brackets, for example: [foo-1234] fix(user-service): changed user….
If using something like Jira this [foo-1234] becomes a hyperlink to the ticket from Gitlab / Github.


The type must be one of the following:

  • build: Changes that affect the build
  • ci: Changes to our CI configuration files and scripts
  • docs: Documentation only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  • test: Adding missing tests or correcting existing tests


If a commit reverts a previous change then the type should begin with revert: and the body should explain what this change is reverting.


The scope refers to the section that this commit belongs to Components, Services, Directives, Pipes for example user-component, user-service, user-directive etc.. Other scopes include changelog, styles, test and refactor.


The subject should contain a short description of the change, and written in present tense, for example “change” and not “changed” or “changes”.


The body should contain a longer description of the change, try not to repeat the subject and keep it in the present tense as above.


The footer is used to highlight where issues have created a breaking change in your commit. The footer should start with BREAKING CHANGE: the body should contain a description of the breaking change.

The footer can also be used to reference other issues, for example: “Fixes ticket #123”.


A few examples of Git Commit messages using this new format:

feat(order): add a save button
add the save button to the sales order form

docs(manual): document the order process
create new document explaining the sales order process

fix(user): update the user menu
update to the user menu to fix the broken menu item

fix(user-service): change save method in API
BREAKING CHANGE: change to the save method to include additional parameters

Let me know in the comments what you think to this format.

How To Best Use The Angular Command Line Interface (CLI)?

Blog Post #005

Duncan Faulkner – February 2020

I find myself repeating the Angular setup process at the start of most posts I write. So to save time. I will write it out here and reference this post when referring to setting up an Angular application in the future.

This will be a standard setup, for setting up a project with NX Workspaces see my previous post here.

Step one:

Open a terminal and create a directory to store our application in.

cd development
mkdir myproject
cd myproject

Step two:

If you have nvm, node and the angular cli installed you can skip this step.

To install node.js, you could install this from, but for greater flexibility, I find installing node version manager (nvm), will save a lot of hassle next time you need update node.

Note: Remember to check the version number and update this in the scripts below, at the time of writing this was v0.35.2, it may be different.
Note: You only need to run one of these.

curl -o- | bash


wget -qO- | bash

Once installed you should be able to check the version, in the terminal type:

nvm --version

Now we have nvm installed we can install node. Again from the terminal type:

nvm install #and the version of node you want to install, for example:
nvm install 12.14.1
#Other useful nvm commands are:
nvm ls #this will list all installed versions of node
nvm use 12.6.0 #will use this version of node.
nvm alias default v9.3.0 #this will set the default version.

Now we have node installed we can now install angular cli, from the ternimal type:

npm install -g @angular/cli 

This will install the angular cli globally, as denoted by the -g. After installation is complete check the version of angular by typing:

ng v
angular version printed out in console
screen shot of angular version

Step three

Now that’s all setup, lets create a project, in the terminal type:

ng new my-first-project

The angular cli will ask the following questions.

? Would you like to add Angular routing? (y/N) y
>SCSS [] #select this one
 Sass []
 Less []
 Stylus []

That should start the process off and it will install all the dependencies and create our project. You may see some warnings at the end of the install, these are dependencies they may need to be updated, which we will do at the end. For now switch to the my-first-project directory and open up VS Code.

cd my-first-project
code-insiders .
my-first-project shown in vs code

And that’s all there is to it.

Step four

Update the project to the latest versions. In the terminal type:

ng update #this will list any packages that have an update available.

This will check to see if there are any updates, if there are then run:

ng update --all
#there are a couple of additional flags that can be used (with caution!) these are:
ng update --all --allow-dirty #this allows the update to happen when the current branch (if using version control) has not been checked in
ng update --all --allow-dirty --force #this will force the updates, though chances are compatibility will be broken and you may need to roll some packages back to a previous state. 

There is a good chance that this will fail, mainly because there are newer versions of certain packages that would break compatibility.

The next step would be to add Angular Material to the project. For that I will create a separate post so as to keep this purely for the standard setup.

Thanks for reading enjoy…

Previous Posts