Level 1: Angular 5+ Gotchas
At work, we’re architecting the future path of our front-end stack. A few months ago, we decided on Angular after running POCs against React, Vue, and Angular itself. There are a few reasons why we ended up where we did, but everyone’s entitled to their own opinions.
While working on Angular, I discovered a few gotchas that I thought deserved some special attention. This post is a collection of my findings.
Constructor
vs.ngOnInit
On the surface, they do the same thing.
constructor(private todoHTTPService: TodoHTTPService) {
this.todoHTTPService.getTodos().subscribe((todos: Array<TodoJSON>) => {
this.todoJSON = todos;
todos.forEach(todo => this.transformedTodo.push(new TodoTitleStatus(todo.userId, todo.id, todo.title, todo.completed)));
});
}
has the same end result as
ngOnInit() {
this.todoHTTPService.getTodos().subscribe((todos: Array<TodoJSON>) => {
this.todoJSON = todos;
todos.forEach(todo => this.transformedTodo.push(new TodoTitleStatus(todo.userId, todo.id, todo.title, todo.completed)));
});
}
Constructor is a typescript concept and, from a Java background, is meant for what is required to even instantiate the class.
ngOnInit is Angular, and is called when Angular has finished constructing the component. It is called after the first ngOnChanges()
.
Generally, we try to keep the constructor as light as possible. It’s a pain to set up tests for it and although I prefer to be as light on the Angular framework as possible, it doesn’t seem right in this case.
All the initialization logic should go in the ngOnInit and only the dependency injection for the constructor.
Class
vs.Interface
for Model definitions
In order to have well-ordered structure in your application, a good data model is essential. Without one, you’re just playing in the sand with all the JSON like in angular.js. Lel (at least the way that we do it at work).
In terms of performance, both are lightweight. My understanding is that both classes and interfaces are able to shape JSON data into the model objects that we want them to be in. That being said, interfaces are removed from compilation while classes remain. If you have methods and/or private variables, use classes. If not, and if all you really need is to shape the data, interfaces are fine.
Addendum
I also decided to include some notes that I took from reading the Angular 2+ style guide below. Hope it may help distill some of the information even further.
Shared Module (Content that is repeated but not singletons)
For content that is referenced across the entire application.
- Avoid putting services under shared unless intended to be singletons.
- Mainly for components, directives, and pipes.
Core Module (Singleton content)
Singleton content shared across the entire application
- Navigation/Spinner/Dialog Components
- Logger and Exception Services
Lazy Loaded Modules
- Don’t directly import lazy loaded modules, it defeats the purpose.
Components
- Leave for only view logic and externalize the service for more complex logic.
- Avoid calculations in the template but rather in the component itself.
- Does not care how it gets the data, just that it knows who to ask for it.
Directives
Presentation logic without a template.
- Use @HostBinding and @HostListener over host property.
Services
Singletons.
- Single Responsibility Principle.
- Inherited by children components when put in provider of parent.
- For sharing state/methods between components.
- @Injectable
- Have data services.