Angular component practices

Picture of a computer.
Photo by Christopher Sardegna on Unsplash

Angular is known to provide complete solutions out of the box. It gives developers all the tools alongside the guideline on how to create applications. Overall that makes it more strict than other solutions like React or Vue. In my opinion, Anulgar is still very flexible. It allows creating an application using different practices. Some of them are good for small projects others for larger ones. In this article, I would like to present some of the component practices for larger applications.

Motivation

The main idea behind these practices is:

Project basecode should look like it is written by one person.

In other words, practices goals are:

  • Allow developers to focus on technical aspects - they don't have to think about nuances,
  • I'm a big fan of TypeScript strict mode as it reduces the number of places where a developer can make a mistake- style guide should be compatible with strict mode,
  • Focus on large enterprise-scale applications - some of the practices may look too complicated, but in larger projects, they are worth using.

1. Input

Inputs are one of the most commonly used methods of communication with a component.

Required inputs

The most important inputs are the ones that are required by the component in order for it to work. We need to be able to distinguish these inputs from the ones that are not needed. There are two techniques that will let us achieve it.

First of all, we need to specify the input name in the component selector:

Component with a required input name
Component with a required input name

This method changes the selector of the component. Now angular will not recognize the model tag used alone without also specifying the text input.

The problem that still exists is that TS strict mode doesn't allow declaring a variable without assigning a value to it, or adding to its type that it can also be undefined. This practice focuses on reducing the number of null or undefined usages, so I prefer a different solution. To read more about TypeScript strict mode I recommend this article Bulletproof TypeScript - strict mode for Enterprise scale Applications.

The text input is required and it will always have a value, so we need to tell the TS compiler about it. To do it the best practice is to use the exclamation mark or non-null assertion operator.

Model component with a required input
Model component with a required input

Optional inputs

Some of the inputs are optional by the component, they are not required by it in order to work.

The best way to handle it is by assigning a value to the input:

Property initialized with a value
Property initialized with a value

For most of the cases, you can assign input with an empty value, like e.g. string property can be initialized with an empty string ''.

You cannot always assign the default value for the input. In that case, use the ? mark and make property optional:

Component with an optional input
Component with an optional input

Input practices

  • Required inputs should be specified in the selector,
  • Required inputs should be declared with an exclamation mark(non-null assertion),
  • Optional inputs should be assigned with value,
  • When the previous point is not possible not required inputs should be declared as optional with ? mark.
Angular component input practices
Angular component input practices

Presented practice makes component inputs much more readable. You can tell right away which input is required and with is optional. A developer is able to use components more easily.

2. Outputs

Outputs allow for communication with the parent of the component.

Angular component Output practice
Angular component Output practice

Output practices

  • Always initialize output variables on the declaration - assign value with new EventEmitter(),
  • Declare property as readonly so no one reassigns it with a new value,
  • Specify the type of EventEmitter.

3. Queries

The next practices concern view and content queries:

  • @ViewChild,
  • @ViewChildren,
  • @ContentChild,
  • @ContentChildren.

readonly

Queries are similar to inputs in a way that we don't set their values, the framework does it for us. For e.g. we only read a value of a @ViewChild property. That is why we should declare properties as optional and readonly:

Model component with a @ViewChild property
Model component with a @ViewChild property

type

One of the powerful features of queries is that you can specify the read property.

Definition of the read property from @ViewChild
Definition of the read property from @ViewChild

It can select different types of values. From ElementRef and ViewContainerRef to any provider defined in the components injector.

That is the way in order to always be sure what is the correct type of the variable you should specify the read property:

View child with the specified read value
View child with the specified read value

Query practices

  • declared as optional - they cannot be assigned at the start,
  • always specify readonly - developer can only read the value of the query property. The framework's responsibility is to set its value,
  • always specify correct read type.
Component practices for view and content queries
Component practices for view and content queries

4. Selector

Angular components are always rendered in dom as custom elements. They have no built-in CSS styles. This is kind of uncomfortable for the developer, as you always have to remember to set the display property:

Basic component with specified display
Basic component with specified display

There is an interesting practice which I recommend using. You can specify the selector of the component as div[model] which tells Angular that the ModelComponent can be used only on the div tag:

Model component with div selector
Model component with div selector

You can use this model component in the template:

The model component used in the template
The model component used in the template

You can specify any other tag in the selector. It doesn't have to be div.

Style guide

If you are interested in checking more of these practices, I recommend visiting The Generic UI Angular Style Guide.

Final word

Some of the practices may look like overreacting. When I first saw it I immediately ask myself, will I ever make that kind of mistake. Will I ever assign a value to an input or a property connected to a ViewChild? My answer is probably not. In my head, I already see the readonly next to the input property, even though it is not here. But practices are not for me, they are for everyone who works with angular and want to make their application more readable and have fewer bugs. No matter their experience in the framework.

Luke, Software engineer, passionate about best practices, frameworks React, Vue, patterns and architectures for modern web
				development, open-source creator, TypeScript enthusiast, Generic UI Technical Blog

Luke

Software engineer, passionate about best practices, frameworks React & Vue, patterns and architectures for modern web development, open-source creator, TypeScript enthusiast.