Debugging without breakpoints

I covered the Angular Devtools extension in a newsletter entry last year, and this browser extension keeps getting better and better.

For instance, with Angular 17, an injector tree view feature was added.

With the addition of signals to the framework, we get even better insights and access to our data in a static way that doesn’t require any breakpoint. For instance, if you want to see what’s the current value of a signal in one of your components, the extension shows that value:

We can tell right away that title is a Signal and that the current value is “Welcome to our store”. With Observables, we don’t have that luxury:

So that’s one more good reason to use signals in our Angular applications and perhaps one more reason to try the official Angular dev tools extension if you haven’t done so yet.

Another cool feature is that when you select a component in the tree view, you can see the text "== $ng0" showing up next to the component name:

This $ng0 is a variable that can be explored in the browser’s console. If I type $ng0 there, here’s what I get:

I can explore that component and any service injected into it right from the browser’s console—no breakpoint is needed.

Bonus tip: If you selected another component previously, it is now known as $ng1. The one before that, $ng2, and so on.

Tutorial: Architecting forms with Signals

In today’s post, I want to showcase several Angular framework features in one example. More specifically, we’ll use standalone components, signals with model() and input(), as well as forms.

Our goal is to build a reusable date-range picker component to select two dates:

To do so, let’s create a standalone component with two HTML date inputs (no need for component libraries!):

We use ngModel (which is from FormsModule) to capture the current value selected by the user and set a default value for those dates if needed. To do so, let’s use two signals created by the model() function from @angular/core:

Two important things to note:

  1. These two variables are signals and work seamlessly with ngModel
  2. These variables enable two-way data bindings with the parent component as follows:

start and end are signals as well. We can use those signals to pass a default value to the child component or keep that value empty if we don’t want any:

And that code is 100% functional as-is. No need for template-driven forms or reactive forms! Now, let’s add some features to our date-range picker component. Let’s say we want to enforce the rule that the start date cannot be after the end date and vice versa. The following bindings do the trick using the min and max HTML attributes:

Because this is all based on signals, it’s all reactive by default. Changing the start date or the end date automatically updates the range of what’s selectable in the other date input:

Adding more features is now as easy as adding more signals and bindings. For instance, I want to enforce a minimum start date. I added a new signal input called minDate and I bind it to the min attribute of our startDate:

And then, in the parent component, we can pass a minimum start date:

You can find that code example in action on Stackblitz here. Note that our date range picker has less than 20 lines of code and relies on basic HTML features (input, min, max) instead of adding dependencies that would impact performance.

Please email me if you’d like me to add more features to that example in a future post. I’m always happy to cover what really matters to most people reading these posts.

Talks on Signals, SSR, and Angular 18

I’m giving several talks at free conferences and events this week, so I thought I would share those with you in case you’re interested. As always, all of these are free for you to enjoy.

Two of those events already have a recording available on YouTube:

Then I’m speaking about Signals at Frontend Nation on Wednesday (25-minute intro to Signals at 11 am US/Pacific) and Friday (2-hour workshop on Architecting Angular apps with Signals). You can register here.

Last but not least, I’m doing a webinar with ng-conf on that same topic next Tuesday. Registrations are open here as well:

This will close my marathon of talks for June! We’ll be back to our regular weekly newsletter next week.