DEV Community

Phạm Trung Kiên
Phạm Trung Kiên

Posted on

My journey with Angular

Recently, I was assigned the task of upgrading an Angular project from version 4 to the latest version (version 18 at the time the project started). I had never worked with Angular before but had heard many people say that it was a great framework, easy to approach even for backend developers, so I was quite excited.

Out of habit, I looked for guides to learn the basic features on Angular's official site. I should mention that I was already familiar with React and Vue, so Angular's approach completely overwhelmed and... frustrated me. First, Angular heavily relies on rxjs, so you have to know how to use it. Alright, let's take a quick look. And boom, rxjs knocked me out! Maybe a decade ago, it was a great library to deal with "callback hell" but for me, it was overly complicated. Since I didn't have much time for the project, I made a rather risky decision to push it aside and try to convert all rxjs-related code into Promise. Of course, this wasn't easy, but I managed to pull it off.

The next thing that drove me crazy was component control. Incredibly, just to execute a simple control like if or for, you have to import an entire module! Then, to bind variables between TypeScript and HTML, you have to memorize a whole set of bracket rules. Want to pass an attribute? Use square brackets. Event binding? Use parentheses. Two-way binding? Use both. I don't understand what the Angular team was thinking when they defined such bizarre rules. Recent versions have improved some of these commands, but not significantly compared to React or Vue. For example, in React, passing data is as simple as propName={something}, and that's it. At this point, you might argue that these are just trivial things, like learning a new language and its syntax, but there's more. You still have to struggle with different ways to interact with components: ng-content, ng-container, @Input, @Output, etc. Angular provides a dozen ways to achieve the same functionality, which can feel overwhelming. Discussing all of them here will be off-topic, so I won't detail in this article. Some might call this flexibility; to me, it's cumbersome. In my project, I had to use some rather... heresy DOM manipulation tricks because Angular preserves components in the generated HTML, making the DOM tree more complex. Maybe I haven't spent enough time with Angular, so I found it difficult to handle things smoothly.

Forms were especially painful. My project involved multi-step forms, where each step had similar fields: entering a value and providing feedback if the user didn't enter anything. Naturally, creating a reusable input component was the obvious choice. Normally, you could create a RequiredInput component that takes a value and validates it, but Angular isn't that simple. Each field must be declared with a FormBuilder, must have a defined name, and cannot be directly assigned or passed to a child component. You have to declare FormBuilder in each component and bind it to FormModule. Suppose you have two fields, "Last Name" and "First Name"—you have to create two separate components instead of reusing RequiredInput, which is very cumbersome. If you also work with Angular, here's a great article on creating a reusable component that I wish I had found earlier (I only discovered it after completing the project 😢).

After overcoming the initial confusion, I started working on the project, and this was when the real nightmare began. Beyond finding replacement libraries for outdated or incompatible versions, the old codebase seemed to be written by beginners. They had no concept of clean code. Instead of leveraging Angular's advantages, such as type definitions, dependency injection, or inheritance, they created completely non-reusable components and mixed service logic directly into the UI. The project used a theme built with jQuery, so most of their work was just wrapping Angular around the components, while DOM manipulation still relied heavily on jQuery. Moreover, the gap between the two versions was so vast that I had to rebuild the project from scratch rather than migrate it.

On the bright side, I got to experience writing code differently from other libraries or frameworks, without worrying about state management or passing data between nested components, thanks to dependency injection. This is the only aspect of Angular that I found appealing - it’s easy to see why some backend developers like it. I also tried to stay away from rxjs (though this may not have been the best approach) and used the new standalone components instead of the old module-based approach. If you're also racing against a deadline like I was, you might find this starter template useful to save time on project setup.

After three months, I completed the project. If you ask me now whether I hate Angular—no, I don't hate it, but I wouldn’t recommend it to anyone. It's too complex and time-consuming to learn and implement compared to other frameworks. Frontend is not backend - if you want to write code like in the backend, it's better to just use backend frameworks like .NET or Spring.

Top comments (0)