source:https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Angular_full_color_logo.svg/1024px-Angular_full_color_logo.svg.png

Some things I wish I knew before I start to work with Angular.

piotr szybicki
12 developer labors
10 min readOct 3, 2018

--

So this time around on my quest fighting with complexity I will make an admission of guild. Some time ago I started working in new company on a new project that was a total green field. Justifiable or not i was made a technical lead on the project. It started as great fun we had new stack that I could play around with. Spring boot, Angular 5 plus some infrastructure that we could do nothing about. I was very excited. And in that excitement i didn’t took a breath and ask my self:

Do I need angular at all?

Angular is an extensive framework that allows developer to create quite complicated web apps (and beyond). But it has a lot of moving parts that you have to know how to use. And what’s more you have to now about its existence first. Otherwise you risk reinventing the wheel. That leads to accidental complexity. But even if you know all this parts you might not need the juggernaut that is Angular framework. In our case we had just a form with a couple of controls that’s it. From the perspective of time jQuery plus pure javascript would be much better fit for use cases.

And it might be a case for you too. Don’t be eager to use new stuff only because it is new. You might think that it good to pad you cv with that knowledge but i wasn’t thinking about that when me and my team had to stay at work late trying to fit the square into a round hole. It was a nerve wracking experience.

Smart components vs presentation components

OK. Let’s say that we stick with Angular. The next important question how to structure application. Months later when I decided to dig deeper into some good practices when designing the app. I stumble upon the smart vs presentation components. And i have to say i like it a lot. I have a sample application attached to this article (it is complicated enough to illustrate my point). And when i reflect back to the beginning of my project this would save us a lot of time and to quote the borg “bring some order to chaos”. This is known for quite some time but readable code is easier to maintain.

The basic principle of this very dumb (in a good sense) pattern is that you split any component that you have in to two parts. Presentation component. It contain only presentation login. If this control should be displayed, what style. Any variable with the business meaning is annotated with @Input and passed from the parent component called the smart component. The smart component encapsulates the presentation component and in it’s template definition there is nothing else but tag to the presentation component. The presentation component passed any information to it’s parent via Events. So again any field with the business meaning are annotated with @Output.

It create this beautiful architecture where the developer responsible for the visualization (ux/accessibility expert, css master) does not causes any merge conflicts with the guy that tries to hack away some business logic.

A word of warning here the custom events do not double up the DOM tree so they have to be handled in the parent component. And that brings me to the next point. Some further reading (this article will contain a lot of links i do not want to repeat something that was said already by somebody else):

Use Single Responsibility Principle

The first of 6 SOLID principles finds its application in all walks of life. It says that every building block (i avoid on purpose using the word class) should have only one reason to change. The splitting of presentation and business logic is only one example and a first step. We should divide the smart component further into validators, services that interact with the backed, services for state management etc. We should never allow to grow our services out of proportions. If you have to scroll 3 screens just to go over your imports you might’ve gone too far :)

Existence of a Render

Every time we needed to set focus on an element we used @ElementRef and manipulated the HTML element directly. Either by setting invoking and event or set a value. Bypassing the angular platform itself. I think the proper solution is to use the Renderer. It is a service created at a root level and can be injected and then used like this:

constructor( private renderer : Renderer) {}this.renderer.invokeElementMethod(inputElement, “focus”, []);

This allows you to manipulate the DOM without bypassing angular DOM abstraction.

Structural directives introduce a new template inside template

I had a specific problem when i try to use template reference variable inside a tag with a *ngIf on it. You see this:

<div *ngIf="true">
<input #variable />
</div>

Became this:

<ng-template [ngIf]="true">
<input #variable />
</ng-template>

And that limits the scope of the #variable. The more detail explanation can be found in this article:

Difference between <ng-template>, <ng-content>, <ng-container>

This is a fun one. I start with ng-template (originally create to function much like <template> tag in html, something that is not rendered but can be made visible using JavaScript) If you put some code between the tag it won’t appear in dome it will become comment. It can only be displayed in tandem with a structural directive.

<ng-template [ngIf]="true">
<button mat-button>Contact</button>
</ng-template>

Or if we use it as a place holder

<div *ngIf="someCondition else display">
Hello
</div>

<ng-template #display>
<button mat-button>Contact</button>
</ng-template>

Also important fact to notice is that ng-template will not become the part of the DOM. Only a content will.

ng-container main difference is that it will always be rendered. It is useful if you need to put some structural logic and you don’t want to use another dom element. Classical example is if we want to have if and for loop statement on the same tag.

<ng-container *ngFor="let item of items">
<tr *ngIf="item.amountInStorage > 0">
<td>{{item}}</td>
</tr>
</ng-container>

ng-content to be honest i have never found a need to use this one, so it doesn’t belong in to this article per say. But i decided to include it as I had some trouble to understand the difference between thous tags. So ng content is used as a way to insert html content into a component

This is template part of our component:

<h1>Bla bla bla</h1>
<ng-content></ng-content>
<p>Bla bla bla</p>

and this is a part where we use the component:

<custom-angular-component>
<h3>This will be put in place of ng-content :)</h3>
</costume-angular-component>

Use NgRx for your state management

I will not go over that in much detail because I want to write a separate piece on this super cool technology. But as I mention this before events do not bubble up so for example if you have information that component 10 levels deep in your DOM have to share with the menu bar you would have to create a very complicated chain of events to pass that information. And if you have any rooting done this will not work because you can’t pass custom events from the <router-outlet> tag.

Simplest solution to that problem is to create service inject into both component and share the data this way. But I do not recommend it. I think for any kind of state management we should you NgRx. This is the case where a little over engineering is a good thing :). See setting up NgRx is quite easy and after we do that we are set for life. There is a learning curve is much bigger compared to the services (after all we all get dependency injection) but I think it is a time well spent. I promise you that it will pay of. If you have any project that seize merits use of angular the number of services to share data will grow so fast that you will end up in service injection hell. I know I’ve been there.

What are really useful lifecycle hooks

  • ngOnChanges called when references of objects that are bound to the component as DOM input properties change. Careful with that let’s say that you have complex object with couple of fields changing one of that fields will not trigger this hook.
  • ngOnInit called once right after the first execution of ngOnChanges completes. At that point the angular displays all the properties. Good place to initialize your variables, call backend for some additional info etc.
  • ngDoCheck this is what we want if we want to listen to changes to fields of objects that are bound to a template. It is more sensitive then ngOnChanges.
  • ngOnDestroy called before angular destroys the component good place to unsubscribe from any observable’s. Do general cleanup.

Use reactive forms.

Angular has to approaches to form, there is a template driven and there is a reactive driven. Reactive gives you more flexibility and i recommend using this one. I strongly believe that things like validations should be a part of your business logic and not the html template. The whole purpose of the smart component is to be a placeholder for all things business related so we can key the presentation component as clean as possible. When we give it to the web designer he/she will have much easier time working with it. For me pretty good primer was this article:

Dependency injection as a backbone to share behavior and avoid duplication.

One thing I always look while doing a code review is violation of DRY principle (Do not repeat yourself). And although I’m not the ‘avoid duplication at all cost’ kind of a guy I’m not afraid to point it out when it is effect of developer laziness, or lack of knowledge. Dependency Injection could be a solution to centralize behavior where needed. But Angular does DI in it’s own way. To understand that. Great resource for me was this article:

Learn how the router works

So the router is a way for us to structure and navigate thru your application. I think aside of how the routes are matched to the path you should have a good understanding how to update the component data when route change, and how should you protect your routes. It is also a good practice to put routes definition in it’s own module. Following resources ware a good starting point for me:

Embrace the reactive style of programming

I think i should start with that one. Angular makes the observable pattern and the use of RxJS to heart. And if you come form the imperative programming worlds you will struggle with writing code that is not executed by blocking until the result is returned. Well get over that. Start by writing some unit test using RxJS to get the feeling what is possible and what’s not. There are parts that will have to be imperative for example: conditional logic. Key concepts to figure out are:

  • The usage of the | async pipe.
  • Observable creation: of, fromEvent
  • Oparators that are most used: map, filter, flatMap vs megeMap vs swichMap, zip, startWith
  • hot vs cold observable, and the risk of memory leaks

Learn Angular Material Design

This is a little specific and maybe it shouldn’t be. My point is that there are some great free libraries out the full of components that are ready to go. Material design is just one of them. I said it in this article many times that there is absolutely no benefit to reinvent the wheel. So before you embark on the journey of writing or refactoring your application take a look at some of those libraries, maybe someone solved your problem.

The visulal studio code tips and tricks.

The last one is not any less important. Master your IDE. I know many people are using WebStorm theas days. I started using visual studio code, and the suffering it put me thru at first was unbelievable. I’m used to code completion, syntax highlighting and all those things i get in the JAVA world. Here at first i got nothing. Until i installed some plugins :), until i learned some shortcuts etc. If you planing using VS Code. Very fun presentation:

Example app:

It is not a fully working example as I’m writing another peace on websockets but it is usable and enough to show my approach to some basic structures of the web app.

There are two main folders where the app lives. The ‘smart’ and ‘presentation’ folder. The structures under the tree is the same. We have a chat, login, menu folders that are home for the components. Routes are in it’s own module, and also import for the material design. Explore, there is not that much going on. I just want to remind you to that this is an example, imperfect approximation of what I would do if designing a real application. To use with extreme caution and don’t copy paste like mindless zombie.

--

--

piotr szybicki
12 developer labors

Piotr Szybicki’s, Programmer, Java Developer, ML Entusiast