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 occurs when the user refreshes the page, types a URL into the browser, or clicks a link defined using
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:
- 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!