A common issue when adding a required attribute to a textbox/textarea in an Angular application is that someone can just press space bar once, and the “required” validation is completed. A space counts as character!

The simple way to get around this is to use a regex pattern attribute to validate that there is more than just a space. Something like :

<input type="text" pattern="^(?!\s*$).+" />

But this quickly gets annoying to copy and paste everywhere. A better solution if you need to validate multiple fields the same way is to create a nice directive. Here’s one I prepared earlier :

import { Directive } from '@angular/core';
import { NG_VALIDATORS, Validator, ValidationErrors, AbstractControl } from '@angular/forms';

@Directive({
  selector: '[noWhitespace]', 
  providers: [{ provide: NG_VALIDATORS, useExisting: NoWhitespaceDirective, multi: true }]
})
export class NoWhitespaceDirective implements Validator {

  constructor() { }

  validate(control: AbstractControl): ValidationErrors {
    if(!control.value || control.value.trim() == '')
    {
      return {'required' : true };
    }

    return null;
  }

}

Simply place this on any text input/area control like so :

<input type="text" noWhitespace />

And you will now validate that the control has a value *and* that the value is not just whitespace. Easy!

I came across an interesting challenge recently that involved being able to pass a “template” between components. In my particular case, I had a “table” component that simply laid out tabular data, nothing too crazy. In most cases I simply wanted the text value of a property to be displayed, but in some rare cases, I needed a custom template to be shown. While it may seem simple, simply pass through a string variable with HTML inside and be done with it, when it comes to data binding, it actually becomes a bit more complex than that.

I quickly came across TemplateRef in the Angular documentation which sounded like what I needed, but as is the case with many Angular internals, the documentation was somewhat lacking. So let’s explore TemplateRef and see what it can actually do.

The Basics

The basics to actually get a “TemplateRef” variable in the first place looks like so. Let’s say I create a component called “ParentComponent”. I’m going to create the HTML (thus far) looking like so :

<ng-template #myTemplate>
    <h1>This is my Template</h1>
</ng-template>

All this is doing is creating a “template” object called #myTemplate. This actually doesn’t render anything to the page, it simply tells Angular that at some point, you will use this template somewhere. I think it’s probably pretty similar to Handlebars templating if you’ve ever used that before.

Now the code behind our component will be very simple.

export class ParentComponent implements OnInit {

  @ViewChild('myTemplate', {static : true}) myTemplate : TemplateRef;

  myModel = {
  };

  constructor() { }

  ngOnInit() {
    this.myModel =  {
      template : this.myTemplate
    }
  }

}

So all we are doing here is using ViewChild to get a reference to the actual template and storing it in a TemplateRef variable. I’m also creating a “model” object. Although you don’t have to do this, from my MVC days I prefer creating a “ViewModel” to pass between components. In our case we want to create a second component to accept this template.

So I’m going to create a component called ChildComponent. The code behind the component looks like so :

export class ChildComponent implements OnInit {
  
  @Input() model : any;

  constructor() { }

  ngOnInit() {
  }

}

It will accept an input of “any” which in our case will be our model we created in our ParentComponent. Really I should create a proper strongly typed class here but for now, the type of any will suffice.

For the HTML of our child component, we then need to do the following :

This is my child component. <br />

<ng-container *ngTemplateOutlet="model.template"></ng-container>

What we are doing here is outputting an ng-container that is given a template (The template we passed through) to render.

If we go back to our ParentComponent and add the child tag to it so the HTML ends up looking like :

<ng-template #myTemplate>
    <h1>This is my Template</h1>
</ng-template>

<app-child [model]="myModel"></app-child>

Run everything and wham! Our template is passed through to our child component that renders it perfectly!

Why Not Use NG-Content?

So another way to achieve this is using the <ng-content> tag which we will definitely talk about in another post. But if a developer is asking you why not just use that? Well… After using it for a while I’ve found that the ng-content tag is great for single projections, but if you are wanting to pass multiple templates into a component ng-content is a little bit more rough around the edges on how that works. The other thing I found was that the data binding was no where near as intuitive in ng-content as it is using ngTemplateOutlet.

Databinding?! You can do that?! You sure can. Let’s take a look at hot it works.

Databinding NgTemplateOutlet

A very common scenario for templates is that you will want to databind values inside the actual template. The issue with this is, what is it binding to? In our example above, if we added data bindings to our template would it be binding to the ParentComponent since that’s where the template is defined, or would it bind to the ChildComponent because that’s where the template is actually output?

The answer is neither. It doesn’t bind at all unless you specify where it should bind and to what.

Let’s modify our template to bind a subheading. The way to make this work looks like :

<ng-template #myTemplate let-data="data">
    <h1>This is my Template</h1>
    <h4>{{data.subheading}}</h4>
</ng-template>

So you’ll notice we do a “let” command above. What that says is, I’m going to be passed a value called “data” (That’s the data actually inside the quotes), when I’m given that, bind it to a variable called “data” that is scoped to this template.

Then below, I will expect on this data object to be a subheading property.

Go back to our ParentComponent and change how we bind the model to also have a subheading property :

ngOnInit() {
  this.myModel =  {
    template : this.myTemplate, 
    subheading : 'this is my subheading'
  }
}

Because we are still passing through our model to the child component, the binding and codebehind there stays the same. But inside the actual HTML of the ChildComponent we have to tell it the context we want to give it. We do that like so :

This is my child component. <br />
<ng-container *ngTemplateOutlet="model.template; context: { data : model}"></ng-container>

So notice on the *ngTemplateOutlet, we pass in a context. Now personally, I like to create another “sub” object with a key value like this. This means that you can pass in multiple values on the same object etc, but it’s up to you.

Now when our template is run, it knows about this object called “data”, and can use that to bind values. Super easy!

I have a pretty easy rule when it comes to using NG-Deep on my projects, “if you think you need it, I would think a little harder”. 9 times out of 10 when I see people using the ng-deep modifier, it’s because they want a “quick fix” without really thinking through the consequences. And in the majority of those cases, the use of ng-deep comes back to bite. I want to talk a little more about NG-Deep “bleeding”, and how the lazy loading of styles in Angular often hides the issue until things are already in production.

What Is NG-Deep?

NG-Deep is essentially a CSS pseudo element that allows you to “break” CSS encapsulation. For example let’s say that I have a very simple component like so :

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-first-parent',
  template: `<app-child></app-child>`,
  styles : ['h1 { color:red; }']
})
export class FirstParentComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

Notice a couple of things, that the template is simply a component called “child”, and on this particular page, I want all H1 tags to be red. Well you may think that if I create the child component like so :

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `<h1>This is a child component</h1>`,
  styles: []
})
export class ChildComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

We might at first suspect that the H1 tag is going to be red. But if we view it in a browser, it doesn’t work!

When we check the page source for our styling, we can see it looks like so :

h1[_ngcontent-iqb-c1] { color:red; }

The _ngcontent is our view encapsulation taking hold. Because we have put our H1 styling into our FirstParent component, it’s limited that styling to *only* that component. Because our H1 is actually in a child component, we are a bit shafted.

But hold on, we’ve heard about this amazing thing called ng-deep that basically removes encapsulation for components in Angular! Let’s try it!

If we change the styling of our FirstParent component from :

styles : ['h1 { color:red; }']

To :

styles : ['::ng-deep h1 { color:red; }']

Does everything work?

It does! And when we check the source code we can see that the styling has had the view encapsulation removed and it’s just a plain h1 style now!

<style>h1 { color:red; }</style>

So everything works right?

Adding Another Component

Let’s add another component that’s almost identical to the first. We’ll call it “SecondParent”.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-second-parent',
  template: `<app-child></app-child>`
})
export class SecondParentComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

This one is identical to the first, except that we don’t have any styling for our H1s. We instead just want to use the default styling.

We will also add some routing so that if we go to /firstparent, we are taking to the FirstComponent, and /secondparent goes to the second. The routing looks like so :

const routes: Routes = [
  { path : 'firstparent', component : FirstParentComponent}, 
  { path : 'secondparent', component: SecondParentComponent}
];

For this to work, we want a button on the FirstParent that goes to the Second, and vice versa. To make things easier for ourselves, we want to change the FirstParentComponent to have the following template :

template: `This is the first parent. <br /><app-child></app-child> <a [routerLink]="['/secondparent']">Go To Second Parent</a>`

And the SecondParentComponent should have :

template: `This is the second parent. <br /><app-child></app-child> <a [routerLink]="['/firstparent']">Go To First Parent</a>`

While theoretically the template changes aren’t needed, for this next little demo it will make things easier to see.

Let’s try a couple of straight navigation options.

If I go directly to /firstparent, I see :

This is correct. We get the red H1 tag.

If I go directly to /secondparent (By direct I mean typing it in my browser and not clicking the link), I see :

Also correct, we have the black H1 and not the red. Perfect!

Let’s try something else, if we go directly to /firstparent, then click the link to go to the SecondParent, what happens?

So.. When we go direct to /secondparent, everything works fine, but if we go to /firstparent, then navigate via Angular to the /secondparent, it all goes wrong. Why?

Well it’s actually a simple explanation.

CSS in Angular is LazyLoaded, that means that any styles for a particular component are only actually loaded when that component is itself loaded. For us that means that we only get our special ng-deep rule when FirstComponent is actually loaded, but if we go direct to the SecondComponent from our URL bar, then it doesn’t need to load that CSS and so doesn’t.

The reason I want to point this out is because in the majority of cases where I see ng-deep go wrong, it’s been incredibly hard to track down bugs where sometimes you have to go through a series of pages to recreate the bug. In our example, imagine if a tester/QA logged a bug that said when they went to /secondparent, the text was red. Well if we just tried to recreate it by going directly to that page, we wouldn’t see the issue!

At the crux of it though, we see that using ng-deep the way we have done causes big issues because we are essentially writing an H1 rule to the global stylesheet. It’s the exact issue that view encapsulation tries to fix, but then gives us the tools to wreck it anyway.

Working Without NG-Deep

Let’s look at some ways to work without NG-Deep, or more so ways in which we can limit our exposure to bugs like above.

Using :host

First up is my favourite, and one that Angular actually recommends, and that’s prepending any ng-deep rule with the :host modifier. We have a great article on how to use :host here! But in simple terms, if we change our rule inside FirstComponent to look like so :

styles : [':host ::ng-deep h1 { color:red; }']

What we are essentially saying is that we still want to go “deep”, but only when we are inside this particular component. The rule itself when written to the page looks like :

[_nghost-qxj-c1] h1 { color:red; }

Where the _nghost is the FirstComponent, and it’s saying any H1s inside this component can be red, but any H1s inside any other component will not be affected.

Being More Specific

If for some reason you don’t want to use :host (Or can’t), then another option is to simply be more specific in your rules that are going to be global. For example if we changed our template and styling inside FirstParent to look like so :

template: `This is the first parent. <br /><div class="first-parent-wrapper"><app-child></app-child></div> <a [routerLink]="['/secondparent']">Go To Second Parent</a>`,
styles : ['::ng-deep .first-parent-wrapper h1 { color:red; }']

So notice how we have now wrapped our child control in a very specific class, that we can then use for our styling. Even though this rule will be global, it’s unlikely (But not impossible), that someone somewhere else uses the same “first-parent-wrapper” class. But again, you are essentially breaking view encapsulation and banking that no one else uses this class name anywhere else.

Passing Variables

Of course the final option, which should be pretty obvious,¬† is that you can ofcourse pass styles or even switches to a child component. So you can create an input parameter for your child component called “headerText”, and then pass in the color you want it to be. This does have it’s limits though in that generally you are looking for a direct parent to child relationship, and you don’t want to be passing around styling several layers deep. But it’s an option!

Work Without It

This isn’t really a solution but one that always pays to keep in mind. Use of NG-Deep should be a last resort. It should be used when you really can’t find any other way to achieve what you are doing. You’ve asked on stackoverflow and on the Angular Github tracker, and there’s just no other possible way to do things without NG-Deep. Even then, you should use one of the above methods to limit your exposure.

Over the past couple of months I’ve been doing battle with an Angular Universal project. Angular Universal is Angular’s answer to Server Side Rendering or SSR for short. Why use SSR? In most cases it’s for SEO purposes but in some cases it also gives “perceived” performance.

For SEO, when opening a link to an SSR website, Angular renders the complete (Or semi-complete) page on the server, and returns the HTML that can be read by search engines (and other robots).

When I say “perceived” performance, what I mean is that because it’s atleast semi-rendered,¬† a user doesn’t see a flash of a blank screen like you normally get with regular Angular apps. I personally don’t think it really returns the complete page any faster than a regular Angular App, but the first paint is more “complete” than that of a regular Angular app.

It sounds good on the surface, but just try and have a quick search for how many people are actually using Angular Universal in production – there’s not many. Almost every tutorial you find on the subject is the Angular Universal equivalent of a “Hello World”. I won’t say I’m an expert on Angular Universal, but I wanted to write this article to maybe show you a couple of things that every tutorial leaves out of the conversation.

Library Support Is Rough

The first thing you probably learn when using Universal is that when the page is rendered on the server, it doesn’t have access to a couple of really important (common) javascript paradigms. Among them, you can’t access the window object (Since this refers to the browser window of which there isn’t one when doing server side rendering), you can’t access things like localStorage or any sort of memory that might live inside a browser window like Session Storage. Cookies are also a bit of an issue for obvious reasons.

Angular recommends you wrap things that need to access these objects inside a method called isPlatformBrowser so that you can check if you are in that moment doing server side rendering or if you are doing it in a browser. (More info here https://github.com/angular/universal/blob/master/docs/gotchas.md).

But, that’s with your code. What about something like an authentication library that uses localStorage? Like the MSAL library from Microsoft that allows your javascript application to integrate with Azure AD. They have a great Angular package that makes authentication a cinch. But they obviously haven’t gone and wrapped everything in browser checks. Why would they muddle their code with that when very very few people are using Angular Universal anyway?

And I ran into this same problem many times over. Even just libraries that try and access the window object (which has to be pretty common in javascript), they are going to completely bomb out when running inside Angular Universal. Of course, you can always fork the code or try and add in a bunch of browser checks yourself, but the point is is that all those libraries that were plug and play on your last project suddenly become a headache to get integrated.

Development Is Extremely Slow And Confusing

Let’s face it, building Angular Universal bundles are slow. When you have a plain Angular app and you run “ng serve”, it’s snappy. The watchers are fast and changing a couple of lines typically only takes a couple of seconds to recompile. I’ve found Angular Universal to be the exact opposite. Often with recompiles taking almost the exact same time as the initial compile. Those jokes back in the day of “can’t work, code recompiling” when you were working on mainframes are back!

I also found debugging of Angular Universal apps incredibly complicated and often confusing. You see it’s only the *initial* request that is server side rendered. As you click around the site, you are then inside a regular Angular app and therefore everything is client side. But common debugging tools like console.log() become very confusing to follow because if it’s an initial request, that log will be written on the server, not in the browser, all subsequent logs will be written to the browser. Same goes for any debugging tool you might use. The initial request would be like debugging a typical Express application, but all subsequent requests can be debugged just fine from the browser. Trying to bring a new developer up to speed is pretty damn difficult.

Documentation Is Terrible

Finally. The documentation is terrible. Angular Universal has one, yes one, page of documentation here : https://angular.io/guide/universal. That’s it. I even had to log a bug that the sample application they provide doesn’t actually compile at all. And they closed it was they were “working on it”. So not sure how hard it is to just provide a working example of an Angular Universal app, but evidently it’s still not been updated.

Beyond the official documentation, you typically rely on other examples and blogs floating around on the web that really only scratch the surface of what Angular Universal does. If you run into any roadblocks at all, you are pretty much on your own because as far as I’ve seen, no one actually uses Angular Universal in any large commercial capacity (Happy to be proven wrong though!).

Should You Use Angular Universal?

I’m a big believer in using the right tech for the right purpose. As it stands right now, I believe that if you need server side rendering, then don’t use a client side javascript framework to do it. While it’s not too hard to turn any app into Angular Universal. On any project of reasonable size, you’ll start hitting roadblocks thick and fast and soon realize that Angular Universal is a fun POC, but not a commercial offering.

This article is part of a series on creating multi step form wizards in Angular.

Part 1 – Basic Setup
Part 2 – Building Our Forms
Part 3 – Tying It All Together


We are on the home stretch with our multi-step form, infact we are pretty much there! But I wanted to give a few more tips on tying everything together, including an awesome debugging trick.

The Final HTTP Post

Having a form is useless unless it actually sends data, and luckily for us, we already have a service prepared to do just that – our FormDataService! At the moment it looks like :

export class FormDataService{

  personalDetails : PersonalDetails;
  addressDetails : AddressDetails;

  constructor() {
    this.personalDetails = new PersonalDetails();
    this.addressDetails = new AddressDetails();
   }
}

Our best bet is to add a simple “postData” method that collates everything together and talks to some backend API (Not features). For example :

export class FormDataService{

  personalDetails : PersonalDetails;
  addressDetails : AddressDetails;

  constructor() {
    this.personalDetails = new PersonalDetails();
    this.addressDetails = new AddressDetails();
   }

   postData(){
     let newCombinedObject = {
       personalDetails : this.personalDetails, 
       fullAddress : this.addressDetails.fullAddress
     }

     //Use somthing like http.post etc to send the data to the backend server. 
   }
}

I know that this is a bit of a simplistic view, but it’s hard to get into the nitty gritty without also building out an actual API. The point I want to make here though is that we have all the models from all the different steps of the form, we can take all of that data and mould it into our API model. In my case, I have taken the full personalDetails object, but from the address I’ve taken out the individual property. It’s up to you to transform the data how you need it, but the idea is that it’s all there to play with!

Heading back to our Address Details component, if we add in a click event handler to our backend :

export class AddressDetailsComponent implements OnInit {

  addressDetails : AddressDetails;

  constructor(private formDataService : FormDataService) { 
    this.addressDetails = formDataService.addressDetails;
  }

  ngOnInit() {
  }

  submit(){
    this.formDataService.postData();
  }

}

And then bind our HTML to that click event handler :

<table>
    <tr>
        <td>Full Address</td>
        <td><input type="text" [(ngModel)]="addressDetails.fullAddress" #fullAddress /></td>
    </tr>
    <tr>
        <td><input type="button" value="Back" routerLink="" /></td>
        <td><input type="button" value="Complete" (click)="submit()" /></td>
    </tr>
</table>

And we have a full complete submit routine!

Debugging Helper

The biggest thing I struggle with when building out extremely large forms with multiple steps is testing each individual input. Namely, that when I get to the end of the form to submit… I’ve almost forgotten what it was I typed at the start!

There’s actually a nice way to debug this (Atleast in Dev). The first thing we want to do is go to a parent component of our entire form, in our example project’s case, that’s simply the app-component. The first thing we do is inject the formDataService into the backend.

export class AppComponent {
  constructor(public formDataService : FormDataService) {
  }
}

Then we need to edit the HTML of the AppComponent to output the models of the service as JSON. That looks like so :

<h1>My Multistep Form</h1> 
<router-outlet></router-outlet>
Personal Details : {{this.formDataService.personalDetails | json}} <br />
Address Details : {{this.formDataService.addressDetails | json}}

Now as we fill out the form, on all steps we have a live update of how our model actually looks on the backend.

Not only is it handy when we get to the end of the form to be able to see what we “should” be submitting just before we submit it, but also if we have any complex controls/custom controls in our form, we can see exactly what’s going on in the backend as we fill them out.

Is This The Best Method?

Finally I just want to touch on if this is the “best” way of achieving a multi step wizard in Angular. You could probably swap out “best” for “most efficient”, “proper”, “up to date”, however you want to say it. As I said early on, this is the way I’ve been building these sorts of forms since the very early days of Angular. It’s served me well and even with things like Reactive Forms and RxJS becoming increasingly popular, I find this to be the most straight forward method. There’s no hidden “magic” or library doing things on the backend, it’s just simple code that works.

This article is part of a series on creating multi step form wizards in Angular.

Part 1 – Basic Setup
Part 2 – Building Our Forms
Part 3 – Tying It All Together


In the last part of this series on building a multi step form wizard, we got a simple project up and running, but it wasn’t really doing a heck of a lot. Let’s change that by building out the HTML forms to capture some basic information.

Personal Details Form Build

The first thing we want to do is to generate a new component called “PersonalDetails”. We can do that in the Angular CLI :

ng generate component PersonalDetails

The first thing we need to do is wire up the component to pull in the service, and load the personal details model out. Without too much faffing about, it will look like :

export class PersonalDetailsComponent implements OnInit {

  personalDetails : PersonalDetails;

  constructor(private formDataService : FormDataService) { 
    this.personalDetails = formDataService.personalDetails;
  }

  ngOnInit() {
  }

}

Pretty simple really. Inject the service in, pull out the personal details model, and set it locally. Remember that because the FormDataService is a singleton, for our entire app (per page load), there will only ever be one instance.

Next, we can replace personal-details.component.html with the following amazingly styled HTML.

<table>
    <tr>
        <td>First Name</td>
        <td><input type="text" [(ngModel)]="personalDetails.firstName" #firstName /></td>
    </tr>
    <tr>
        <td>Last Name</td>
        <td><input type="text" [(ngModel)]="personalDetails.lastName" #lastName /></td>
    </tr>
    <tr>
        <td>&nbsp;</td>
        <td><input type="button" value="Next" routerLink="addressdetails" /></td>
    </tr>
</table>

Not yes, we are using tables. And yes this is not going to look great at all but it’s just a demo!

Everything here should be rather straight forward. We have two text boxes, and they bind to the personal details object on the component. Then we have a next button that routes to our (future) address details component. This link obviously won’t work right now, and will actually break everything if you try and view it! Grrr!

What we need to do is first create the AddressDetails component by going

ng generate component AddressDetails

Then we need to open up our app-routing.module.ts file, at the top will be a const of routes that will (probably) be empty right now. Change it to the following :

const routes: Routes = [
  { path : '',   component : PersonalDetailsComponent }, 
  { path : 'addressdetails',   component : AddressDetailsComponent }, 
];

This then wires up our two components, the first will be on the homepage, and the next will be at /addressdetails.

Run a quick ng serve, and we should end up with something like :

It’s not pretty, but it works! Click Next will take us to our AddressDetails component which is actually empty. So let’s fix that!

Address Details Form Build

We’ve already generated our AddressDetails component so that we could route to it, so let’s just fill it out.

Our component definition should look like so :

export class AddressDetailsComponent implements OnInit {

  addressDetails : AddressDetails;

  constructor(private formDataService : FormDataService) { 
    this.addressDetails = formDataService.addressDetails;
  }

  ngOnInit() {
  }

}

And the actual HTML of the component should look like :

<table>
    <tr>
        <td>Full Address</td>
        <td><input type="text" [(ngModel)]="addressDetails.fullAddress" #fullAddress /></td>
    </tr>
    <tr>
        <td><input type="button" value="Back" routerLink="" /></td>
        <td><input type="button" value="Complete" /></td>
    </tr>
</table>

Now we could go ahead and deep dive this code but I think it’s pretty self explanatory. In our component we load out the FormDataService which is actually the exact same instance we used in the PersonalDetails component (Infact we could access the PersonalDetails model if required here), and then we display a simple form bound to the AddressDetails model.

Now the most important think to notice is that if we run our solution and test it. We can type in our personal details, press next, enter in our address details, but then press *Back*. Our Personal Details are re-loaded out of our shared service and pre-populated into the form! We haven’t had to do some crazy loading/unloading of models into our form, simple data binding does the magic for us.

In the next part of this series, we will look at how we then post our data to an API, and some tips and tricks working with larger multi step forms.

 

This article is part of a series on creating multi step form wizards in Angular.

Part 1 – Basic Setup
Part 2 – Building Our Forms
Part 3 – Tying It All Together


I recently came across a question on social media asking what the best way to create a “multi stage” form wizard in Angular would be. Now multi stage might be one word for it, but I’ve also seen it called multi step, multi page, multi form, hell even just “form wizard”. But they all roughly mean the same thing – a big long form that should be done in one sitting, but is broken up (often into bite size sections) across multiple “pages”.

The solutions on social media mostly involved complex third party libraries, like piping results around using rxJS, or creative use of reactive forms in Angular etc. I might be showing my age here… But I’ve built multi step forms in the exact same way since Angular 1.6. Using a shared service to hold the form “state”, and simply sharing that service between different forms/components. I’m going to outline that solution here in a very simple way so that (hopefully), you can follow on and realize that while Angular can be powerful, it can often handle complex scenarios with very non-complex code.

Project Setup

The first thing we need to do is create a brand new project for the walkthrough. Using Angular CLI we can run our standard angular new project command :

ng new multistageform

Make sure to select “Yes” when asked if I wanted to add Angular Routing as we need this to route between different steps of the form.

Inside our app.component.html we want to replace the default content in here with :

<h1>My Multistep Form</h1>
<router-outlet></router-outlet>

This will be the starting point for our form. In a real world scenario we would probably go with some sort of nested routing strategy, but for our first cut, let’s make things simple! Fire up our angular serve command in the CLI :

ng serve

And we should be able to browse to localhost:4200 and be greeted with our project all nicely set up!

Shared Service Setup

The secret to making this multi step form work is a shared service that can hold “state” as we click next throughout the form. Go ahead and run the following CLI command¬† to generate a new service called “FormData”. I personally like throwing all my services into a services folder – it just makes things a bit easier to find.

ng generate service services/FormData

This should create a new folder called services in your app directory, and inside it should be form-data.service.ts. Also note that it’s decorated with the following attribute :

@Injectable({
  providedIn: 'root'
})

This just happens by default but it’s actually incredibly important to what we are doing. The providedIn : ‘root’ property tells Angular that the service should be created at the root level, and re-used for every component/service that requests it. In simple terms, our service will be a singleton. It will be created once, and that instance will be reused everywhere. This is super important for us because as we step through the form, we want to “share” data between steps and right at the end be able to grab all the data at once.

Let’s create a model to hold some data.

ng generate class models/PersonalDetails

This will generate a class to hold the “personal details” step of the form – just a first/last name for now. Replace the contents of your newly created class with the following :

export class PersonalDetails {
    firstName : string;
    lastName : string;
}

Go ahead and do the same and create an AddressDetails model

ng generate class models/AddressDetails

And fill it with the following class definition

export class AddressDetails {
    fullAddress : string;
}

Let’s head back to our FormDataService as we need to add references to our two new models.

There’s a few different ways we could go about this, we could do it with methods, properties, or just plain public variables. For now let’s just go with public variables. We will also want to “reset” our variables in the constructor which essentially means that on page load, we have an “empty” form.

So with all that in mind, our FormDataService should end up looking like :

@Injectable({
  providedIn: 'root'
})
export class FormDataService{

  personalDetails : PersonalDetails;
  addressDetails : AddressDetails;

  constructor() {
    this.personalDetails = new PersonalDetails();
    this.addressDetails = new AddressDetails();
   }
}

That’s all we will be doing with the service for now as we jump into actually building out our forms!

Following along so far? I’ve broken up the tutorial into bite sized chunks so it’s a little less daunting. Check out the next part of this series where we build out our multi step form with some very simple HTML and Angular components.

Angular 9 was released on Februrary 7th, 2020. Generally speaking, this isn’t a flashy release with lots of goodies, but instead a release that gives a huge (needed) update to plenty of behind the scene components.

Angular Ivy

Angular Ivy is the name given to Angular’s new compilation and rendering pipeline. Essentially when you build and package your Angular app, the HTML, JS and CSS you have written is all compiled and packaged up to be delivered to a users browser. While the way you write code doesn’t change, the way Angular builds thing has changed dramatically without you having to do anything. This results in :

  • Faster build times (Which is massive if you do any sort of git pre-commit hook using ng build!)
  • Smaller build package sizes (Less to deliver to the client results in your page loading faster)
  • Better understanding of how modules fit together unlocks better tree shaking, ability to lazy load components etc.
  • Improved CSS and style binding

And a tonne more!

Probably the most exciting thing to me are the first two. Faster build times is huge to me as I like to do a full build before checking any work in just to make sure everything is playing nice, but the slow down in commiting even a one line change is pretty big right now. Secondly, the smaller build packages are pretty amazing. There is this official image floating around that demonstrates the difference :

40% size decrease!? Sign me up!

What Else?

I get that Ivy maybe isn’t the most exciting thing in the world if you were looking to get your hands on something new and shiny. Angular 9 does have a bunch of bug fixes and deprecations, but nothing new that will completely blow you away. In terms of methods being deprecated, you can see the full list here : https://angular.io/guide/updating-to-version-9. Most notably are things like Renderer becoming Renderer2, and the <ngForm> tag becoming <ng-form>. Nothing too spectacular.

Upgrading

To update your existing application to Angular 9, simply run :

ng update @angular/cli @angular/core

Let’s be honest, it’s pretty common that when your pipe isn’t running how you think it should in Angular, you can sometimes just tack on the “pure : false” tag like so

@Pipe({
  name: 'myPipe', 
  pure : false
})

And you just hope for the best. But this actually has severe consequences for your application, and in some cases can grind your entire application to a halt. It’s also extremely easy to end up with infinite loops or memory issues as an impure pipe can easily end up running far more often than you realize. But let’s rewind a bit, what’s this “pure” business about anyway?

Pure Pipes

A “pure” pipe (Which I have to say, I don’t like the naming.. It’s not that intuitive…), is an Angular Pipe that only runs when the underlying variable value changes. So for example if I had the following

{{ myVariable | myPipe }}

Then myPipe would only run when myVariable changes value. This typically means on load, and then anytime that variable is touched. But there is a small caveat. Let’s say for example I have a variable that looks like so :

myVariable : any = { propertyA : "foo"};

And then I am piping my variable as normal

{{ myVariable | myPipe }}

What happens when I do the following?

myVariable.propertyA = "bar";

Does the pipe run again? The answer is actually no. The easiest way to understand this is that it’s only looking if the top level value of the variable changes. It does not look at child properties at all. The only way for this pipe to be run again is to change the entire instance of myVariable like :

myVariable = { propertyA : "bar"}

But that’s somewhat impractical. You can’t be rebuilding the entire object every time just so a pipe can run. And you may even be trying to pipe an object you have no control over how it’s being set. So that’s where impure pipes come in.

Impure Pipes

Introducing Impure pipes, you can make *any* Pipe impure just by setting the pure flag to false in your declaration :

@Pipe({
  name: 'myPipe', 
  pure : false
})

Now instead of running every time the value changes, it runs often, *much* more often. Specifically it runs every digest cycle which is essentially Angular’s internal loop. Generally speaking, you may be running the pipe every time you move your mouse or use your keyboard. There’s a couple of issues this may cause :

  • You are now running code irrespective of changes to the underlying data, meaning there is a lot of time wasted doing unneeded work.
  • Depending on how heavy your pipe is, you could slow down your app trying to process work that doesn’t need to be done.

The second point is important. If your Pipe is doing something with a large piece of data, for example sorting a large array, it’s impractical to be doing this every digest cycle.

You’ll even notice this little tidbit from the Angular documentation around the lack or filter/orderBy pipes in the framework :

Angular doesn’t provide pipes for filtering or sorting lists. Developers familiar with AngularJS know these as filter and orderBy. There are no equivalents in Angular.

This isn’t an oversight. Angular doesn’t offer such pipes because they perform poorly and prevent aggressive minification. Both filter and orderBy require parameters that reference object properties. Earlier in this page, you learned that such pipes must be impure and that Angular calls impure pipes in almost every change-detection cycle.

Filtering and especially sorting are expensive operations. The user experience can degrade severely for even moderate-sized lists when Angular calls these pipe methods many times per second.

So as a framework, Angular has gone to pains to point out that even pure pipes should be lightweight and try and do as little heavy lifting as possible. Let alone if you are doing impure pipes.

A good trick to get into is to just add a simple console.log inside your pipe to see how often it’s being run, the results may blow your mind and make you think twice about switching to impure.

Good Examples Of Impure Pipes

For good examples of impure pipes, we can look at which pipes in the framework are marked as impure. These are :

  • JsonPipe
  • SlicePipe
  • KeyValuePipe

Key to all 3 of these pipes are that they are working on objects, not primitive values (So require Impure pipes to detect “deep” changes), and all of them do a very simple process to output the data. For example the JsonPipe simply does a stringify on an object (Essentially a one liner). It doesn’t mean that these are particular performant and should be used everywhere, but they are a good example of “when you have to”.

As an example of the absolute worst thing you could do would be to make an HTTP Call from an Impure pipe. This will surely result in thousands of HTTP calls to an API and your page grinding to a halt.

Using Input Parameters Instead Of Impure Pipes

There may be times where you need to pipe a particular object, but within that object you are only using a couple of properties to derive the pipe output. You can get around having to use an impure pipe by instead using input parameters on your pipe. Using our object from earlier :

myVariable : any = { propertyA : "foo"};

We can then create a pipe that looks like so :

@Pipe({
  name: 'myPipe'
})
export class myPipe implements PipeTransform {
  transform(myVariable : any, inputParam : any): string {
    return inputParam;
  }
}

In my HTML I can then call the pipe like so :

{{ myVariable | myPipe:myVariable.propertyA }}

The pipe will run when myVariable changes *and* when propertyA changes. You don’t even have to use the parameter (Or the initial input variable) inside the pipe, but you can still use them to “trigger” the pipe. This can also be handy when you need the pipe to trigger based on another objects parameter. This can feel hacky at times and if your pipe is lightweight enough, it can be simpler to just to go impure, but it’s an option if you don’t want things firing multiple times per second.

There’s going to be a couple of assumptions for this guide on adding App Insights to an Angular app. The biggest of all is that you are familiar with the Application Insights product itself. Maybe you’ve used in an another app before, maybe in a C# backend application or maybe a React/Vanilla Javascript app. But the biggest thing is that you know what it does and how to create an instance in the Azure Portal.

So with that out of the way. Why use Application Insights at all in an Angular App? The biggest win of all is that it can be used to track every application error thrown by your application, both handled and unhandled. And the second is that it can be used to track pageviews of users as they move through your SPA, which can then be used to track navigation paths, where users drop off in your sign up process, how your pipelines perform etc.

With all that said and done. Let’s jump right into it.

Installing Application Insights Libraries

The first thing we need to is install the following NPM package

npm install @microsoft/applicationinsights-web --save

Now this next piece of code is going to look big but it should be easy to understand. We want to create an “ApplicationInsightsService” that can handle logging exceptions, setting the logged in user, and tracking page views. The service contents will look like so :

import { Injectable } from '@angular/core';
import { ApplicationInsights, IExceptionTelemetry, DistributedTracingModes } from '@microsoft/applicationinsights-web';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class ApplicationInsightsService {
  private appInsights : ApplicationInsights;

  constructor(private router: Router) {

    this.appInsights = new ApplicationInsights({
      config: {
        instrumentationKey: "YourKeyHere"
      }
    });

    this.appInsights.loadAppInsights();
    this.loadCustomTelemetryProperties();
    this.createRouterSubscription();
  }

  setUserId(userId: string) {
    this.appInsights.setAuthenticatedUserContext(userId);
  }

  clearUserId() {
    this.appInsights.clearAuthenticatedUserContext();
  }

  logPageView(name?: string, uri?: string) {
    this.appInsights.trackPageView({ name, uri});
  }

  logException(error : Error){
    let exception : IExceptionTelemetry = {
      exception : error
    };
    this.appInsights.trackException(exception);
  }

  private loadCustomTelemetryProperties()
  {
    this.appInsights.addTelemetryInitializer(envelope => 
      {
        var item = envelope.baseData;
        item.properties = item.properties || {};
        item.properties["ApplicationPlatform"] = "WEB";
        item.properties["ApplicationName"] = "My.Application.Name";
      }
    );
  }

  private createRouterSubscription()
  {
    this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event: NavigationEnd) => {
      this.logPageView(null, event.urlAfterRedirects);
    });
  }
}

So a couple of notes :

  • LoadCustomTelemetryProperties can be used to set “custom” properties inside ApplicationInsights. This is handy to name your app, or pass through specific information that isn’t normally captured by AppInsights.
  • CreateRouterSubscription allows us to listen for navigation events and then log these as pageviews. By default AppInsights only logs full page refreshes so you will need this if you are using the internal Angular router.
  • LogException can be used to log exceptions, but you need to inject this service manually for it to be of any use (We will look at that shortly).
  • The @Injectable attribute has been told that the provider is for the root, this means there will only ever be one instance of this service for your entire app (Singleton).

Error Handling

So in theory the Application Insights javascript packages should catch all unhandled errors. But in reality Angular actually catches any internal errors (for example a bug in your code), and has it’s own way of handling them. This kicks in well before AppInsights as a chance to see the error, and so you won’t actually see your exceptions being logged to AppInsights at all!

Let’s fix that. We want to create an ErrorHandler implementation that does nothing but log the exception to AppInsights, and print out to the console (If we want to). The code looks like :

import { ErrorHandler, Injector, Injectable } from '@angular/core';
import { ApplicationInsightsService } from './application-insights.service';

@Injectable()
export class ApplicationInsightsErrorHandler implements ErrorHandler{

  constructor(private injector : Injector)
  {
  }

  handleError(error: any): void {
    this.injector.get<ApplicationInsightsService>(ApplicationInsightsService).logException(error);
    console.log(error);
  }
}

Now I know the use of Injector here is a bit flaky, but there is a bit of reasoning behind it. I found that when dealing with exceptions, if they were issues with the error handler or the AppInsightsService itself, I ended up in infinite loop territory when trying to inject things in normally. The use of Injector isn’t ideal, but it works and typically broke out of loops before hitting max callstack exceptions.

In our NGModule, we then want to create a provider for our error handler :

@NgModule({ 
  declarations: [
	...
  ],
  imports: [
	...
  ],
  providers: [
    ...
    { provide : ErrorHandler, useClass : ApplicationInsightsErrorHandler},
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

We use the token of ErrorHandler so Angular knows that we want to use this particular class for handling all errors. And that’s it!

Using Distributed Tracing With CORS

If you are attempting to setup distributed tracing with CORS (That is your API is something like api.mydomain.com and your front end is mydomain.com), then there is some more mucking about to do before you get there. It’s a headache, I can assure you.

The first is that CORS is not turned on within the App Insights Angular library by default. To do so, in our ApplicationInsightsService we want to pass in an extra flag when creating our ApplicationInsights object :

this.appInsights = new ApplicationInsights({
  config: {
	instrumentationKey: "YourKeyHere", 
	enableCorsCorrelation : true
  }
});

Next you need to set up your backend app for CORS. Now this will be different depending on what language you are using. My suggestion would be to google “YourLanguage Setup CORS” and follow the steps from there, then right at the end you need to look how to set up “ExposedHeaders”. We need to expose the header “request-context” otherwise the token AppInsights uses to link up requests is not passed back and forth.

As an example, in C# .NET Core, it would look like :

app.UseCors(x =>
    x.AllowAnyOrigin()
        .AllowAnyHeader()
        .AllowAnyMethod()
        .WithExposedHeaders("request-context")
);

Only then will your application pass the distributed tracing tokens back and forth.

Obviously you will also need to wire up Application Insights for your backend application which will completely depend on which backend language you are using. But almost all “support” distributed tracing out of the box, just not using CORS.