Material Design Notifications for Angular2+

Astonishingly, I haven’t found a good reliable library to display material-design style notifications in Angular2. So I have created this library, it can be found here:

It’s super easy to use, yet flexible. Material design is optional. The Material Design library is not required for this library to work!

You can edit styles like box-shadow, position, background or color. There are also some defaults, such as success or error.

I hope you enjoy it!

Typescript on the Server

During the past few weeks I’ve been working on a Typescript MEAN seed-application (Mongo-Express-Angular-NodeJS). I gave it some more thought today. Why is no-one else doing something like this? I mean the frontend is stuffed with Javascript frameworks. You can choose between Angular2, React, VueJS or many others. In the backend world we also have frameworks to choose from. You have Django for Python, Spring for Java or Play for Scala. But there isn’t anything anywhere near of being a framework in Typescript or for that matter, neither in Javascript. Hasn’t nodejs been somewhat of a hype now for a while? Why hasn’t anyone built a substantial framework for this?

For example the tech giants, Google and Facebook, they aren’t interested at all in typescript / javascript server side applications? They took the time to battle against each other with React and Angular2, but don’t want to claim the server side JS/TS framework throne? There’s this big discussion going on “omg node is so amazing for servers, it’s non blocking and so amazing” but no one cared enough to write a substantial framework? I know ONE framework that extends all the way front to back in JS and that is Meteor. Unfortunately it doesn’t do the best job in separating front and back and it’s a bit too much magic for me, so I’d like to see a pure server side framework written in typescript.

So if I’m asking the question “why hasn’t this happened yet”, I’m inferring that there are some benefits of using typescript in the backend. The benefits to me are first and foremost:

  • One language everywhere
  • Package management with npm
  • Vibrant open source community
  • Typescript is a good and flexible language

But of course there are also downsides of javascript on the server. What I see is:

  • Dynamic, so it’s slower
  • Dynamic, so it’s less well documented
  • Javascript is a weird language
  • Breaking changes all the time in all the packages / frameworks / things

So is the answer to the question just “Why throw out the good old solid backend for a weird language, just so we have it everywhere?!”. But then again, with typescript it’s not really weird anymore. And if the problem would be with dynamic, there wouldn’t be a python framework either. The point with the most weight here for me is that everything is constantly changing at neck-breaking speed.

There’s also the option “frameworks suck, we can just stich together libraries, that’s much more modular anyways”. Well, if that’s the case, then there’s still the question why there are frameworks for other languages but not for typescript. Apart from that, the host of libraries isn’t really baffling either.

What I see as more likely is that there just hasn’t been enough time to develop such a backend framework using typescript. I forecast, that in some years one of the larger companies will have built such an open source framework for a typescript server. Just who will it be? I think most existing big companies would have too much migration cost at too little gain, but maybe some startup somewhere, right now, decides to write a backend in typescript, and will write the first lines of this framework… We’ll see in 2023.

How to write a typescript library

I was a bit annoyed when googling for the topic. After a while when I had scratched together all the information, discarded the outdated one and inserted the missing bits, I decided to spread the knowledge. I went forward and created how-to-write-a-typescript-library.com! Check it out.

You can also skip the tutorial and find the final demo library on github under https://github.com/bersling/mylib, but I’d really recommend reading the tutorial or at least skimming the tutorial!

A short summary, sort of just like the ‘diff to a normal project’ would be this:

  • Add declaration: true to tsconfig.json
  • Export public parts via index.ts
  • Create a package.json, with the name your library should later have
  • Configure .npmignore
  • run npm publish

 

Building the TS MEAN Stack — First Impressions

When I was looking for a cool starter project / seed / boilerplate or whatever you want to call it for the MEAN stack fully written in typescript, I found nothing really useful. So I started to create this seed myself. Here are my first impressions on this stack. The current result is hosted on github, free to use and reuse!
The MEAN stack was “a thing” once, but it got abandoned over time with Angular2+ coming along, rendering the old projects a bit overhauled. But why would anyone want to use the MEAN stack in the first place? For me, there has always been one big advantage with this stack: Only one language in the project. Now with the rise of Angular 2, this brings a bit of a mixup into the MEAN world. Most backend libraries for the Mongo-Express-Node part are written in Javascript, while most Angular 2 things are written in typescript. If we still want to have one language everywhere, we need to decide: Frontend Angular 2 in JS or backend in TS. Since I love typescript, for me the choice was easy. Typescript everywhere it was!

M — Mongo

I started out with the backend, since this had much more unknown factors for me. Using Angular 2 you’re backed by a lot of tutorials and Google supporting the framework, but with a TS Mongo-Express-Node backend, you’re a bit on your own. The questions I had were along the lines of “what is the tooling like?”, “can I run my unit tests with IntelliJ like I’m used to from JUnit?”, “for how many npm packages are there typings?” and “how reliable are those packages?”.
I started with the database layer, for which I found a Mongo Connector with typings. For unit tests I decided to go with Mocha and Chai. I placed the test files in the same directory as the source files and was able to run them from the command line like:

mocha --reporter spec --compilers ts:ts-node/register '**/*.test.ts

Of course, when project gets bigger you want to be able to run individual unit tests. This is possible with grep , which is somewhat cumbersome. However, after some hours I managed to get IntelliJ to run individual unit tests directly from the editor. Since then the development experience has improved drastically.
During the development of the database layer, I didn’t run into any major problems. I’m not the biggest advocate of MongoDB by the way, but the MEAN stack was an existing “brand” I could build upon. In any case, I would prefer an SQL database for any real web projects based my past experiences with Mongo. Here are my reasons why. In case you share this view, I also abused the “M” in MEAN to create a MySQL branch of the stack. I designed the database access interface in a way, such that the rest of the application doesn’t need to know whether it’s Mongo or MySQL backed. Modular design ftw. In any case, I’m going to maintain both branches in the future.

E — Express

The next part in the application was the “E”, the ExpressJS / ExpressTS. I set up some simple routings and a generic “CRUD router” that would allow you to create/read/update/delete any data using the url /api/v1/:resource/:id . Next I added a user model and authentication layer. A side note on the models: I first shared the models between frontend and backend, but this was too annoying since I always had to npm publish on every change and there wasn’t that much benefit since the models differed anyways. For example, the backend user also has a password stored and so on. For authentication I used PassportJS. I found it a bit confusing at first, how it’s directly used in the routing layer. I also used something called connector-flash related to passportJS until I noticed how hopefully outdated it was… I had a similar experience with the password hashing library. I first installed bcrypt and later had to switch to bcrypt-nodejs since bcrypt threw crazy errors on install. Luckily, I hadn’t used the bcrypt library directly in my code, but wrapped it with a small layer. Like this I could switch out the implementation (the library) easily and be proud of myself how masterfully I had programmed against an interface. But seriously, with all the package churn I would heavily recommend you this for your NodeJS project: Unless it’s a professionally maintained library, better wrap it so you can switch it out easily! Of course there are cases when it doesn’t make any sense, e.g. example you can’t just wrap the Angular interface, but Angular 1 -> Angular 2 is actually a good example of how f****d you are when your heavily-used-library-you-trusted becomes deprecated…

A — Angular

For the frontend itself, originally I didn’t plan to do anything, since it’s mainly the backend that was lacking typescript boilerplate, while Angular 2 has a nice CLI for scaffolding. But then I though, “well, you should at least demonstrate how your cool backend api is used”. And I set out to create a small frontend. I have to say I really love to work with the CLI since I’m a person who generates quite small components (“one for every button”) and this just makes it a whole lot easier. I had my shell scripts in Angular 1 that did this for me, but with the AngularCli it’s an even neater experience. Also, when it comes to bundling a production build it’s unbeatable. Simply being able to run ng build –prod is just amazing. I like Angular2 a lot in general. The only thing that I’m still not 100% happy with is the state management since everyone does it a bit differently and there aren’t really any best practices, but apart from that, there’s not so much I found to nag about so far. Well , there are a few pitfalls, but mostly stuff works as I’d expect it to do.

N — Node

Finally, having strapped all of those things together, a functional REST-API and a simplistic frontend I decided to host a demo of the app. It’s still constantly improving as I’m working on the project, but that’s what it is now. For deployment I chose to, again, completely separate the backend and the frontend. The frontend just consumes the backend through http://demo.tsmean.com:4242 . I think that’s a pretty cool setup, since like this you can also use the remote backend to locally develop your frontend. For example if you’re only interested in the frontend, go ahead and get the git repo of the frontend and use that REST Api to test against! The backend has to allow CORS requests that this setup works, but apart from that nothing had to be configured. The frontend itself is served by a 20-line node script (also using express).

Conclusion

Where does this all leave me so far? I’m still quite excited about the stack. I really love that there’s no context switching, that there is just typescript, typescript, typescript (and some html and css). There was one exception, I first tried to write my deploy script in typescript, that experience really sucked. The node-ssh package was buggy and it was just so much more complicated, so I switched back to a regular shell script. I have tried many deploy script implementations over the years (js, ts, python, java, …) and I always came back to the simple shell script. But back on topic. I like the stack so far, except that I prefer MySQL to Mongo for anything that should become a real project. But of course I can’t really say so far how this stack will behave on scale. I haven’t built a multi-million user web-app with it yet, as the “first impressions” in the title might suggest. However, I don’t see any reasons why you wouldn’t want to use this stack for your production project. I wouldn’t argue too much about performance, since your development hours will probably be worth much much much more than your server costs. I would neither choose nor discard the stack based on performance. I wouldn’t say “node is non-blocking, we have to use it!”, since you can also get non-blocking with Scala, Java and so on. And I wouldn’t say “JS is a dynamic language it’s so much slower than compiled Java”, since you could always outsource computationally heavy tasks to dedicated web services and buying an extra node server also won’t ruin you. More of my concerns come from “how’s the tooling” and “how stable are the packages”? There I’m somewhere in the middle. Of course the tooling isn’t as great as you’d get it with Java. I still find IntelliJ sometimes a bit on it’s limit with my project (it gets a bit sluggish), I don’t know why though. Also the small things, like having to import typings, which are sometimes missing some times, having to set up NodeJS & mocha support in IntelliJ etc etc cost you some time. On the other hand, managing front- and backend dependencies with npm (or yarn) is cool. It’s again this “just one system” thing that makes you more efficient and gives a clean feel to the project. Bottom line: I really like to work fullstack-typescript and will definitely continue to develop my boilerplate / seed / starter-package / whatever. I think it’s a perfect start for your application as it’s easy to get started with, but it’s also a great choice for any medium sized project. If your project is the next biggest-web-app-on-earth, it might still be too early to use the stack, but there could also be an opportunity in adopting it with the recent explosion of typescript usage.

Next steps

I’m currently working on improving the modularity of the system, so there’s really a mysql and a mongo module, and also authentication etc. is modularized. I’m doing this using typescript npm libraries, on which I’ve written a small tutorial how to build them trough the process at how-to-write-a-typescript-library.com.


I’d love to hear your thoughts on the matter. What are your experiences with fullstack typescript?

Pitfalls in Angular 2+

pitfalls

Angular 1 has been complex, intertwined and error prone. “Is what I’m doing updating my data?”, “Why doesn’t this work?”, “WTF is this?” or “GNARRRFL I wrote myObject instead of my-object again!!” might have been common things you have said developing an angular 1 app. So what about Angular 2? Is it all chocolate and honey bears from there on? The answer is no. There are still quite a few pitfalls you’ll have to be aware of. Let me warn you of some here.

Template Syntax

Angular now allows less in the templates. What’s most confusing is what may and may not go into bindings / expressions.

PITFALL 1: Javascript in templates is not really javascript!

We write template expressions in a language that looks like JavaScript. Many JavaScript expressions are legal template expressions, but not all.

I mean c’mon guys… Either it’s javascript or it’s not, but what’s that?

JavaScript expressions that have or promote side effects are prohibited, including:

  • assignments (=, +=, -=, …)
  • new
  • chaining expressions with ; or ,
  • increment and decrement operators (++ and --)

(and more)

ProTip from Angular how to dodge problems with this:

A property name or method call should be the norm.


Okay, now you think you know it all about the js in the view? That’s where you’re wrong. In “Statements” (the stuff from the round brackets ()), there’s yet another javascript like syntax that isn’t really javascript!

PITFALL 2:

The template statement parser is different than the template expression parser

meaning

()="someExpr" and []="someExpr" have different allowed "someExpr"

An example:

[blub]="x = 3" // totally not okay
(blubbl)="x = 3" // totally ok
(blarb)="console.log('hello')" // totally not okay

ooooomg…. Well, I’d say in this case still stick with the above recommendation (only use function calls) and you should be pretty fine. In any case, I mean it’s kind of logical that in events you want to assign stuff, but not in property bindings, so you won’t run into problems 99% of the time, but when you do, it might help you to recall those rules. But I mean seriously, why do you make 2 parsers, Angular Team? Haven’t you learned in Angular 1, that the more concepts you introduce the worse it gets? Why not just allow a property name or method call in both () AND []? Why also allow assignment in () , you really think it adds that much convenience to introduce a new concept?


Anyways, let’s move on.

PITFALL 3: Forgetting []

It’s such a common pitfall because this wasn’t required in Angular 1. Now it is.

As Angular states:

The HTML attribute and the DOM property are not the same thing, even when they have the same name.

This means <button [disabled]="isUnchanged">Save</button> will work, but <button disabled="isUnchanged">Save</button> won’t work as expected.

You can find more information here. Basically the quirky () [] syntax is justified in about 2000 words there.


 

And one more I recently stumbled upon: You can’t have single { in your templates. For example, if your want to describe some code and write:

if else statements work like this:
if (condition) { ... } else { ... }

in your template, Angular won’t like that. You can either escape each curly brace it in the most peculiar fashion:

"{{ '{' }}"

OR you could use the ngNonBindable directive!

Fortunately the Angular error report is good on this one, so even when you walk into the pit, you’ll get out fast.

CSS

I think it’s awesome how we can write css / scss in Angular 2: directly in the components and it’s not leaking around. The way it’s implemented is that Angular adds name-spacing to emulate shadow-DOM-like behaviour. Yet, this introduces some problems when changing elements outside of Angular, e.g. with jQuery or something like d3js. For example, if I replace <div id="my-chart"></div> with d3 rendered html, the styles don’t get applied. You now have two options. Option one: put the styles into the global styles.css file. Option two: prepend all styles with :host /deep/ .  See also this related stackoverflow answer. Of course that’s a bit hacky, but that’s how it is.

State Management and Data Binding

State management doesn’t have a magical solution in Angular 2 and still requires serious consideration and planning when you write your app. It’s a topic too big for this pitfalls-post, so here are some links to other posts concerning state management to get you started:


I’ll update this article constantly as I run into more pitfalls during development, so stay posted by subscribing!

State Management: ngrx/store vs Angular services

ngrx vs services

State management is one of the most difficult tasks in front-end development. In Angular2 we are presented with a number of options. The most promising ones seem to be holding reusable state in services vs. using the ngrx/store library specifically designed to help with state management. Here are my current views on the pros and cons of each approach.

Pros of using ngrx/store

  • You always know where all your state is
  • Everything is an observable => more flexibility to use stores
  • You get dev tools such as time-travel
  • It could become a standard
  • There are some examples

Cons of using ngrx/store

  • The examples don’t cover real world cases like having an actual database with items with ids.
  • Everything is an observable => more complexity in use
  • It could become an outdated library
  • Difficulty to learn
  • Name-spacing is ugly, e.g. '[heroes] UPDATE'.
  • Idea of immutability is nice but from the example //remember to avoid mutation within reducers. Having to remember is not so nice. It makes the reducers fragile and it’s easy to introduce sneaky bugs since nothing guarantees the immutability.

Pros of using services as your store

  • No extra library needed, it’s core Angular
  • Complete flexibility in use
  • You can have stores that aren’t observables
  • You can throw immutability overboard
  • No name-spacing problems as every resource has it’s own service

Cons of using services as your store

  • No-one tells you how to do it, no standards

Conclusion

I still prefer the manual approach with services. I think it adds a lot to the flexibility and simplicity that you can shape your data-store as you need it. Often you don’t need the entire store store to be an observable and you can easily extend your store-services to make them observables once you need that feature. For example I’d rather have a store with the signature

heroStore: {[heroId: string]: BehaviorSubject<Hero>}

than the signature

heroStore: BehaviorSubject<{[heroId: string]: Hero}>

As long as I don’t need something like the total number of heroes it’s completely sufficient to have the first signature. And in case I suddenly need the store as an observable in my app, I can still easily change the service.

Also the mistakes in the docs and an example-app that’s far from real-world scare me a bit. For me this shows too little dev power in a project too big to stem and a concept that’s not guaranteed to be ideal. I mean it’s an interesting idea to combine the principles of redux with observables, but maybe it’s a little overkill?

Please don’t use MongoDB (or any other NoSQL database) for your web-app.

There isn't a single good reason to primarily use a NoSQL database for your web-application. Click To Tweet

I’m going to crush all your arguments here. It’s a general argument against NoSQL in web-apps, but code is going to be mostly MongoDB-related, since that’s what I have the most experience with. Also note that I don’t say there is absolutely no use-case for a NoSQL database. I’m just saying your app should be backed by an SQL database to store things like your registered users and so on. In the unlikely event that you really have a special use-case, then use a separate NoSQL database for this, but don’t put your relational data in there too! So now let’s move on to the crushing.

 

“NoSQL can be faster than SQL because it doesn’t have to do table-joins”

That’s true, but there is a well known and understood solution to this problem. It’s called caching. Let me elaborate.

Let’s say we have to load the following view a gazillion times a day:

Display of Message Data-Structure

It’s similar to a typical forum which most webapps have in some form.

Then the argument for NoSQL would be that you could store everything denormalized as

{
  content: "bla bla"
  user: {
    name: "Jeremy Barns"
    ...
  }
  comments: [
    {content: "bla", user: {name: "Jonas Blue", ...}}},
    {content: "blarb", user: {name: "Jeremy Barns", ...}}
  ]
}

Now in our cool web-app we could fetch all the information we needed without any table-joins, just by extracting one document from the database. Super fast.

Of course, we’ve introduced a problem with this. We have the same user in multiple locations. So if Jeremy Barns decided to change his name, we’d have to update it on every message he ever made, a true nightmare. That’s why there are relational databases, so you can actually insert an id instead of the whole user, which solves a lot of consistency problems. Of course you could do the same with Mongo:

{
  content: "bla bla"
  user: 58e5ee14d37470005df49bcb
  comments: [
    {content: "bla", user: 50e5ee14d36470005cd66waf}},
    {content: "blarb", user: 58e5ee14d37470005df49bcb}
  ]
}

and then in your application code you query the Message and from the Message you query the users, but then it already looks awfully much like a relational database. And you still haven’t solved all problems with this. What if you now need a feature “delete a user and all of his related data”. Easy and consistent with a relational database. Impossible with NoSQL.

So you say “well, we’ve got to choose between speed and consistency!”. Wrong. Let’s say we implement the following data model:

interface Message {
  content: string;
  user: User;
  comments: Message[];
}

interface User {
  name: string;
  ...
}

where we use the same type “Message” for questions and replies. Now to build our view above one million time, would we have to do one million times all of those table-joins:

message -> user
message -> message -> user (n times, where n = #comments)

?

First of all, joins on properly indexed columns aren’t actually that bad. SQL databases have strongly optimised algorithms to make those joins fast. Second, we can still implement caching solutions, if the joins really pose a problem. Now I’m not saying caching is all that simple, cache invalidation is a topic for itself, but at least it’s a solution that holds water. Caching here basically means building something like the denormalised data. Ah, so for that you could use Mongo, as your caching layer! But if something goes wrong with the consistency you can just clear the cache. You can’t do that if the cache is your database!

And what if suddenly this view isn’t important at all anymore to your business? You’d rather like to display it like that:

Jeremy's Messages

Awww, snap! Those business people changed up everything, but you have a database full of data optimised for another case! Denormalising data means committing to certain joins.  So the ideal strategy that would give you performance and reliability would be:

  1. Use a relational database to store data normalised
  2. Use caching if there is a bottleneck of joins somewhere

Furthermore: While changing business requirements will change most certainly it’ll take probably a bit longer for your “new cool web-app” to actually reach a stage where this sort of caching is necessary.

 

“SQL doesn’t scale horizontally”

Not out of the box, but once you reach a certain size you can easily switch to something like Amazon Aurora (compatible with PostgreSQL and MySQL), which has up to 15 read instances. And once you outgrow this (and are probably a billionaire by now), you can still implement caching solutions (see above).

And what about write? Well, in SQL as well as in NoSQL databases you will have one master for write. Then, classically the first thing to do is to scale up vertically the instance that’s responsible for writing. Once this fails, you can check where’s the bottle-neck, e.g. move server logs to Redis (offloading). And once this fails, you can still use sharding. While MongoDB has an automatic mechanism for this, with the SQL solutions you’ll have to take care of the sharding-logic yourself. However, that’s not so bad. Since when this happens you’re probably also at a size where defining the sharding-logic yourself brings performance gains.

 

“In SQL, adding new columns to large tables can lock / slow down the database”

When you’re at the multi-million-rows-per-table level of an application, you can use a solution like Amazon’s Aurora. This system doesn’t slow down when columns are added. From the docs:

In Amazon Aurora, you can use fast DDL to execute an ALTER TABLE operation in place, nearly instantaneously. The operation completes without requiring the table to be copied and without having a material impact on other DML statements. Because the operation doesn’t consume temporary storage for a table copy, it makes DDL statements practical even for large tables on small instance types.

http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Aurora.Managing.html

Actually, you can start with Amazon Aurora right away, as it isn’t really more expensive than a regular database server.

 

“MongoDB is more reliable / available with it’s Replica Sets than a classical SQL DB!”

Again, ever heard of something like AWS? Amazon (or other cloud RDB providers) takes care of availability for you, so you don’t need to worry about that.

 

“MongoDB is free and you can run it on cheap linux systems”

The server costs probably don’t factor in too much next to your love, sweat and time put into your project. Having said that, a simple MongoDB production setup on AWS would be around 65$ / month (smallest MongoDB atlas cluster). By setting it up yourself, you’ll not really be cheaper than this. A simple Aurora production setup would be ~40$ / month.

 

“But I have no schema! I have truly unstructured data!”

Really? You don’t have users logging in, connecting with something? Even if so, sooner or later you will have some relations in any meaningful web-app. I’m still waiting for that use case where there is literally no structure in the data of a web-app.

 

[With Mongo] you can choose what level of consistency you want depending on the value of the data (e.g. faster performance = fire and forget inserts to MongoDB, slower performance = wait til insert has been replicated to multiple nodes before returning) – source

You probably don’t have “fire and forget” data. Which data would that be? I can’t think of any. Users interact with your system, that’s what generates the data as well as the business value for your system. What would be so invaluable as to lose it? A user post? Certainly not. A user changing the privacy settings? Better not.

 

With MongoDB you get full-text search

While that may be true and will help you get your full-text search started, it’s not that hard to set up a search engine like Lucene or Elasticsearch. We’ve actually chosen MongoDB for one project for exactly this reason but we quickly outgrew the capabilities of it and switched to Lucene, while being stuck with Mongo for all our relational data.

Conclusion

Disadvantages of NoSQL:

  • No consistency
  • No transaction safety / No rollbacks
  • Less flexibility in querying

Advantages:

Yet to be found.


If you liked my rant, don’t forget to follow me on facebook or twitter and share this post with others thirsty for NoSQL criticism!

5 Funny Computer Science Jokes

Why do Java programmers wear glasses?

Because they can’t C#.

SQL

A SQL query goes into a bar, walks up to two tables and asks, “Can I join you?”

3 guys

A physicist, an engineer and a programmer are on a steep mountain passage, when suddenly the breaks stop functioning. After some shouting and near death experiences, they finally manage to bring the car to a halt. The physicist says “Let’s check the temperature on the breaks and test the friction, maybe then we can figure out what went wrong.”. The engineer goes “Let me just get some straps, I can fix it”. The programmer just gently shakes his head. Then he goes “Guys that’s not how it works. Let’s first do it again and check if it’s reproducible!”.

OOP Joke

Q: What’s the object oriented way to become rich?
A: Inheritance

[“hip”, “hip”]

(hip hip, array!)

Managing State in Angular 2+

manage state
The hardest thing in a growing single-page application is managing state. Click To Tweet

This problem has always been strongly discussed in the Angular community, but not many standards have emerged. Most tutorials are too far from real-world applications to capture the essence of the problem and only simplistic “parent-child” interactions are discussed. As an application grows, components become more deeply nested and we need solutions to handle interactions between components that are more distant from each other than “parent-child”.

The best approaches to me seem to be storing some state in services or using a state management library. The most prominent exponent for such a library would be ngrx/store (https://github.com/ngrx/store). If you’re having trouble with managing states you are not alone, other people have already had this problem and dealt with it. Unfortunately those people just don’t seem the to be the ones from the Angular Team, which still promote their “hello-world” data-binding mechanisms.

I’m not alone with this opinion, similarly thinks Kyle Cords in this excellent summary on managing states in Angular2+. Exactly as in my experience, he describes how the application gets messier as the codebase grows with the classical data-binding mechanisms you find in all Angular tutorials. The way I see it, the tutorials mostly mention those techniques for two reasons:

  • They are a tiny bit simpler to demonstrate in a small demo app than other methods.
  • They are a “Unique Selling Point” for Angular. If they would suggest using something like ngrx/store they’d essentially say “why don’t you just switch to React & Redux, here’s a link to get you started”.

Now whether it’s best to use ngrx/store or using mechanisms provided by angular (services) is subject to debate. Here’s a list of pros and cons for each: State Management: ngrx/store vs Angular services

In case you want to take the manual path with services, here are some of my thoughts on the subject.

Update resources with an id

Typically, behind every application, we have a database. And typically, this database has different tables (or collections or however you want to call them) and all of the entries in a table have an id. For example behind the Angular2 Heroes tutorial, we’d have a database with a heroes table where each hero is stored with its own id. Almost every application is structured this way. What’s very often the case in a real-world application, is that we want to change the data in the database as well as in our entire application. There could be, for example, an input field to change a hero’s name and when clicking the button “Change”, we’d send the change-request to the server (database). When the server responds with “200 ok” we want to change the hero’s name application wide. How would we go about that? The answer is: observables.

UpdateAll (1)

Since “ResourceName + ResourceId” are always unique for each unique object in our application, we can easily build a frontend-datastore based on this. The basics of the ResourceStore service, or here more specifically a HeroStore (leaned on the Angular hero tutorial-series) are:

import { Injectable } from '@angular/core';
import { Hero } from './hero';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';

@Injectable()
export class HeroService {
  private heroStore = {
  }

  insertHero(hero: Hero): void {
    this.heroStore[hero.id] = new BehaviorSubject<Hero>(hero);
    this.heroStore[hero.id].next(hero);
  }

  updateHero(hero: Hero): void {
    this.heroStore[hero.id].next(hero);
  }
  
  getHero(heroId: string): Hero {
    return this.heroStore[heroId];
  }
  
}

Like this, everywhere in the application you can listen to changes on those observables. There is one catch though: You shouldn’t forget to unsubscribe when the component is destroyed or otherwise you’ll gather loads of dead listeners on your observables over time. Here’s how it’s done:

import { Component, OnDestroy, OnInit } from '@angular/core';
import 'rxjs/add/operator/takeUntil';
import { Subject } from 'rxjs/Subject';

import { MyThingService } from '../my-thing.service';

@Component({
    selector: 'my-thing',
    templateUrl: './my-thing.component.html'
})
export class MyThingComponent implements OnDestroy, OnInit {
    private ngUnsubscribe: Subject<void> = new Subject<void>();

    constructor(
        private myThingService: MyThingService,
    ) { }

    ngOnInit() {
        this.myThingService.getThings()
            .takeUntil(this.ngUnsubscribe)
            .subscribe(things => console.log(things));

        this.myThingService.getOtherThings()
            .takeUntil(this.ngUnsubscribe)
            .subscribe(things => console.log(things));

    }

    ngOnDestroy() {
        this.ngUnsubscribe.next();
        this.ngUnsubscribe.complete();
    }
}

(courtesy to stackoverflow)

Here is the Hero-Tutorial adapted to use observables instead of ngModel:

Angular Heroes

The essential code bits behind this example are the hero.service:

import { Injectable } from '@angular/core';
import { Hero } from './hero';

import {BehaviorSubject} from 'rxjs/BehaviorSubject';

@Injectable()
export class HeroService {
  private heroStore = {
  }

  insertHero(hero: Hero): void {
    this.heroStore[hero.id] = new BehaviorSubject(hero);
    this.heroStore[hero.id].next(hero);
  }

  updateHero(hero: Hero): void {
    this.heroStore[hero.id].next(hero);
  }
  
  getHero(heroId: string): Hero {
    return this.heroStore[heroId];
  }
  
}

as well as the subscribing entities (here: app.component and hero-detail.component)

//app.component.ts
...
ngOnInit() {
    HEROES.forEach(hero => {
      this.heroes.push(hero);
      this.heroService.insertHero(hero);
      this.heroService.getHero(hero.id).subscribe(updatedHero => {
        for (let i = 0; i < this.heroes.length; i++) {
          if (this.heroes[i].id === updatedHero.id) {
            this.heroes[i] = updatedHero;
          }
        }
      });
    })
  }
...

//hero-detail.component.ts
...
ngOnInit() {
    const heroObs = this.heroService.getHero(this.heroId);
    this.hero = heroObs.getValue();
    heroObs.subscribe(hero => {
      this.hero = hero;
    });
  }
...

 

Here, the heroes are fetched from a constant HEROES which is turned into observables on storage. The library used for observables is RxJS, the standard for an observable-library nowadays.

RxJS Logo

Admittedly, at first it may look a bit more complicated using observables than using ngModel, especially when you are used to ngModel from all the tutorials and Angular 1 two-way binding. But as your application grows, this scales nicely as it guarantees consistent data across your application.

Talk to all components of the same name

For example if our component structure would be:

hero-list > hero > delete-button

Then how could the delete-button tell the hero list to delete a hero? Does it really have to tell its parent (hero) “please delete this hero”, but the parent is also not allowed to do so, so the parent needs to ask the hero-list in return “please delete hero”? As you see this becomes more annoying as components become more nested. Is there really no way where components can communicate directly with one another? Can’t the child tell the grandparent directly please delete the hero?

Namespaced Broadcast Service

The solution to this problem are, again, observables. Let me elaborate. Basically you can create a service like the following

import { Injectable, EventEmitter } from '@angular/core';

@Injectable()
export class BroadcastService {

  public heroList = {
    deleteHero: new EventEmitter()
  };
  constructor() { }

}

The structure of this service encapsulates the magic behind this approach. It avoids name-spacing problems, by naming the methods of the BroadcastService after the components that should listen to the events. Each method then has the available EventEmitters as properties.

In the child component, you can simply inject the BroadcastService and emit a new event:

import {Component, Input, OnInit} from '@angular/core';
import {Hero} from "../hero";
import {HeroService} from "../hero.service";
import {BroadcastService} from "../broadcast.service";

@Component({
  selector: 'app-delete-hero',
  templateUrl: './delete-hero.component.html',
  styleUrls: ['./delete-hero.component.css']
})
export class DeleteHeroComponent implements OnInit {

  constructor(
    private heroService: HeroService,
    private broadcast: BroadcastService
  ) { }

  ngOnInit() {
  }

  @Input()
  hero: Hero;

  public deleteHero() {
    this.heroService.deleteHero(this.hero.uid).then(resp => {
      this.broadcast.heroList.deleteHero.emit({
        heroId: this.hero.uid
      });
    });
  }


}

and the great-grandparent (or whoever!) can subscribe to those events

...
ngOnInit() {

  //set up listeners
  this.broadcast.heroList.deleteHero.subscribe(evt => {
    this.heroes = this.heroes.filter(hero => hero.uid !== evt.heroId);
  });

  ...

}

Where is the downside of this approach? The child will not tell something directly to it’s grandparent. Other components with the same name are also listening. So for example if we were to feature the hero-list twice on the same page, and both lists would contain the hero with the uid xyz, then emitting a deleteHero Event would delete the hero in both lists. If you need the child to tell something to its grandparent and only to its grandparent, then you’ll really need to pass the information through the parent (see event-binding below). However, this is often not a problem since, like in this example, most of the time we would even want the second list to also be updated, since that hero was actually deleted from the database and this should be reflected everywhere in our application. We’ve also limited the problem with our name-spacing, such that only the right components will actually listen to those events. This is already much much better than just broadcasting events out into the wild like broadcast.deleteHero.

When no id is present

When no id is present on the data you want to update, the classical Angular data-binding mechanisms come into play which you find in most of the tutorials.

In any case, when no ids are available, those mechanisms prove to be quite useful.

“Downwards” Data-Flow

Upwards vs Downwards

Here “downwards” designates a flow from parent to a child to grand-child and so on. Angular pretty much takes care of this one for us. It’s similar as in Angular 1, just the notation changed a bit. Here’s how it would look like to propagate data and data changes from parent to child to grandchild.

The parent:

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

@Component({
  selector: 'app-parent',
  template: `<div> {{item + 1}} <app-child [item]="item"></app-child></div>`,
})
export class ParentComponent {

  item;
  constructor() {
    this.item = 'My Item ';
  }

}

The child:

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

@Component({
  selector: 'app-child',
  template: `<div> {{item + 2}} <app-grandchild [item]="item"></app-grandchild></div>`
})
export class ChildComponent {
  @Input()
  public item;
}

The grandchild:

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

@Component({
  selector: 'app-grandchild',
  template: '<div>{{item + 3}}</div>'
})
export class GrandchildComponent {
  @Input()
  public item;
}

Which would yield the output:

When item is changed in the parent, the changes are also propagated downwards. Here, I’m probably not telling you anything new and it’s the method of choice in most Angular tutorials. This method has proven clear, convenient and maintainable to our team over the years. The most common source of errors with this method in Angular 2 is to forget the square brackets (i.e. to write <app-child item=”item”> instead of <app-child [item]=”item”>, thus marked red above). Apart from this, you can’t really go wrong.

Upwards Flow

Classically in Angular1, you would just modify data on the child and the changes would be propagated upwards through two-way data-binding. However, in Angular2+,  they diluted this concept for performance & “clarity of the application” reasons. Now only changes via ngModel  in properties of objects are propagated upwards (example: tour of heroes). What exactly does this mean? For one, it means that if you don’t have an object but instead a primitive (string, number etc.), changes made will not be reflected in the parent. As an example, here is the “tour of heroes” from the Angular tutorial series adapted to demonstrate this:

Second, this means that you can’t just update this property in your controller or you may run into nasty errors like the following:

Nasty Angular2 Error

This happens with the following piece of code:

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

@Component({
  selector: 'app-grandchild',
  template: `<div>{{item.name + 3}}...</div>`
})
export class GrandchildComponent implements OnInit {
  @Input()
  public item;

  ngOnInit() {
    this.item.name = 'Jacky';
  }

}

All of this makes it hard for novices in Angular 2 to understand where they may and where they may not change data. That’s why I prefer the method with the observables whenever possible. In cases where you have to use ngModel: just make sure it’s actually an object and not a primitive you’re trying to change.

In case you want to propagate an event (as opposed to data-changes) upwards, then you can use the Angular event-binding mechanisms. Let’s consider the following component structure

hero-list > hero > change-color-button

In event-binding, the hero component invokes the change-color-button like so:

<change-color-button (colorChanged)="doOnColorChange($event)">
</change-color-button>

and in the change-color-button an event can be emitted like that

@Output() colorChanged = new EventEmitter();
...
colorChanged.emit({newColor: "green"});

Then the hero component can act upon a color change by implementing the doOnColorChange method. This method becomes quite annoying if we have components that are nested by several levels, as the each component must create its own EventEmitter, but sometimes we have no other choice.

Conclusion

There are many options for handling state. In my opinion it’s a close race between using a state-management library such and combining some of Angular’s core features. In case you want to handle management yourself rather than including yet another library, here’s a possible decision-making flowchart:

Exchange Information Between Components (6)

 

Thanks for reading, don’t forget to subscribe to get updates timely & share if you found this post useful!