Angular — Make your code more Consistent, Readable and Expandable

Kalpesh Shingala
Mar 26 · 4 min read

This blog describes some practices which can be followed in an Angular project to make the code more consistent, readable and extendable. It can also be applied to other frameworks. These are sort of recommendations instead of ‘must haves’. Let’s Go..!

1. Split ngOnInit() logic

Mostly ngOnInit lifecycle hook is used to initialize the component properties, to make HTTP requests and to subscribe to some states. Check the below snippet.

demo.component.ts

There are 3 variables tempProperty , tempData and tempFormControl . All of these variables have different usage. The above code works perfectly fine. Also, as in our example, the component has no logic and is really small. In real-world scenarios, a component can be very large in terms of line of code and more code can be there in ngOnInit method. As you can see in ngOnInit method of our Demo-Component, all the operations are performed in the same method. It can be divided in some way, like below.

demo.component.ts

We now divided our ngOnInit method into three different methods.

  1. initialization() is used to initialize global component properties. It is not used for anything else. Its only purpose is to set the default values of component properties. That’s it.
  2. getData() is used to call an API and get the data.
  3. makeSubscriptions() is used to subscribe to Observables used in the component. For example, in our case, it is FormControl’s value-change. It can be any other Observables, like, Subject , BehaviorSubject or some state from the store if your project has NgRx.

This approach makes code more readable and extendable. It is really easy for new developers to understand where all component properties are set, where all subscriptions are defined. Also, if a new developer wants to add a new property or want to subscribe to a new observable it is easy for him/her to add it.

2. Instantiate objects in Constructor

Check the below code.

demo.component.ts

You might have recognized the inconsistency in the above snippet. There are 3 objects, statusUpdate, categoryUpdate and userUpdate.

statusUpdate is instantiated at declaration time, categoryUpdate is instantiated in the constructor() and userUpdate is instantiated in ngOnInit() method.

There are two problems here:

  1. The code is very inconsistent.
  2. For a new developer, it is really difficult to decide where to add a new subject if he/she has to.

Solution:

demo.component.ts

Now, there is only one method to instantiate all the objects of the component. The same can be implemented in the case of Services. It is not only to instantiate Subject but also can be used to instantiate FormControl, FormGroup or any other classes.

3. Use CONSTANTS

Consider the following scenarios:

You define your path to the Login page as <your-domain>/login. This path is used everywhere in the application. For example,

  • You check the authentication in the guard and redirect the user to the Login page if one is not authenticated.
  • A user logs out from the system and you want to redirect him to the Login page.
  • A user tries to go to some unauthorized path of the system by using the URL and you want to redirect him to the Login page. Now suppose you have a requirement to change the path of Login page from <your-domain>/login to <your-domain>/user/login.

How would you do that? You have to go to every single file and change the path just because you introduced a new word ( user ) in your path.

Solution:

Create a file named route.constants.ts and define every single path as constants.

routes.constants.ts
app-routing.module.ts

You can use the same constants everywhere you want to redirect a user to the Login page. If you want to change the path, you just have to modify the value of a constant variable LOGIN_URL.

It is not only for paths of routes. You can use constants for your unique modal-ids, default configuration options of any library ( Date-picker, Charts, Maps ).

4. Use enum

Consider the following scenarios:

You have a method in the service which has a signature as below:

You use this method in your component as below:

You want your getStatus() method to return one of the statuses only from todo, in-progress and done. Therefore, you use union types.

But in your component, you want to assign the value returned by getStatus() method to a variable having string type. It will give the error as:

You might use the solution of using as to explicitly convert the return type as below:

But if you have to use getStatus() in many components, the above solution is not a better one.

Solution:

Define an enum as below:

status.enum.ts

Modify the signature of getStatus():

Modify the usage of getStatus():

It resolves the error and you can be sure that there are only three types of statuses returned by the method.

Add comments if you follow something which can be useful to other developers. I will add it to this blog and will mention you.

More to Learn:

Aubergine Solutions

Among the World’s Top 50 UX Agencies.

Kalpesh Shingala

Written by

Frontend web developer ( Angular )

Aubergine Solutions

Among the World’s Top 50 UX Agencies. We’re a team of UX Designers and IT Engineers. We balance our madness and method. To know more about us visit www.auberginesolutions.com

More From Medium

More from Aubergine Solutions

More from Aubergine Solutions

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade