I’m not a huge fan of asking a candidate questions like:
Tell me all the different lifecycle hooks that Angular components offer us, and tell me in which order they are being executed.
Questions like that could make our candidate uncomfortable and stressed out. I also don’t like to ask:
What's the difference between `markForCheck()` and `detectChanges()`?
I’d love to hear it in a response of another question I might ask but we shouldn’t focus on api specifics. Maybe sometimes I would ask for api specifics, but then it only means the candidate has answered most of the other things and he or she is really doing a good job. And let’s be honest… Everyone can memorize api’s…
Why would we ask people if they could memorize all the api’s a framework has to offer? When we can try to understand how they think and reason about problems and proper solutions? This is the reason we should focus on open questions that can be answered in many ways. The more open our questions are as to the candidates, the more we learn from the piece of talent we are interviewing. We only have limited time right?!
Our candidate can give us some nice twists like sidetracking on best-practices and bad-practices. I love to hear long answers where the candidate can show his or her passion about Angular and the surrounding experience.
For every question I will try to explain on how I personally would answer the question and why, so basically what could make me happy as the hypothetical interviewer. The concrete answers will not be found here, that is something you have to do on your own.
1: Name all the ways you can think about on how components communicate with each other in Angular?
This is a very simple question but can still be used to blow the mind of the interviewer.
I would start that the easiest way for component communication would definitely be the use of
I would mention that data flows from parent components towards child components through
@Input() properties and we
pass that data into the component with the square brackets syntax
[foo]="bar". The child component can notify the parent components
through the famous
@Output() properties and for that we use the square bracket syntax
Yes, yes this is also api specific, but let’s face it. If they don’t know that api they simply haven’t used Angular, and I have gotten
my share of candidates who were unable to answer that question.
I would maybe mention that for
@Output() names we should never use
onClick but we rather use
That is more consistent with the current api of Angular and it’s a known best practice.
I could talk about injecting parent components into child components through dependency injection in the constructor. I would focus even more on when I would do that and if it is a good idea in general. I personally consider this to be a bad practice in a lot of cases as it breaks the unidirectional dataflow and makes it quite complex. That being said, I can give an example on where I inject a custom form component into an input-wrapper component to see if the form is submitted or not.
I can go on about ViewChildren where one could gain access to child components within parent components. This also creates a form of communication. Maybe I step it up a notch and explain the difference between ViewChildren and ContentChildren.
Lastly I would talk about how to use services to communicate between different components and that in general I wouldn’t do that to communicate between children and parents. I’d say that it might be a good idea to let siblings communicate with each other. Although in many cases we can use the parent component for that. When we want to communicate between a parent and a child, but there is a router-outlet in between it might be a good fit to use a service for that.
Bonus question: Can you name a bad way to let components communicate with each other and why?
I would probably say we could use the window object to do that, but that it is not a good idea because we lose all the encapsulation and we should not communicate with the window object directly. It would create complexities, dependencies we don’t want and we are communicating outside of the framework.
We could also use redux or @ngrx/store to communicate between components. I would also consider this to be a bad practice since we are using a complex framework for something very simple and we are creating a very hard dependency in every layer of our code. That being said, this is a personal opinion and I’d love to hear the perspective of the candidate.
2: How would you structure components in Angular?
I would talk about smart and dumb components and what their responsibility is and how we keep them dumb components ignorant to the rest of the application but that they still can have complex logic. I’d probably give an example that a month view of a calendar is stupid, but can be very complex. I would say that splitting up into more and smaller components is beneficial for:
- Control over change detection when using the
- Less observable subscriptions
- Single responsibility principle
- Separation of concerns
I’d also keep a separate folder for smart and dumb components so they don’t get mixed up.
I could talk about when I would extract code from the component. I could talk about preference of inline templates or not and share the advantages and disadvantages for both ways. It’s important to show that that I am not biased and that both solutions could work.
Bonus question: Tell me the difference between pipes and components
I don’t think this question should be answered here since it’s a very straightforward question.
3: Dependency injection, services, lifecycle of services and use cases. go!
With this question we can really show that we know exactly how Angular works in terms of dependency injection.
I could talk about services and how to make them injectable. I would say that we can provide services in modules and
that they would become singleton for the entire application. After that I’d say that we can also provide them in
lazy loaded modules (by using providedIn:’any’) which would result in singleton at that modules level. Then I could explain how we can also
provide them at any component and that the lifecycle would be shared with those components.
A nice addition there is to mention that if we provide them at component level we could also implement
ngOnDestroy() lifecycle hooks
in the services. Some nice examples on services in components would be very welcome and I would probably say I could use it
to remove redundancy from 2 big fat smart components that share 80% of the same code.
It would be my moment to mention that I prefer composition over inheritance.
A nice addition would be explaining the
providedIn: 'root' syntax in the
Injectable() decorator and that this creates an
application wide singleton instance. It would also be worth mentioning that this improvement was there to make treeshaking possible.
This is a great moment to start about the standalone components that Angular 14 brings with it, and I could give my opinion on Angular modules in general. By mentioning that Angular modules were introduced in angular2@rc5 I could prove my experience.
The reason why I am saying this is not to brag, it’s to show how deep you could go with this question.
4: What’s the difference between guards and interceptors?
I like this question because we ask 2 things at the same time. Guards and interceptors don’t have anything to do with each other
but they are important tools within the framework. After explaining what guards are I could come up with examples on either
when to use the
canActivate guard but also explain the less often used
canDeactivate guard. A nice example there would be when
the user has filled in a form and we don’t want to block him from navigating away.
I would explain that I don’t only use interceptors for adding jwt tokens but I could also use them for loading state, error handling and so much more.
5: What is the
Not only could I say we could use the
async to subscribe on observables, I could start talking about RxJS and that it is the only real dependency Angular has besides zone.js.
I would say that the async pipe, subscribes to the observable, also unsubscribes from the observable when the component gets destroyed and I would talk about
how it runs a
markForCheck() as well.
I would say I consider using the
async pipe as a best practice because it does a lot of management for us (subscribing, unsubscribing, mark for check).
Maybe I would even talk about the
*ngIf=foo$|async as foo syntax where we can keep the value of the observable inside the template
and share it like that. I could mention that it can be dangerous if foo has a falsy value.
6: Tell me about RxJS in Angular, what reactive api’s are there?
This is a beauty because you can talk about so much here.
It might be a good idea to start talking about my passion in RxJS first and how I fell in love with it.
After that could talk about how the router is reactive and that we can subscribe to events.
The activated route gives us observable params, queryParams and so much more.
We could talk about Reactive forms and how the
valueChanges property is observable.
ViewChildren and ContentChildren can also be observable.
I would also like to talk about the
HttpClient returning observables instead of promises and that unsubscribing from
an observable that is performing an XHR call will result in an
xhr.abort() behind the scenes.
If I want to blow the interviewer his mind I’d mention that
@Output() EventEmitters are also observables behind the scenes and that
you can replace the EventEmitters with any kind of observable
7: Give me an easy way to create a memory leak in Angular and how to fix it. Eg setInterval()
If the candidate does not understand the question: You have to add a
setInterval(console.log) statement somewhere in a piece of code
that will be destroyed and we want to keep seeing numbers logged in the console.
This should help the candidate enough. What will get destroyed and reinstantiated? Components will.
So adding that piece of code in the constructor or
ngOnInit() of a page that is a component and navigating away from that
could do the trick. By clearing the interval on
ngOnDestroy() we could clean up that memory leak.
I would start on how easy it is to create memory leaks with RxJS and that it’s important to always clean up subscriptions. This might be a tough question but we could really peek into the reasoning of the attendee here.
8: How would you test Angular applications?
This question has a lot of different answers, and none of them are right or wrong. But it’s a great way to see how the candidate feels about testing, where the priorities lie and how much experience they have with testing Angular applications.
I would first talk about the testing pyramid vs snowcone and how today I prefer something like the honeycomb principle:
A small amount of unit tests (only the real complex logic), a lot of integration tests for the components, a small amount of E2E tests
to test the happy flows.
I would say something like I unittest the real logic in services and I don’t use TestBed but
jest just like I would test
For components I use a combination of
storybook as integration tests were we would create a storybook of the usecase
we would test and use
cypress to do so.
I would also use
cypress to tackle the E2E tests, but since these are slow and hard to maintain I wouldn’t write too much of them.
I would challenge the use of a huge amount of unit tests because they are very brittle (an extra dependency in the constructor breaks every test).
and if we break a
storybook integration test chances are quite big that we actually broke something.
9: Explain to me how change detection works in Angular
Here I could talk about
zone.js monkey patches all the native browser events and that Angular uses it to get notified when something happens.
I could talk about how Angular takes the component hierarchy and by default evaluates all the components from top to bottom.
I could say that this isn’t the most performant thing to do and could explain how the
ChangeDetection.OnPush strategy helps us with that.
When talking about that strategy we could explain the
markForCheck thingy and the difference between
ChangeDetectorRef.detectChanges(). We could also explain that we need immutable data flows to make this work and that it does not make sense
to use the
ChangeDetection.Onpush strategy on components that don’t have any inputs.
I would sidetrack on the advantages of immutable data structures and that its predictability is of more use than the performance gain.
It might also be worth noting that the
async pipe also triggers a
markForCheck, but we already said that didn’t we?.
Bonus question: What happens if you apply the
ChangeDetection.OnPush strategy on your app component?
I could explain here that it’s not a good idea to do that because it will basically break your change detection and you have to manually
markForCheck() for everything. A nice example could be this one:
When we do an
httpClient.get('url').subscribe(result => this.result = result) in our code. Our application will never update because it isn’t marked for check.
Also the change detection deep within your component hierarchy could be broken. Another thing is that our app component doesn’t have any
@Input() properties so it is useless anyway.
10: What is the Expression has changed after it was checked error?
I would start to laugh about the fact that this bug has bitten me in the butt more than once and explain when and how much it has occurred. I would say that the change detection ran twice in development and that both results are compared. If the results that are used in the template don’t match it means something has changed in between proving that there is something wrong with our “clean” dataflow.
I could also explain why this isn’t run in production and that even the bug is harmless, it does shed some light on problems.
11: How can you tackle redundancy in Angular?
Very open question, if you are a senior profile you could talk for tens of minutes but I will wrap it up quite shortly here:
- We can extract logic into reusable components
- We can extract logic into reusable directives
- We can extract logic into reusable pipes
- We can extract logic in services
12: What is trackBy and how does it work?
This question proves a level of seniority of the candidate within the framework.
I would explain that every
*ngFor statement could benefit from that and how the performance is optimised.
Especially with big lists this property can have a huge impact.
13: Tell me about Angular CLI.
Here I can talk about code generation, about webpack. Maybe if I really want to make an impression I can talk about
why you think they chose for
webpack and not
rollup. Maybe mention why I think it wouldn’t work with
I could talk about schematics and that there is a thing called Nx that takes the Angular CLI to the next level.
I could talk about updating to new versions. I could talk about ng-packagr and how I would create a public Angular package.
I would talk about the CLI sets up webpack configs, unit test configurations, prettier config, linting config files etc.
14: How do you consume params from an ActivatedRoute and do you see complexities there?
Here I could say is that injecting the
ActivatedRoute gives us observables of params but also snapshots if we want.
I could say that it only has access to its own params, and not to the params of its parent router-outlets.
Unless we set the
paramsInheritanceStrategy of the routerconfig to
always that is.
I would share frustrations that it is complex to access params from child router outlets and that it should also be available because they are available in the url, but that I believe they have developed it like that to support auxiliary routes.
I would use this question to talk about how I love nesting router-outlets and using them to display dialogs so that Angular takes care of the lifecycle for me.
One last thing to mention here is that when a param changes, the component is not being destroyed and reinstantiated.
15: Name your 3 favourite Angular characteristics
This question speaks for itself. You can verify experience, reasoning, passion and the ability to challenge technical decisions by listening to the candidate talk.
My personal favorite is the integration with RxJS, the fact that it is opinionated and I think it is suited for huge projects.
16: Name your 3 biggest Angular frustrations
This question also speaks for itself. You can verify experience, reasoning, passion and the ability to challenge technical decisions by listening to the candidate.
My biggest frustration is its bundle size, the build time and the ReactiveForms. I would continue on the fact that it is nice that Angular 14 gives us typed forms but that I see a lot of improvements there.
17: Explain how you would do content projection in Angular
I could start out by the fact that you can have an
<ng-content> slot and whatever I put between the tags of my components would be rendered there.
I could also mention that you can have multiple slots that I could name. And that all these slots can be referenced in the component
@ContentChildren(). After that I would probably start giving examples on where to use multiple slots like dialogs that have
both a title and a body section.
After that I could also explain that there is a thingy called
ngTemplateOutlet but to be quite honest, that kind of stuff is the
stuff I have to look up every time I need it. That being said, mentioning the existence of it is way more important then
knowing the api by heart.
I could even say it is possible to render content from the right view into the left view by using services to pass template references, but now I’m just trying to be smart even though it is possible.
18: Tell me something about selector prefixes.
Again a question where you can validate the experience and reasoning.
- I’d say every component selector has a prefix, but selectors aren’t even mandatory so prefixes aren’t either.
- We pass these prefixes so they are unique and it’s easier to see where they live.
- We use linting rules to validate if the prefixes are used correctly
- Both components and directives can have prefixes.
- It’s a bad practice not to have prefixes.
- Prefixes are both stored in the
project.json(for Nx) and
angular.json(for Angular CLI) file for schematic generation of components and directives, and they are also defined in the linting config files
This question is different then the other ones, here the candidate can just make a list of all the things he or she knows about a simple subject.
19: What version upgrades of Angular were really exciting for you and why?
This is a very easy question to check on seniority or if the candidate is up to date with the newest version.
At the time of writing I would talk about standalone components and typed forms in Angular 14. That is was pretty weird that there was no Angular 3 but that I understand why.
I would go on that I was pretty frustrated that angular2@rc5 had modules when angular2@rc4 had not… And that I had to rewrite my Angular fundamentals workshop just before my public workshops were planned.
I would go on that the upgrade path had gotten easier and that updating to Angular 6 was a pain in the butt for me.
I’d probably also be a bit more negative about Ivy because at ngVikings they showed a hello world of a few kilobytes but that never seemed to become reality.
You see the question here shouldn’t be about remembering versions, it should trigger the candidate to talk about his or hers experience with Angular and which updates were important.
20: Who do you follow? Which blogs do you read? What do you do to keep up to date with Angular?
This is one of my favorites. One could talk about pluralsight or egghead trainings. They could mention Angular core team members, or interesting pull requests. They could talk about conferences or at least a talk they were interested in. They can talk about books, interesting talks with colleagues and so on. They can talk about pet projects and stuff they are doing in their own time.
This is a great question: not to test seniority, but to test passion and motivation in the framework.
Keep the questions limited, keep them short and expect long answers. You might be surprised how smart our candidate is. Every body can learn a framework, but not all of us can learn to reason. And syntax is easily forgotten of it has been a few months or even weeks until we have used it in practice. Hope you enjoyed the article!
Special thanks to the awesome reviewers: