After an experience working with Angular on real life projects, I have developed my own set of patterns for organising scalable Angular code on large and complex apps. I thought it would be useful to share them.

I tried to separate them in small articles, and to be as concise and clear as possible.

Other articles in the series:

In my previous article I spoke about the benefits of removing “decision-making” responsibilities from components, in order to make them reusable. I said that components, who defer responsibilities to their parent, can be seen as “bricks” of your application, that you can place wherever you want, and make behave as you want.

It’s now time to look at the higher picture, and try to bundle together a set of such “bricks” in the root component of a page of your application.

At first sight, these are the problems that we need to solve, in order to achieve our goal:

Problem 1: I want to be able to instantiate all my brick components, and make them work, without ending up in a super-fat root component that does everything

In order to solve this problem, we need to group somehow brick components inside different “areas” of the page; each area should receive a different set of data as input, instantiate its own set of brick components, make them work, and send signals to other areas (or to the root component) in response to user interaction.

Problem 2: I want to be able to set up easily OnPush change detection strategy

The problem with “brick” components, i.e. reusable components that don’t decide anything about their internal status, is that it’s tricky to implement OnPush change detection on them, without in the same time binding them to the specific implementation of the parent component (hence, losing in reusability).

Why? Let’s look at an example.

The two components in the gist above behave very similarly, but they receive their inputs in a different way: the first component receives a bare number, while the second receives an object, that has a number among its properties.

The problem of OnPush change detection (which is its delight too, because it improves performance a lot) is that Angular checks objects by reference. If an object changes, but its reference doesn’t, Angular won’t realise that the child components needs to be updated. So, if you change the input number for the first component, the DOM gets updated, but if you do the same for the second component, the DOM will stay unchanged.

There are several workarounds for this problem, depending on what you want to achieve. One of them is using immutable objects (I’ll redirect you to this clear article).

The problem with all these workarounds is that, implementing one or another of them, you are somehow binding yourself to the specific context where the component is used. Hence, you lose something on reusability.

Let’s look at the example of immutable objects, for instance: if you go for that strategy, you have to hardcode the immutable object’s methods in your component.

This component won’t be reusable in contexts where the input is not immutable.

So, coming back to the list of problems we want to solve: implementing OnPush strategy without losing reusability of our “brick” components is definitely one of them.

Finally,

Problem 3: I want to be able to keep parts of the page isolated from the rest

Let’s say that we have a page that represents an article: the page is complex and contains a lot of different areas, there is a sidebar, a navigation, the article’s content, etc. All these components / groups of components are powered by the same “article” object that comes from the API. If you don’t implement OnPush change detection strategy, and you update, let’s say, the article’s title, the “article” object will be updated simultaneously in all the other parts of the DOM where it’s used. This is an example of a page which parts are not isolated.

Isolating components is not always the most important thing to do, it obviously depends on what you are trying to achieve. The problem is that Angular tends, for its design, to keep all your components up-to-date and synchronised with each other, so, if for any reason you need to do the opposite, and isolate them, you need to find a solution yourself.

Let me then rephrase problem 3: while I can find a workaround for each specific situation in which I want part of the page to be isolated, I’d prefer to have a uniform, standard way to enforce isolation, in the same way, on any given subset of the “brick” components I need.