So, you have joined your first front-end development project using Angular; Congratulations! Whether you are new to web development or a seasoned veteran, joining a new project using an unfamiliar technology can be simultaneously exciting and stressful. On the one hand, you will be gaining real world experience with Angular in a market that increasingly demands it. On the other, navigating through an unfamiliar code base as a new Angular developer can be incredibly daunting.
As a tech lead, I found that this was almost always the sentiment felt by developers for whom I helped onboard to an Angular project. They wanted to be productive as soon as possible, and they just needed a bridge between the existing code and what they learned from tutorials. In this blog post, I’ll cover the basic debugging techniques I always share with developers new to Angular. As developers, we are tinkerers—we open things up, examine them, and break things—it’s how we learn best. I’ve found that once developers are aware of these techniques, they quickly become self-sufficient and are quicker to learn the framework simply because they can tinker.
Navigating through an unfamiliar code base as a new Angular developer can be incredibly daunting.
Before we dive in, note that I am using Google Chrome as my browser to demonstrate the techniques in this article. You should be able to replicate everything I demonstrate with any other modern browser—your developer tools might however, look different than what is shown here.
Identifying Existing Components
When I onboard a new team member, I have them run the application locally and get familiar with the existing workflows. I want them to understand the big picture before they look at a single line of code. This also allows them to see existing behaviors that they may need to reproduce elsewhere when they start coding; why reinvent the wheel when you know it already exists somewhere in the code base?
Once they’ve gotten comfortable with the application, I show them how to identify the Angular Components on the UI so they can bridge what they see with its corresponding source code. With the Angular application running in the browser, I have them open developer tools (F12) and click on the Element Inspector icon at the top left of the menu.
The trick is to click on the area of the UI that you’re interested in so you can work your way up the DOM and identify the closest elements with custom tag names—these represent our Angular Components – Angular calls those custom tag names Selectors. They are unique to each Angular Component, allowing us to search the code base for these and find their corresponding logic.
I’ll use the famous Tour of Heroes demo as an example. Look at the UI below; I’d like to know what component is involved with the list of hero names. Using the Element Inspector, I’ll click in the general vicinity of the list. Note you don’t need to be a sharpshooter. As long as you wind up clicking some element that’s a descendant of a suspected Angular Component, you’re fine.
Looking at the first snapshot, you’ll see that I selected an anchor tag around the “Narco” tile. In the second snapshot, you see that the anchor tag is highlighted in the DOM, and at the bottom of the Elements tab, we see a hierarchy of its related elements. In the hierarchy, each element’s parent is to the left. Therefore, it appears our selected anchor is a descendant of two custom tags (i.e., Angular Components) “app-dashboard” and then “app-root.”
Custom tag names can be completely divorced from a component’s actual name in the source code so let’s do a quick search in Visual Studio code. The element “app-dashboard” was the closest parent to our selected anchor tag. If you pay attention to only the TypeScript files that are returned in the results, you’ll see we can easily identify that this belongs to the DashboardComponent because of the defined selector on line 6.
Now that you’ve identified the Angular Component, you can look at the logic involved in both the template and the TypeScript. What is its purpose? Does it communicate with other components? What services does it utilize? Etc. If the first Angular Component you’ve identified is too granular and doesn’t provide much insight into the process, you were curious about continuing up the DOM. In our example here, the next Angular Component had the Selector “app-root.” Using this technique, you’re able to have a jumping-off point to understand Angular Component hierarchies and the ways in which they communicate.
Be Aware of Source Maps
In short, Source Maps are utilized by the browser for the benefit of developers so they can debug logic using the original TypeScript code.
I stress the importance of being aware of Source Maps because without them, the next set of techniques I’m about to explain won’t work. Out of the box, the Angular build process is configured to create Source Maps. This can be altered, especially for production, when the development team wants to keep the resulting Angular bundles small. New Angular developers are often dumbfounded when they get to a QA environment where they’re no longer able to debug their TypeScript. It’s often because QA was configured to be as close to production as possible, and thus source maps are turned off.
Walking through the TypeScript
Once you’ve identified the Angular Components that you’re interested in you’ll want to set breakpoints in the code so you can follow along to gain a better understanding of what’s going on. I’m going to show you how to do this efficiently using Chrome’s developer tools. Following our Tour of Heroes demo app, let’s set a breakpoint in the DashboardComponent.
Don’t Get Frustrated with Callback Functions
Something that often catches new Angular developers off guard is how to debug callback functions for subscriptions, as shown on line 21. You can’t set a breakpoint on line 20, step over and get to the logic on line 21 where the callback is defined.
As shown above, the execution context will just jump over the callback. When developers see this, they often figure they need to set a breakpoint directly on line 21 instead. Still, this results in the debugger not working as the developer expects and because the breakpoint hit when the subscription occurs but not during the callback.
To pull off the desired behavior, especially for these common one-line callbacks, you need to set a breakpoint within the callback itself. See below how I click on one of the translucent arrows to do this
As a final note on subscriptions and callbacks, ensure you’re taking advantage of conditional breakpoints whenever dealing with an observable that emits frequently. I’ve seen new Angular developers burn through a lot of time stepping through callbacks waiting for a particular situation to occur. To do this, right-click where you want to set a breakpoint, and in the dropdown that appears, click on “Conditional Breakpoint.” In the modal that opens, enter a condition in which you want the debugger to stop—don’t forget to null check!
Manipulating Behavior from Developer Tools
Sometimes to get the bottom of an issue, it’s helpful to know the current state of a given Angular Component. Angular makes it easy to do this by exposing a global variable named ng that helps you probe components in the browser using the developer tools. Note again that the ng variable will only be exposed if the Angular application is in development mode. For a full list of what the ng variable can do see: Angular – @angular/core/global
Let’s walk through a simple example together so you can get a feel for the kind of power the ng variable provides you while debugging. Looking at our Tour of Heroes UI, let’s say I want to know the state of my “HeroesComponent”. Open your developer tools and look at your elements panel, as shown below.
You may have noticed this earlier, but in the elements tab, sometimes there is an odd “== $0” label shown. “$0” is a variable you can access in your developer console and references whatever DOM element you may be focusing on in the UI—in my case, I am focused on an h2 tag. Note that the value of “$0” changes as we focus on different DOM Elements whether we change focus directly in the Element tab or view the Element Inspector tool.
To look at the state of a component, we’re going to use ng.getComponent($0) in the console. Note that this function takes in reference to a DOM element that references an Angular component. If I execute this now while focusing on just the h2 element—a child of the HeroesComponent—the function returns null. If we instead focus right on the HeroesComponent DOM element executing the function returns an object with all the Angular component’s public properties.
With this object, not only can we read properties, but we can also manipulate them on the fly. If I wanted to add another hero to this list, I could right from the console. Let’s add “Angular Man” to the list by directly pushing an object onto the “heroes” array we have access to.
The first highlighted line on the right shows how to change the live data on the fly. If you only executed that single line, you’d notice, however, that on the left, the new “Angular Man” list item does not immediately appear on the UI. This is because we have done something unusual and altered something outside of Angular’s change detection; we need to manually tell it to detect our changes. As you likely guessed, that’s where the second highlighted line on the right comes into play. Once you execute that, you’ll see the new list item as expected.
This technique does not alter your source code whatsoever, and any changes you make will be cleared out after you refresh the page. If that’s the case, then why make alterations like this? I personally do this a lot when I’m trying to get to the bottom of an issue and need to force some states onto a component so I can set a breakpoint and walk through the code as many times as I want. Beyond just altering values, I’ll use this same technique to manually call public functions in a component just to step through them. This saves me from having to temporarily alter source code to specifically test a particular scenario. It also saves me from having to rebuild the application every time if I’m experimenting with small changes.
Interested in learning more? Check out these other Tallan blog articles concentrating on the Angular building platform:
Click here to learn more about our custom application and software development solutions.