This page shows the source for this entry, with WebCore formatting language tags and attributes highlighted.
Title
Angular is pretty specialized
Description
<img attachment="angular.webp" align="right">I recently had a conversation about the pros and cons of using Angular and I found this year-old article that I'd prepared from my notes but never published. The article
<a href="https://software-engineering-corner.zuehlke.com/two-way-binding-between-signals-and-query-params" author="Julio Castro" source="Software Engineering Corner by Zühlke Engineers">Two-way binding between Signals and Query Params</a> includes the following code snippet.
<bq><code>@Component({
selector: "app-root",
standalone: true,
imports: [AsyncPipe],
template: `
<h1>Signals Demo</h1>
<p>Your first name is: {{ firstName$ | async }}</p>
`,
})
export class AppComponent {
private activatedRoute = inject(ActivatedRoute);
firstName$ = this.activatedRoute.queryParams.pipe(
map((allQueryParams) => allQueryParams["firstName"])
);
}</code></bq>
I cannot describe how gross I think Angular code is. <i>None</i> of this is "using the platform". This is all JavaScript-first. It's all custom, untyped, string-matching, gobbledygook. The <c>firstName$</c> in the template isn't checked. There are no type-safe views.<fn> What the hell does <c>| async</c> do? I'm sure it's convenient, but this is more obtuse-looking than modern React.
The injection is also just magic that you have to know about. And why is it injected differently than the <c>AsyncPipe</c>? There are probably good reasons for it, <i>in Angular</i>, but it looks pretty slapdash and ad=hoc as an API. It's like there's a different symbol or character or concept for every possible thing. The <c>imports</c> is in a custom place. It's all packed into a <c>@Component</c> decorator that does a bunch of magic for you to build what is probably a web component (but I'm not sure). They wrapped every single possible API in something custom to Angular.
I hope I'm wrong, but this is so unappealing.
Reading a bit further and we see an example where some of the noise---e.g., the <c>async</c> pipe---has been removed <i>because of the magic of <b>signals</b></i>.
If you're learning Angular, you're not learning anything portable about web-programming. You won't know HTML, you won't know CSS, you won't even necessarily know JavaScript or the browser APIs. You don't use the platform. It's a shame because the platform is already so powerful. In the old days, you needed a framework to shield you from the differences. Nowadays, the platform is more than well-specified, -supported, and -implemented to just write to directly. Learning the platform API is just as easy as learning whatever I'm seeing in Angular.
In fairness to the article, though, it's well-written and offers some good techniques for making the best of a bad situation if you have to work in Angular. 🙃
But then there's this.
<bq>Since we are accessing the value of the <c>allQueryParams</c> signal in the effect, it will run every time this signal gets updated, which happens every time Angular emits a new value in the <c>activatedRoute.queryParams</c> observable.
Inside the effect, we are just updating the value of our <c>queryParamValue</c> signal. For that, notice that we need to pass the <c>allowSignalWrites: true</c> option. This is necessary because updating signals in effects could lead to infinite loops and unexpected and intricate situations in general.</bq>
This is the same kind of black magic for real-life situations as you see in React these days. I'm still a fan of using MobX for the state model, then attaching it to pure reactive web components. I'm still deciding whether that will scale to what I need, but I'm more and more convinced that none of the huge frameworks are the way to go. They're just so much wrapping and bizarre APIs that feel legacy before they're even officially released.
I'm not going to copy it in here but the final version of the read/write signal service based on query-parameter values is 41 lines of hairball code. Do I know how much code it would be to achieve something similar outside of Angular? No. No, I don't. I just know that if I ended up having to learn how to do it and write it---and even if it ended up being more code---I would have learned the general platform and built a service that can work in any web site, not just one framework.
<hr>
<ft>A colleague confirmed for me just last week that this is still the case, even in the latest versions of Angular.</ft>