Angular — Stop Already!

Mike Brown
14 min readMay 5, 2018

I started writing this article maybe 6 months ago. I didn’t publish it then because I thought it come across as bit angry because, well… I was feeling pretty pissed off at the time! I also thought that the last thing the Web Developer world needs is another Angular vs React click-bait article.

Having re-read and partially rewrote it now, I thought “what the hell”!!

Intro — Know Thine Enemy

Angular 1’s incomprehensible popularity in the enterprise has given later versions of Angular a huge advantage in the race to replace it, even though:

  1. Angular 2 and higher (current version is 6 as I write this) are completely different frameworks to Angular 1.
  2. It’s still not very good.

Letting poor stuff like Angular propagate throughout the JavaScript world, without any attempt to stop it, harms all Javascript Devs. Even if you have no intention of using Angular, you need to learn about what it does and how it works so you are able to point out its flaws when challenged. If you don’t do that then you may find that you have it imposed upon you against your will.

“It’s not a zero sum game”

Except when it is…

I often hear that you shouldn’t criticise tech that you don’t like, because there’s “room for all of us”. In an ideal world, where everybody updates their open source code projects out of love or idealism and has unlimited time to do that, then yes, that’s true. Actually, it’s pretty amazing how much of the time we do exist in such a world — most of our time, I would say. But crucially, not all of it.

There are companies out there that charge actual money for their work, and those companies don’t always have resources to support every new hot framework that happens along. Let me give you a concrete example concerning a company behind a very popular commercial UI framework. The company’s framework was originally based on jQuery, but seeing the writing the wall, they committed to developing shiny, new React and Angular 2 native versions of it, simultaneously. Hoorah!

Fast forward to one year later. The company releases its native Angular 2 version to much fanfare. Of the React version there is no sign.

I buttonholed one of that company’s Program Managers at a conference and asked him “what on Earth happened there?” (or words to that effect :wink). His reply didn’t surprise me in the least.

What happened there was that the development and release of Angular 2 was a total train wreck. We had Release Candidate following Release Candidate, and each one with huge breaking changes over its predecessor. Yes, let me say that again: intentional breaking changes in a Release Candidate.

My framework company’s Devs quickly found themselves overwhelmed, and something had to give. Eventually, they called the Program Manager and told him that they did not have resources to keep their framework up to date with the Angular 2 RCs’ breaking changes and develop a React version at the same time. They told him to pick one or the other.

Zero sum game, right there.

Remake/Re-model

I tried my hardest with Angular. I really did. I bought a book about it back in the Angular 1 days. Maybe it was a bad book. Maybe I was just too stupid to grok what Angular was doing. But I didn’t get it. Not only did I not understand what it was doing, I couldn’t even understand what it was trying to do.

To be fair, I also found React to be something of a struggle when I first looked at it. But I stuck at it and eventually the penny dropped.

Evidently, the Angular team had the same light bulb moment that I did when React came along, because they decided write a completely new framework from the ground up. The new framework would attempt to combine the best parts of Angular and React. Out went two-way data binding, replaced with one-way data flow, just like React. Out went Controllers, replaced by Components, just like React. And so on.

There was to be no upgrade path from Angular 1 to the this new framework, so in truth, the new framework should probably have been given a new name. Presumably, the Google/Angular marketing types nixed this one. They doubtless had one eye on the many thousands of Angular 1 Devs who might get the funny idea that they were having the rug pulled out from under them (which, of course, they were).

So they called called the new framework “Angular 2”, later to be known as just “Angular”, with “AngularJS” reserved for Angular 1. (At one point, it was mooted that Angular 1 would become “Angular Legacy”, but the Angular 1 Devs baulked at that prospect for some reason!). I’ll use the terms Angular and AngularJS as above from this point on.

It’s important to remember and repeat, repeat, repeat that Angular isn’t an update of AngularJS; it’s a completely new thing. Especially remember it every time some IT manager outlines to you the three ways forward for an existing AngularJS project:

  1. Stick with AngularJS until it dies (not long now)
  2. Migrate to something else
  3. Upgrade the code to Angular

Are you the guy who puts his hand up and says: “Well, actually, option 3 doesn’t exist. There is no upgrade path from AngularJS to Angular, so that option belongs in the same column as option 2.”? If you’re not, then I suggest you start being that guy PDQ.

At this point, you might be told about ngUpgrade.

NgCoexist (not)

After announcing Angular, with zero mention of an upgrade path from AngularJS (because there isn’t one), the Angular Team faced a backlash from angry Devs. They furiously back pedalled and announced that sure, there would be an upgrade path just as soon as they finished Angular.

And so came forth ngUpgrade.

Now from its name, you might well assume that ngUpgrade does something to, you know, upgrade your AngularJS code to Angular, right?

Nope. What it actually does, according to the blurb at the Angular Docs site, is allow you to upgrade your projects “incrementally, by running the two frameworks side by side in the same application, and porting AngularJS components to Angular one by one.”

See what they did there? Or what they didn’t do? They didn’t say that the tool actually changes any of your AngularJS code over to Angular. That’s because it doesn’t. You still have to do that part yourself. By hand.

Even assuming that it works as advertised, ngUpgrade brings with it some new problems all of its own. If you have to load both Angular and AngularJS into your project at the same time, then which framework is in charge at any given point? Do you load Angular first and then lazy load the bits of AngularJS when they’re needed, or is it the other way around? To go the ngUpgrade route, not only will you need to understand Angular and AngularJS well, you’ll also need to acquire a third bit of knowledge, which is how ngUpgrade lets them operate together. This last bit of hard-earned knowledge is a throwaway: once all your stuff is on Angular, you’ll never need it again.

Either way, you will end up having to rewrite that code at some point. Or else stick with code that’s soon to become obsolete. NgUpgrade does little more than delay the inevitable. NgCoexist might have been a more accurate name for such a tool.

Hey, Java Devs — you can do the Web, sure you can!

Another supposed advantage of Angular is that it makes it easier for Java Devs to learn JavaScript by giving them things like strong typing, courtesy of TypeScript (which you’re pretty much forced to learn from the get go).

I’m not sure why anybody would think this is a good thing. Nothing against Java Devs, but if they want to learn JavaScript, then why can’t they learn it properly?

Think I’m being a bit contrary on this? Okay, then try the following scenario:

I go for a Java job, although my previous experience is mainly JavaScript. At the interview I insist that I will only code in Java using some transpiler plug-in tool I’ve found that lets me have prototype-based inheritance, pass functions as parameters, employs loose data typing and generally has all the other functionality that I’m used to in the JavaScript world. Because when you get right down to it, you see, I think this whole Java thing’s a bit weird really. I sure don’t see why I should have to spend the next 6–12 months learning how it works properly. Oh, and I forgot to mention that I’ll also need all of my new Dev colleagues to convert over to my way of working, so we’re all on the same page.

Have I got that Java job, do you think?

Because that’s the equivalent of what Angular and TypeScript make us to do to JavaScript: twist it around for the benefit of Devs from another discipline. It doesn’t help anybody to learn JavaScript properly if we’re simultaneously bending it into something that it’s not by pumping it full of non-standard add-ons. Too often, I think, Angular keeps developers from learning JavaScript by abstracting as much of it away as it possibly can.

Which brings me to…

Templating — The Horror!

Templating is part of Angular’s “putting JavaScript in your HTML” approach. Except it doesn’t… put JavaScript in your HTML, I mean. When templating, the code that you write is actually some other language that Angular invented specifically for that purpose. Here’s an example from the Angular docs:

<template ngFor let-item [ngForOf]=”items” let-i=”index” [ngForTrackBy]=”trackByFn”>
<li>…</li>
</template>

(NB: since I copied that example from the Angular docs, <template></template> has been deprecated in favour of <ng-template></ng-template>. The former syntax no longer works in Angular 6.)

Now you might be able to infer what’s going on here. If so, give yourself a pat on the head 😃. The bad news though is that the syntax that you have learned here will only be truly useful to you if you stay in Angular for the rest of your Dev career. It’s not transferable knowledge 😢.

To be fair, this is a failing in most template-driven frameworks, not just Angular. A similar loop in Vue (this year’s new framework hotness) might look like this:

<ul id=”example-1">
<li v-for=”item in items”>
{{ item.message }}
</li>
</ul>

Does Vue’s v-for work the same as Angular’s ngFor? Do they loop through all the elements in their respective lists, or can I stop after a certain number by way of an index? Are there v-while or ngWhile loops on offer? How would I do a .map()?

I’ve no idea of the answer to any of these questions, and neither will you have without poring through the framework’s documentation. I later learned that the correct term for this kind of code is a Domain Specific Language or DSL. A more accurate term might have been MUS or Made Up Stuff. (I was going to say “Made Up Shit” at this point, but hey, there may be kiddies reading 😉.)

All this is the opposite of React’s initially derided, but eminently sensible “put HTML in your JavaScript” approach. It’s like the React Team said “hey, we’ve already got a programming language here, so why don’t we use that instead of making up some whole new thing and forcing Devs to learn it by heart?” (A shout out to EJS, which is one other templating framework that puts JavaScript front and centre.)

For example, in React you’d use a JavaScript for loop or a .map() method to generate a list output. So here’s how I might redo my Angular example above in React (updated to include the missing key attribute, as pointed out in one of the comments on this article):

getItemMessages = items => items.map(item => item.message);

render() {
return (
<ul id=”example-1">
<li key={item.id}>{this.getItemMessages(items)}</li>
</ul>
);
}

assuming that this code is inside a React component. Slightly more verbose than the Angular or Vue examples it may be, but it’s far more readable, IMHO. What’s more, my getItemMessages function is pure ES6 Javascript. I didn’t need to look up React’s special syntax for this because it doesn’t have one: it JUST USES JAVASCRIPT 😎.

A little confession here: I didn’t even know that there was a native JavaScript.map()method before I saw it used in the React docs. I’d been using the jQuery equivalent. Now, of course, I use .map() everywhere, and that’s knowledge that I can reuse anywhere that I can use JavaScript. When Devs tell you “React teaches you JavaScript, whereas Angular teaches you Angular”, this is the kind of stuff that they’re talking about.

Templating Update: October 2018

Many Angular fans in the comments for this article were upset that I had chosen the example above. They accused me of going out of my way to choose the worst example that I could find in the Angular docs. I didn’t actually do that, but okay, I’ll try again. Here is a real world example that I ran up against this very day.

In an Angular 6 app, I was trying to determine the data type of a template variable, and then display that variable only if it was a number. Easy enough in JavaScript, you might think, but Angular templates are not JavaScript.

Here’s some sample code to demonstrate the issue. I’ve removed the hide/show code (it was using an *ngIf) to simplify the example further. I now just want to determine if my variable is a number. First things first, here’s how I setup my variable, called myNumber, in my app.component.ts file:

export class AppComponent {
title = “template-type-test”;
myNumber = 3.5;
}

And here’s how I display in the corresponding template:

<div>myNumber: {{myNumber}}</div>

So far, so good. That displays “myNumber: 3.5” in the browser.

Now to determine the variable’s data type. JavaScript has the typeof operator for this, but let’s say it again: Angular templates are not JavaScript. Here’s how I modified my template file:

<div>myNumber: {{myNumber}}</div>
<div>type: {{typeof myNumber}}</div>

Angular chokes on this with the following error message (and a lot more after):

Parser Error: Unexpected token ‘myNumber’ at column 8 in [type: {{typeof myNumber}}] in

I Googled how to use typeof in an Angular template and found this SO post https://stackoverflow.com/questions/37511055/how-to-check-type-of-variable-in-ngif-in-angular2/37511166. The answer is “you can’t” because Angular templating isn’t JavaScript. (Did I mention that already?) The accepted and highest rated answer on that post advises you to work around this by adding a helper function to your component and then calling that helper function from within your template.

Following that recommendation, this is what I ended up with in my component file:

export class AppComponent {
title = “template-type-test”;
myNumber = 3.5;
getType = testVar => typeof testVar;
}

I’ve now added getType, a one line, arrow function that returns the type of a supplied variable. This is how I call it in my template:

<div>myNumber: {{myNumber}}</div>
<div>type: {{getType(myNumber)}}</div>

The good news is that this works! 😃 My web page now shows:

myNumber: 3.5
type: number

The bad news is that it’s insane. 😧

Think about the implications of what I’ve just done: every bit of JavaScript functionality that doesn’t work in an Angular template (quite a lot of it, I suspect) I will now have to rewrite myself. I might easily end up writing dozens of these little helper functions, and they’ll have to be inside every template where I want this functionality.

Sure, I could put all such functions into a central library and import them all, I guess. Maybe there’s kind souls who have already have such DIY rewrites of JavaScript already up there on npmjs. I was too depressed to look.

The transferability of this nonsensical knowledge is close to zero.

Here’s how I’d implement this in React by the way. Inside a React component’s render method I’d have:

return (
<div>{myNumber}</div>
<div>{typeof myNumber}</div>
);

React is just JavaScript, so you can use just about any JavaScript functionality in JSX.

JIT Compilation vs AoT Compilation: how the Angular Compiler deceives you

Have you ever had a tool tell you that your code is fine one minute, then riddled with bugs the next? I mean, to the point where it fails to compile, even though you can see it working fine in another browser tab?

Well, that’s what Angular can do to you if you’re not aware of its two compilation modes. Basically, its JIT (Just in Time) compilation mode, which you’re likely to use for Development, will let through a lot of sloppy code that will only get picked up when you switch to AoT (Ahead of Time) compilation mode for Production. Seriously, Angular hides bugs from you until it’s potentially too late to fix them.

As an approach to development, this is certainly innovative 😉. It’s like developing apps isn’t hard enough without your chosen tools trying to lay traps for you. This is the kind of problem where one has to question whether Angular is even fit for purpose. I’ve written separately about this at:

https://medium.com/@chillypenguin/youre-code-s-bug-free-or-maybe-not-don-t-trust-angular-to-tell-you-either-way-d78357859b4f

Apples to oranges

You’ll often see posts in the interweb forums that say that you can’t compare Angular to React because “Angular’s a framework and React’s only a library”. React only gives you the view part — the “V” in your MVC. Angular gives you everything you’ll need, whereas React makes you stitch together various other tools to give you the equivalent of what Angular gives you out of the box.

To be fair, there’s good deal of truth in this. And there’s a lot to be said for having decisions made on your behalf (Google “Javascript fatigue”!).

However, this is only a plus if the choices that Angular has made on your behalf are good ones. I think it’s fair to say that Angular’s got form here. Let’s take the whole of Angular 1.x for starters: so many missteps that, in the end, they proved impossible to fix, and the whole thing had to be canned. Surely the Angular Team would have fixed those issues if they could have done.

There’s also at least one other flaw in the “Angular’s a framework; React’s only a library” argument: Angular gives you nothing to handle state management.

I actually had no idea that this was the case until I was told it in a Angular course that I attended over year ago. I nearly fell off my chair then the Trainer said it!! He then launched into an hour long explanation of how to use NGRX for Angular’s state management. NGRX seems to be a combination of Redux and RXJS, with some Angular knobs thrown in. I already knew my way around Redux fairly well, as it comes from the React world (although is not actually part of React). I got a bit lost about the rest of NGRX though.

RXJS is based around Observables. I know many JS Devs, myself included, who are still trying to get their heads around using Promises and Await/Async in preference to callbacks, (all of which are actually native to JavaScript, by the way). But Angular seems to expect that you should skip all that in favour of Observables, which are not native to JavaScript and might never be. (Observables may become part of JavaScript one day, but that’s far from certain. The TC39 proposal to include them is still only at Stage 1.)

Angular also has its own built-in command for remote data access, called Http. Again it’s great that you have a common way to do this, but the Http command also uses the aforementioned Observables. Observables are better than Promises or callbacks, I was told at a recent training course, because they handle streams of data. “But what if I just want a single piece of data returned?” I enquired. “Oh I just use a toPromise() call to turn the Observable into a Promise in that case” our Trainer replied. Got that? You get an Observable, then convert it to a Promise. It all makes perfect sense 😉.

Note: since starting this article, I discovered that the Angular Team has now deprecated the Http module in favour of HttpClient, a new module with a different syntax to Http. Time to rewrite again.

In React, you’re free to use whichever Ajax tool you like. Superfetch, Axios or the built-in fetch command that’s in all modern browsers (i.e. not IE). React doesn’t care.

That React didn’t make such decisions for you was definitely a weakness two or three years ago: witness the bazillion versions of Flux that were then on offer. But the React community has now coalesced around an agreed set of approaches to these missing pieces: Redux for state management, React-Router for routing and so on. These approaches are tested and battle-hardened: they work!

Stop already!

If you’re a web developer, Angular is harming you and your world, even if you’re not using it. The more support it gets in the developer world, the less support there will be for more sensible approaches to development.

Angular’s poor design decisions risks creating a new raft of developers who don’t understand JavaScript properly, and who will be forever tied into Angular’s abstractions because that’s all they do understand. In much the same way that some Devs used to think that JavaScript and jQuery were one and the same.

For pity’s sake don’t use it. Don’t let your company use it. Don’t let your friends’ companies use it! But above all, do get to know it so you can explain why it’s not a smart move.

--

--