Early on in my journey with Angular, I found myself in situations where data (such as form values) would disappear mysteriously when routing. I soon became familiar with some of the nuances of Angular’s routing system. In this post, I’ll show you some of the pitfalls that I encountered and how to deal with them.

External vs. internal routing

Let’s start off by defining a couple of terms. I’ll call these terms “external routing” and “internal routing” to differentiate them.

External routing

External routing occurs when the user refreshes the page, types a URL into the browser, or clicks a link defined using href. The main side effect of external routing is that the user gets a new instance of your app, and any variables it has get reinitialized (for instance, those within an Angular service). This happens because the browser reloads your index.html and the associated JavaScript files.

Internal routing

Internal routing is when Angular performs the routing itself, due to the user clicking an element with the routerLink directive (instead of href), or when your app calls a method like Router.navigate(). In this case, because the web page does not need to reload, the user is still in the same instance of your app after the routing is performed. Any variables it has are preserved. This is true even though the URL changes to the new path in the address bar of the browser.

What’s a dev to do?

Well, you’ve got two options:

  1. Care
  2. Don’t care

In some cases, you may be at #2 where it simply doesn’t matter to you. Due to the specifics of your app, it’s not a problem if the entire app reloads and a form gets cleared for instance. However, I’d guess that the majority of apps will be at #1 and will care. They’ll want a consistent user experience that’s agnostic to the means of routing. In this case, the solution is fairly straightforward (though maybe not always “simple”): persist the data yourself, whether it’s using WebStorage, IndexedDB, or your own backend service.

The simplest approach is by far WebStorage, more specifically localStorage. Though persisting and loading data is a topic of its own, there are a number of patterns and tools that can help with using local storage. A pattern I’ve used is to load all data from local storage in the constructor of a component, then persist whenever the data changes (in a callback, for instance). Another pattern is to define getters and setters on your models, having them load from and store into local storage appropriately. The latter pattern actually gave rise to my most recent project Local Motive, which provides a convenient decorator syntax for models, allowing fields to be backed by local storage (or session storage).

Hope that helps illuminate some of the gotchas in Angular’s routing system and how to deal with them. Happy routing!

angular local storage routing