Check out our Angular Book Series.

Why won't my Observable Trigger in a Unit Test?

I've been writing some tests as part of a project I'm working on, and for some reason I could not get a mocked Observable to resolve. This will explain the mistake I made and how to fix it.

The Setup

This component used a resolver to load data before the component loaded. To access a resolver's data, you inject the activated route into the constructor, like this:

constructor(private route:ActivatedRoute){}

In the ngOnInit(), you'd subscribe to the data property:

ngOnInit(){ {myValue}){
this.myValue = data.myValue

This saves your MyValue data from the resolver into the local component instances myValue.

Writing The Tests

First, I mocked the ActivatedRoute:

class ActivatedRouteMock {
data: Observable<Data>;

Then, I created an instance of it:

const activatedRoute = new ActivatedRoutMock();

As part of the TestBed's providers:

{ provide: ActivatedRoute, useValue: activatedRoute}

The first test I wrote was to make sure the subscribe was actively working.

First, I created the observer and component:

const observer;
beforeEach(() =>
{ = Observable.create (observer) => {
observer = observer;
spyOn(, 'subscribe');
component = TestBed.createComponent(myComp).componentInstance;

Then, I ran the test:

it('should subscribe to activated route', () =>

This worked great. Now, I wanted to test to make sure that other methods inside the component's result function worked. To do that I'll have manually trigger the observer:

it('should resolve route data and save myValue'. ()=>
const myValue = "something";
const results = {};
results['myValue'] = myValue;;

This should work, right? Nope, it failed ever time. The observer was always null. I was scratching my head and adding a lot of breakpoints and outputs trying to figure out what I had done wrong so far.

What is wrong

The function to create the observable is never run until the observable is subscribed to. Clearly we are subscribing to it in the component code: {myValue}){
this.myValue = data.myValue

So, why doesn't it run? Think about it first, because spoilers are below.

The spy is getting in the way:

spyOn(, 'subscribe');

Because of the spy in place, the subscribe() function is intercepted, and as such never run, which never runs the function in the Observable's create function, which never saves the Observer. The solution was simple once I figured out what was going on:

spyOn(, 'subscribe').and.callThrough();

Tell the spy to intercept and watch, but still allow the call to go through.

Everything started working wonderfully. :-)

How do I switch between different NG Material Button Types?

ng-materal provides a bunch of button variants. Each button type is an HTML button that offers identical functionality, but with slightly different designs and colors. Here is an example of two buttons:

<button mat-flat-button>My Button 1</button>
<button mat-stroked-button>My Button 2</button>

If you drill into the button class, you'll see that all the button variants are implemented in the same code base, as directives.

I was doing a code review on a current project and saw that the code was conditionally determining which button type to display:

<button mat-flat-button *ngIf="condition">My Button 1</button>
<button mat-stroked-button *ngIf="!condition">My Button 1</button>

I was bugged by the fact that we were implementing two button components in our code for what was essentially a style change. That's when I started digging into the specific implementation and discovered that the primary difference between a mat-flat-button and a mat-stroked-button was style changes.

I proposed this alternate approach:

<button mat-button [ngClass]="condition?'mat-flat-button':'mat-stroked-button'">My Button 1</button>

We use the ngClass directive to conditionally flip the style between the flat-button and the stroked-button. It solved our issue with less code.

How do I display a Calendar Icon as part of the NG Bootstrap DatePicker?

I'm working on a project that uses ng-bootstrap, an Angular Library based on Bootstrap styles. I'm using the DatePicker and set it using their samples as a guide.

This is what I want to see:

But this is what I see:

Where is the fancy icon?

The CSS to create that graphic button is not in their base CSS for some reason. In past versions I've used an image. This time it takes some CSS Magic:

button.calendar, button.calendar:active {
width: 2.75rem;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAcCAYAAAAEN20fAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAEUSURBVEiJ7ZQxToVAEIY/YCHGxN6XGOIpnpaEsBSeQC9ArZbm9TZ6ADyBNzAhQGGl8Riv4BLAWAgmkpBYkH1b8FWT2WK/zJ8ZJ4qiI6XUI3ANnGKWBnht2/ZBDRK3hgVGNsCd7/ui+JkEIrKtqurLpEWaphd933+IyI3LEIdpCYCiKD6HcuOa/nwOa0ScJEnk0BJg0UTUWJRl6RxCYEzEmomsIlPU3IPW+grIAbquy+q6fluy/28RIBeRMwDXdXMgXLj/B2uimRXpui4D9sBeRLKl+1N+L+t6RwbWrZliTTTr1oxYtzVWiTQAcRxvTX+eJMnlUDaO1vpZRO5NS0x48sIwfPc87xg4B04MCzQi8hIEwe4bl1DnFMCN2zsAAAAASUVORK5CYII=') !important;
background-repeat: no-repeat;
background-size: 23px;
background-position: center;

The image is no longer external, but created in-line. In my Angular project, I added this to the main styles.css to solve the problem.

How do I access Remote Services from the Angular CLI Dev Server?

I have been working on re-writing my Angular books for Angular 7. Along the way, I Decided it is time to finally ditch the build scripts for Angular that I wrote and move the text over to the Angular CLI. The Angular CLI has become a standard so it makes sense to base the books on that.

As part of this, I had to get the local dev server, localhost:4200, to load services from remote servers. I had to set this up for each separate service layer in the book. Thankfully Angular CLI includes proxy support for its server. That just means whenever the localhost:4200 makes a service request to a specific URL, I can redirect it to a different server where the real services lie.

When my UI code accesses:


I want to redirect it to:

Coldfusion, Java, PHP, and NodeJS will not be running as part of the Angular CLI Dev server, so this allows me to keep services separate from the UI code, but still develop them together. For the purposes of this article, I'll show you how I set up the proxy for the ColdFusion services, however the same principles apply for whatever services you want to access.

Create the Proxy File

The first step is to create a proxy.conf.js file. First create a proxy-conf.js file and create a PROXY_CONFIG variable:

var PROXY_CONFIG = [{ }]
module.exports = PROXY_CONFIG;

The PROXY_CONFIG object is an array of different redirects. For this article, only one object is listed, which I'll use to define the redirect for the ColdFusion services.

Fist, I'll add the context:

context: [

The context tells the server-side proxy to look for all calls to coldFusion and to process them. Next I'll add the target:

target: "",

The target tells us which server should be redirected to. Since I'm directing to a different server, I need to make sure to set the changeOrigin property to true:

changeOrigin: true,

You won't need this if your services also reside on localhost. Next set secure to false:

secure: false,

I never set up HTTPS certificates on my local environment for testing purposes, which is why this value is set to false.

Finally, I added a path re-write:

pathRewrite: {
"^": ""

This is because a request to localhost:4200/coldFusion actually needs to redirect to The path rewrite rules affect this.

One thing that was very helpful when I was debugging this was setting the log level:

logLevel: "debug",

This provides a lot of details in the console. It took me some trial and error to get this working.

Tell Angular about the Config

Open up your angular.json file. Find projects.yourproject.architect.serve.options. It'll probably look something like this:

"options": {
"browserTarget": "lw:build",

Add a proxyConfig value to this options object so that Angular CLI knows to load the proxy config file:

"proxyConfig": "proxy.conf.js"

Now you can shut down your app, re-run ng serve and you should be good to go.

How can you listen for a Browser Event in Angular?

This question recently came up in StackOverflow, and I thought I'd cross post my answer because I think I nailed this one.

The poster wanted to listen for an event in Angular. In the bulk of cases, I would do this in your HTML:

<button (click)="eventHandler($event)">

And this inside your component method:


It is simple, well documented, and Angular already 'wraps' the bulk of events dispatched up from your HTML page.

However, the poster really wanted to access the eventsin TypeScript. This is doable, but becomes a bit more complex.

First, add a #value to the HTML element in your HTML Template:

<button #myButton>

The #MyButton syntax allows you to reference the child in code using the @ViewChild metadata:

myButton: ElementRef;

Then you should be able to call the methods on the native element to access the event:


If at all possible, I try to avoid drilling down into the ElementRef like this. I think I did it once when I created a reusable toast style component for a client, but for normal development I stick with the event directives.

Angular 7 is out, learn all about it here!

Angular 7 is out.. Along with it, I updated all the books in the Learn With series.

This is a major update to the book text, because I finally ditched the SystemJS infrastructure I created in the Angular 2 days, in favor of the more popular Angular CLI. The Angular CLI has become a standard Angular dev tool, and the formal Angular docs and samples do not use the SystemJS approach at all anymore.

Get your updated Books here, and use the discount code LaunchDayGiftFromJeffry to get 25% off when you buy straight from us:

I put together a brand new demo of the app that the book teaches you to build if you want a video reminder of what is going on.

Why aren't Styles working with my Angular 6 Build?

I was working on an Angular 6 project that recently ran into a problem. All our styles were messed up when we created a production build. There are a lot of complaints about it here.

There seem to be two solutions that work for us and I'll go over both of them.

Move the Styles

The first solution is to remove all your style imports from the Angular.json. Then add them back into the main styles.scss using @imports. So, my Angular CLI styles looks like this:

"styles": [

Open up the styles.scss and add them as imports:

@import "../node_modules/bootstrap/dist/css/bootstrap.css";
@import "../node_modules/@swimlane/ngx-datatable/release/assets/icons.css";
@import "../node_modules/@swimlane/ngx-datatable/release/themes/material.css";

The styles would now change to this:

"styles": [

This worked. I actually think I like putting the styles in the main styles.scss instead of the Angular.json. I prefer to stay out of the Angular.json as much as possible.

Change Extract CSS Value

The second option, and the one in which we chose to do for this project, was to change the extractCss value from true to false. Inside your Angular.json find the value:


You'll find the value at

Change it to:


Now open up your package.json and find the build prod command:

"prod":"ng build"

Add the build-optimizer argument:

"prod":"ng build --build-optimizer"

This should address the issue.

When you create a normal build, the styles are minimized into a JavaScript file--styles.js--and then loaded on demand by Angular as needed. When you use extractCSS, the files are combined into a single CSS file instead of being created in a js file. Part of the minimization process seems to be screwing up the order that files are compressed, which of course affects the final CSS and why our styles were not showing up correctly.

This caused a few grumblings among my team about how borked Angular CLI is, but I still enjoy working with it.

How do I sort two ng-material table instances on the same component?

I have been doing some prototype work with the ng-material's table component. The table component is, basically, a DataGrid.

As part of this proof of concept work I put two separate tables inside the same ecomponent. The code worked well enough, but I had trouble getting both tables to sort.

To get a table to sort you need to add a ViewChild reference to the MatSort. In the HTML:

<table mat-table [dataSource]="rowData1" matSort >

Then you get a reference inside the component code:

@ViewChild(MatSort) sort: MatSort;

And attach the two together:

ngOnInit() {
this.rowData1.sort = this.sort;

The my missing magic from last week's post.

There is a problem once you add a second table. First create the two tables:

<table mat-table [dataSource]="rowData1" matSort >
<table mat-table [dataSource]="rowData2" matSort >

Then get the ViewChildren:

@ViewChild(MatSort) sort: MatSort;

@ViewChild(MatSort) sort2: MatSort;

This will cause issues, because both variables are pulling the same MatSort value and only the first grid will sort.

The way to solve this is how you mark the table to get the matSort value:

<table mat-table [dataSource]="rowData1" matSort #sort1="matSort">
<table mat-table [dataSource]="rowData2" matSort #sort2="matSort">

Now get the ViewChildren references like this:

@ViewChild('sort1') sort: MatSort;

@ViewChild('sort2') sort2: MatSort;

And associate the sort element with the data source:

ngOnInit() {
this.rowData1.sort = this.sort1;
this.rowData2.sort = this.sort2;

Now both grids should sort properly.

Five Reasons My ngMaterial Table won't sort!

I've been doing some prototype work with the ngMaterial grid and had a problem where the grid would not sort. Here are a few things to check if this happens to you.

  1. Import the MatSortModule Module: Be sure that your @NgModule definition includes the MatSortModule:

    declarations: [
    imports: [
    bootstrap: [AppComponent]

    Without this, the sorting will not work.

  2. Specify the matSort header: Be sure to specify the matSort header on your table grid:

    <table mat-table [dataSource]="rowData" matSort class="mat-elevation-z8"

    // rest of the table definition here

    Without that you won't be able to click on the headers.

  3. Wrap Your Data Source in a MatTableDataSource: If you do not wrap your own datasource--probably an array--in the MatTableDataSource class you'll have to write your own sorting algorithm to affect your data because it won't work out of the box.

    this.rowData = new MatTableDataSource(myRowDataArray);

    Do this because it makes your life easier.

  4. Tell the data source about your sort: Your MatTableDataSource does not know about the sort by default. Get a ViewChild instance to the sort in your code:

    @ViewChild(MatSort) sort: MatSort;

    And apply that:

    ngOnInit() {
    this.rowData.sort = this.sort;

    Hopefully you got this far and your table is sorting now.

  5. Write Your Own Sort: If you're avoiding using the MatTableDataSource for some reason, you'll have to write your own sort algorithm. In the HTML, listen for the matSortChange event:

    <table mat-table [dataSource]="rowData" matSort class="mat-elevation-z8" (matSortChange)="onMatSortChange()">
    // rest of the table definition here

    And in your code:

    // do something to modify your data source here.

I've found the documentation lacking for ngMaterial, but so far we plan on plunging ahead with it. Hopefully this helped someone out.

How does the HTML5 Pattern Attribute work?

I came across a question on StackOverflow about how to use Angular to restrict input to capital letters. Back in my Flex days, I'd use the restrict attribute for that, but I've never had to do that for HTML5.

I did some digging and found that HTML5 introduced a pattern attribute. I thought this is probably exactly what is needed and Angular doesn't need to get involved at all.

I threw together a quick sample.

<input type="text" pattern="[A-Z]*" name="sampleinput" />

Unfortunately, that wasn't nearly as helpful as I thought it might be. It does not restrict input, only gives guidance. In Firefox, it will turn red if you enter invalid characters:

If we change to all caps, the Firefox red warning goes away. A nice visual queue, but it does not restrict the input like I wanted.

Chrome on the other hand provides no feedback:

I didn't continue testing in different browsers, but I imagine there is similar inconsistencies.

You can control the error message, but using the title attribute, and even write your own code against an invalid event.

As best I can tell, there is no HTML5 way to restrict the input into a text field. But, after some searching, I found a few ways to do this with Angular, most involve adding a validator on the input.

You can also use CSS to force the text to uppercase:

<input type="text" style="text-transform: uppercase;" name="sampleinput" />

However, that won't prevent the user from entering numbers.

More Entries

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version