With its highly scalable architecture, many web development teams choose Angular to create efficient, sophisticated single-page applications. But, hiring Angular developers is easier said than done. While there are many candidates out there, the key to a seamless development experience is finding a great Angular developer, one who applies best practices and advanced techniques to meet high-quality coding standards.
Understanding key concepts about Google’s popular front-end framework will prepare you to confidently interview prospects and hire the highest-caliber developers—those who strive to bring a codebase to the next level. This article lays out the crucial skills and knowledge that a premium Angular professional should have.
High-quality Angular candidates will be those who:
- Know the core functions of Angular.
- Design before they start to code.
- Understand Angular application lifecycles.
- Have a solid knowledge of reactive programming.
- Know what state is and how to use it.
- Are skilled in and supportive of automated testing.
- Stay informed about the latest Angular releases.
Note: This guide applies to the latest Angular versions, which are no longer known as AngularJS—“Angular” has applied since Angular 2. If you’re hiring for the maintenance or upgrade of a legacy AngularJS web application project (the 1.x branch), check out How to Hire a Great AngularJS Developer.
Know the Core Functions of Angular
So, ask the candidate if they have knowledge of HTML5 and CSS3. A good Angular developer does not need to be an HTML or CSS expert as long as someone else on the team is, but they should understand these key concepts:
- SCSS variables
- The difference between a
- The important classes in CSS
Design Before Coding
Good design is the key to good application architecture. Ask your candidate how they make their designs and compare their thinking with these ideal considerations:
- Where will the code go? Is there need for a new library or a module?
- What are the inputs and outputs?
- Should there be any reusable components or directives?
- Where will the state go? (Discussed further under State Management below.)
- Where will the business logic go—i.e., in which service?
- Can certain components be shared among libraries to create, essentially, a UI design system?
The full specifics of a particular design are less important than whether the candidate is in the habit of making designs. All designs are temporary so, for most applications, documentation can be as simple as a photo of a sketch on a whiteboard unless formal documentation is required. At a later stage, the developer can generate the technical design from code (with the right tools) to make it clear how all the parts interrelate.
Understanding Angular Application Lifecycles
Ask your candidate what they know about the Angular component lifecycle. Their answer should include three lifecycle hooks:
ngOnDestroy. As the names suggest,
ngOnInit is called at component initialization,
ngOnDestroy is called when the component is destroyed, and
ngOnChanges is called when an attribute changes. The latter can occur before
ngOnInit—when the attribute is already assigned before the component is completely initialized, then
ngOnChanges is executed before
If the candidate also knows about
ngAfterViewChecked, they know all the change detection hooks for components and are a step ahead.
A good follow-up question to ask about any of the hooks: “When does this change detection happen?”
A lesser-known lifecycle is the provider lifecycle, which has only one hook:
ngOnDestroy. This is called only when the provider is attached at the component level, in which case it gets destroyed together with the component. If it is provided at the root or module level, it will never get destroyed.
The constructor of a provider will be executed the first time the provider is used, so it is possible that the constructor will never be executed. Quiz your candidate about this possibility—in real-world scenarios, it can be an often-overlooked source of bugs!
Solid Knowledge of Reactive Programming
In an Angular application, reactive programming is often the hardest part to understand. Many people think in a procedural way when they start programming a piece of code, assuming that it’s easier to understand and work with, like the steps of a recipe.
Reactive programming involves reacting to things we cannot control, and that may occur in an unpredictable order. Although we react to things in this way every day—for instance, braking when the car in front of us suddenly stops—many developers find it difficult to take a reactive approach to programming.
But, everything that happens inside an Angular app is based on reactive programming. Some examples of reactivity in in an Angular shopping application, for example, may include:
- When the user logs in, the number on the shopping cart icon updates, and menu items change to more specific options.
- When the user navigates to a category, the products update depending on the selected category.
- When the user adds a product to their cart, the shopping cart icon updates with the number of products.
- When an item is out of stock (registered through a listener monitoring current stock quantities from the back end), the page UI updates.
Note that these things happen automatically, and do not need a page refresh to appear. In an interview, ask the candidate to describe how they applied reactive programming in an application they developed. If the candidate describes solutions that involve refreshing the page or manually calling
ChangeDetectorRef.detectChanges() to refresh a component, consider that a yellow flag.
Pitfalls With Observables in Angular
Less-experienced developers may sometimes find that the code they write in their Angular applications does not get executed. Seasoned Angular developers can identify a common cause: There is no subscription on an
Observable, a mainstay object type in reactive programming. Only with a subscription will back-end calls or other reactions be executed.
There are two ways to create subscriptions: Developers can use the
async pipe or the
subscribe method. But there is a caveat: If developers do a manual subscription (with the
subscribe method), the
Observable will need to be destroyed manually (although there are some edge cases where it happens by default). Developers can destroy
Observables in multiple ways:
- Using the
asyncpipe, where possible (this destroys the
Observablewhen the component is no longer needed).
- Manually unsubscribing by using the
unsubscribemethod on an
Observableat the end of the lifetime of the component (
- In a more declarative way with the
takeUntiloperator inside the
pipeoperator, and using a subject (i.e., something named like
destroy$). In this case, the subject emits
destroy$.next()at the end of the component’s lifetime (
ngOnDestroy). After receiving the destroy event, the
takeUntiloperator will no longer accept events from the Observable that it’s bound to so that its subscriber logic will no longer be triggered. For an example, see the takeUntil operator in section 2. Similar functionality can be exposed with the
- Since Angular applications switched to the Ivy compiler, we can also use annotations. The
until-destroylibrary or another third-party library like SubSink can be used to smoothly unsubscribe from observables once a component is destroyed.
Another potential pain point with reactive programming comes from memory leaks and multiple calls to the back end. Ask the candidate if they are aware of these problems, and how they would normally solve them. Memory leaks can occur by failing to unsubscribing from
Observables as described above. Multiple calls to the back end because of multiple subscriptions on a back-end call can be solved by sharing the
Know State and How to Use It
All single page applications have a state, and this state is available somewhere on the front end. But what is a state, exactly? It contains all the variables specific to the current user experience. For example, authenticated user details like name and profile image URL, a specific menu item selected, or an on-screen list such as a list of shopping cart items.
In an Angular application, there are three main types of front-end state to consider:
|Application||General information available to the entire application such as authenticated users, user roles, menu items, or a user’s shopping basket. Anything that changes in this state will change for the whole application.|
|Module||Information available to the entire module where a service is used. Every time a developer reuses a module with providers, it creates a new instance of each provider. The state will never be destroyed and will only be created the first time a given provider is used.|
|Component||Information available to a certain component. Components are the smallest parts of an application. An Angular application can have multiple component states, but they will only be accessible through each component. The state will be created when the component is created and destroyed when the component is destroyed.|
A good understanding of what state is, and when it should be loaded or reloaded, is one of the key skills to look for when hiring Angular developers. This is prime territory to explore if your team has the opportunity to review some example code written by the candidate. If the applicant is using a library for state management:
- Look for the use of NgRx, Akita, NgXs, or similar state-management-specific libraries.
- Then look to see whether there are any notifications for
selectorin the related code.
Let’s look at the general flow of the application state in NgRx (which is similar to that of Akita and other libraries) as an example:
If the developer creates their own state with services, their competency in state management can be harder to identify:
- Search for references to the words
- See if the code is reacting to some action, e.g., if the user presses Button A, the text should change on Screen B.
Questions for Interviewers to Ask About State
You can’t always find out everything you need to know by investigating an applicant’s code. Add these queries to your question list to investigate how well potential Angular developers understand state:
Where have you used
state—and how? This is a solid starting point to understand their experience with state; don’t be afraid to probe for specifics.
- How do you make a decision whether or not to use a library? It’s a good sign if they know it’s not always useful to include a state library in an application.
- What would you put inside the state, where would you put it, and how do you make use of a state management system? If they say, “I put everything into my global application state,” this is a sure sign that the developer is not aware of the negative side effects that such a system can give an application.
Developers who understand the various state types will avoid these side effects:
- State that only applies to one component could get modified or corrupted by other components.
- Data is nested in the store, so it becomes hard to keep track of the data, and the data becomes human-unreadable (for the purposes of debugging, data exchange, etc.).
- Editing data inside a form already emits it to the rest of the application, whereas it should only be pushed to the store when saving the data—in other words, the rest of the application might be consuming invalid data.
It doesn’t take long before the global store becomes a disorganized mess, and it’s not clear where each part of the mess originates, making it harder to debug and maintain.
Understanding the Importance of Automated Testing
Automated testing should be considered as important as code quality for any Angular web application. One of the major reasons for programmers to write tests is to document their code: If a new developer joins the company, the business logic and certain UI flows should be clear based on the test suite’s expectations. Also, automated testing reveals bugs early in development.
Ask your potential Angular developer three testing questions:
- What are your thoughts on testing? Any candidate who doesn’t care about automated testing should cease to be considered. Even if they prefer not to use test-driven development (TDD), developers who fail to see the value of automated testing will cost your company manual testing time and, worse, end-user downtime when regressions appear as changes are made to an app over time.
- What do you focus on when testing? Rather than testing basic givens like being able to assign values to a field or striving for specific test coverage metrics (i.e., 85% coverage), a great Angular developer should focus on testing core business logic.
- Are there usually more E2E tests or more unit tests? Why? As front-end applications, Angular apps can leverage two main kinds of automated tests: unit tests and end-to-end (E2E) tests. Typically, a test suite will have many unit tests and fewer E2E tests. Unit tests are small, so they are fast to write and execute. E2E tests are bigger and slower. Fair warning: Not all developers will have the same opinion as to the correct ratio of unit and E2E tests to maintain. In reality, it depends on the complexity of the app being tested, and even then, the answer is debatable to some extent.
Angular Testing Frameworks
Angular developers have choices when it comes to automated testing frameworks. Unit testing can be performed through Jest or Jasmine and Karma. Every Angular developer should be familiar with Jasmine and Karma. Jest is also common—it’s generally faster and features more advanced testing options.
The E2E testing standard for an Angular application is Protractor, the default tool generated by the Angular CLI. An alternative is Cypress, a promising E2E testing framework with a lot of options.
Be sure that the candidate has in-depth knowledge of at least one unit testing framework and one E2E testing framework.
Staying Informed About the Latest Angular Releases
Great Angular developers may not always use the latest version in development for various reasons, but they should know the Angular release schedule so they can stay abreast of changes and be prepared to switch. One way to assess this is to ask the candidate if they are familiar with the release strategy of Angular. Angular aims for a major release every six months, typically around February and May. An Angular release is under “active support” during the first six months after its release date, and is under “long-term support” for 12 months after its release date. This is a fairly tight timeline compared to some other technologies, making it particularly important to stay current.
You might also do some research about the most recent version of Angular, and ask your candidate about the benefits of these new features. For example, around the time that Angular 14 was released, you might have asked the candidate about:
Standalone components, which reduce the need for Angular modules. Standalone components are not declared in any existing
NgModule, and they directly manage their own dependencies. As a result, they can be depended upon directly without the need for an intermediate
Typed forms, another major update in Angular 14, which set strict typing as the default for Angular Reactive Forms. Typed forms ensure that the values inside
FormArraysare type-safe across the entire API surface. This enables safer forms, especially for deeply nested complex cases.
The Next Great Angular Developer for Your Front-end Team
Every web development project and team is different and will place different importance on the various aspects of an Angular developer’s skills and knowledge. But understanding the foundational topics we’ve presented here will allow hiring managers to participate meaningfully in hiring—even in the more technical evaluations.
The Toptal Engineering Blog extends its gratitude to Ramazan Yıldız for reviewing the technical concepts and diagrams presented in this article.