Notes Of A Three.js Beginner: QuaternionKeyframeTrack Struggles

When I started researching how to programmatically animate object rotations in three.js, I was warned that quaternions are hard to work with and can easily bamboozle beginners. I gave it a shot anyway, and I can confirm caution is indeed warranted. Aside from my confusion between Euler angles and quaternions, I was also ignorant of how three.js keyframe track objects process their data arrays. Constructor of keyframe track objects like QuaternionKeyframeTrack accept (as their third parameter) an array of key values. I thought it would obviously be an array of quaternions like [quaterion1, quaternion2], but when I did that, my CPU utilization shot to 100% and the browser stopped responding. Using the browser debugger, I saw it was stuck in this for() loop:

class QuaternionLinearInterpolant extends Interpolant {
  constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    super(parameterPositions, sampleValues, sampleSize, resultBuffer);
  interpolate_(i1, t0, t, t1) {
    const result = this.resultBuffer, values = this.sampleValues, stride = this.valueSize, alpha = (t - t0) / (t1 - t0);
    let offset = i1 * stride;
    for (let end = offset + stride; offset !== end; offset += 4) {
      Quaternion.slerpFlat(result, 0, values, offset - stride, values, offset, alpha);
    return result;

I only have two quaterions in my key frame values, but it is stepping through in increments of 4. So this for() loop immediately shot past end and kept looping. The fact it was stepping by four instead of by one was the key clue. This class doesn’t want an array of quaternions, it wants an array of quaternion numerical fields flattened out.

  • Wrong: [quaterion1, quaternion2]
  • Right: [quaterion1.x, quaterion1.y, quaterion1.z, quaterion1.w, quaternion2.x, quaternion2.y, quaternion2.z, quaternion2.w]

The latter can also be created via quaterion1.toArray().concat(quaternion2.toArray()).

Once I got past that hurdle, I had an animation on screen. But only half of the colors animated in the way I wanted. The other half of the colors went in the opposite direction while swerving wildly on screen. In a HSV cylinder, colors are rotated across the full range of 360 degrees. When I told them to all go to zero in the transition to a cube, the angles greater than 180 went one direction and the angles less than 180 went the opposite direction.

Having this understanding of the behavior, however, wasn’t much help in trying to get things working the way I had it in my head. I’m sure there are some amateur hour mistakes causing me grief but after several hours of ever-crazier animations, I surrendered and settled for hideous hacks. Half of the colors still behaved differently from the other half, but at least they don’t fly wildly across the screen. It is unsatisfactory but will have to suffice for now. I obviously don’t understand quaternions and need to study up before I can make this thing work the way I intended. But that’s for later, because this was originally supposed to be a side quest to the main objective: the Arduino color composite video out library I’ve released with known problems I should fix.

[Code for this project is publicly available on GitHub]

Notes Of A Three.js Beginner: Euler Angles vs. Quaternions

I was pretty happy with how quickly I was able to get a static 3D visualization on screen with the three.js library. My first project to turn the static display into an interactive color picker also went smoothly, giving me a great deal of self confidence for proceeding to the next challenge: adding an animation. And this was where three.js put me in my place reminding me I’m still only a beginner in both 3D graphics and JavaScript.

Before we get to details on how I fell flat on my face, to be fair three.js animation system is optimized for controlling animations created using content creation tools such as Blender. In this respect, it is much like Unity 3D. In both of these tools, programmatically generated animations are not the priority. In fact there weren’t any examples for me to follow in the manual. I hunted around online and found DISCOVER three.js, which proclaimed itself as “The Missing Manual for three.js”. The final chapter (so far) of this online book talks about animations. This chapter had an ominous note on animation rotations:

As we mentioned back in the chapter on transformations, quaternions are a bit harder to work with than Euler angles, so, to avoid becoming bamboozled, we’ll ignore rotations and focus on position and scale for now.

This is worrisome, because my goal is to animate the 256 colors between two color model layouts. From the current layout of a HSV cylinder, to a RGB cube. This required dealing with rotations and just as the warning predicted that’s what kicked my butt.

The first source confusion is between Euler angles and quaternions when dealing with three.js 3D object properties. Object3D.rotation is an object representing Euler angles, so trying to use QuaternionKeyframeTrack to animate object rotation resulted in a lot of runtime errors because the data types didn’t match. This problem I blame on JavaScript in general and not three.js specifically. In a strongly typed language like C there would be an error indicating I’ve confused my types. In JavaScript I only see errors at runtime, in this case one of these two:

  1. When the debug console complains “NaN error” it probably meant I’ve accidentally used Euler angles when quaternions are expected. Both of those data types have fields called x, y, and z. Quaterions have a fourth numeric field named w, while Euler angles have a string indicating order. Trying to use an Euler angle as quaternion would result in the order string trying to fit in w, which is not a number hence the NaN error.
  2. When the debug console complains “THREE.Quaternion: .setFromEuler() encountered an unknown order:” it means I’ve done the reverse and accidentally used Quaternion when Euler angles are expected. This one is fortunately a bit more obvious: numeric value w is not a string and does not dictate an order.

Getting this sorted out was annoying, but this headache was nothing compared to my next problem: using QuaternionKeyframeTrack to animate object rotations.

[Code for this project is publicly available on GitHub]

Notes Of A Three.js Beginner: Color Picker with Raycaster

I was pleasantly surprised at how easy it was to use three.js to draw 256 cubes, each representing a different color from the 8-bit RGB332 palette available for use in my composite video out library. Arranged in a cylinder representing the HSV color model, it failed to give me special insight on how to flatten it into a two-dimension color chart. But even though I didn’t get what I had originally hoped for, I thought it looked quite good. So I decided to get deeper into three.js to make this more useful. Towards the end of three.js getting started guide is a list of Useful Links pointing to additional resources, and I thought the top link Three.js Fundamentals was as good of a place to start as any. It gave me enough knowledge to navigate the rest of three.js reference documentation.

After several hours of working with it, my impression is that three.js is a very powerful but not very beginner-friendly library. I think it’s reasonable for such a library to expect that developers already know some fundamentals of 3D graphics and JavaScript. From there it felt fairly straightforward to start using tools in the library. But, and this is a BIG BUT, there is a steep drop if we should go off the expected path. The library is focused on performance, and in exchange there’s less priority on fault tolerance, graceful recovery, or even helpful debugging messages for when things go wrong. There’s not much to prevent us from shooting ourselves in the foot and we’re on our own to figure out what went wrong.

The first exercise was to turn my pretty HSV cylinder into a color picker, making it an actually useful tool for choosing colors from the RGB332 color palette. I added pointer down + pointer up listeners and if they both occurred on the same cube, I change the background color to that color and display the two-digit hexadecimal code representing that color. Changing the background allows instant comparison to every other color in the cylinder. This functionality requires the three.js Raycaster class, and the documentation example translated across to my application without much fuss, giving me confidence to tackle the next project: add the ability to switch between HSV color cylinder and RGB color cube, where I promptly fell on my face.

[Code for this project is publicly available on GitHub]

HSV Color Wheel of 256 RGB332 Colors

I have a rectangular spread of all 256 colors of the 8-bit RGB332 color cube. This satisfies the technical requirement to present all the colors possible in my composite video out library, built by bolting the Adafruit GFX library on top of video signal generation code of rossumur’s ESP_8_BIT project for ESP32. But even though it satisfies the technical requirements, it is vaguely unsatisfying because making a slice for each of four blue channel values necessarily meant separating some similar colors from each other. While Emily went to Photoshop to play with creative arrangements, I went into code.

I thought I’d look into arranging these colors in the HSV color space, which I was first exposed to via Pixelblaze I used in my Glow Flow project. HSV is good for keeping similar colors together and is typically depicted as a wheel of colors with the angles around the circle corresponding to the H or hue axis. However, that still leaves two more dimensions of values: saturation and value. We still have the general problem of three variables but only two dimensions to represent them, but again I hoped the limited set of 256 colors could be put to advantage. I tried working through the layout on paper, then a spreadsheet, but eventually decided I need to see the HSV color space plotted out as a cylinder in three dimensional space.

I briefly considered putting something together in Unity3D, since I have a bit of familiarity with it via my Bouncy Bouncy Lights project. But I thought Unity would be too heavyweight and overkill for this project, specifically because I didn’t need a built-in physics engine for this project. Building a Unity 3D project takes a good chunk of time and imposes downtime breaking my trains of thought. Ideally I can try ideas and see them instantly by pressing F5 like a web page.

Which led me to three.js, a JavaScript library for 3D graphics in a browser. The Getting Started guide walked me through creating a scene with a single cube, and I got the fast F5 refresh that I wanted. In addition to rendering, I wanted a way to look around a HSV space. I found OrbitControls in the three.js examples library, letting us manipulate the camera view using a pointer device (mouse, touchpad, etc.) and that was enough for me to get down to business.

I wrote some JavaScript to convert each of the 256 RGB values into their HSV equivalents, and from there to a HSV coordinate in three dimensions. When the color cylinder popped up on screen, I was quite disappointed to see no obvious path to flatten that to two dimensions. But even though it didn’t give me the flash of insight I sought, the layout is still interesting. I see a pattern, but it is not consistent across the whole cylinder. There’s something going on but I couldn’t immediately articulate what it is.

Independent of those curiosities, I decided the cylinder looks cool all on its own, so I’ll keep working with it to make it useful.

[Code for this project is publicly available on GitHub]

Notes After Node.js Introduction

After I ran through the Docker Getting Started tutorial, I went back into the docker container (the one we built as we progressed through the tutorial) and poked around some more. The tutorial template was an Express application, built on Node.js. Since I had parts of this infrastructure in hand, I thought I will just run with it and use Node.js to build a simple web server. The goal is to create a desktop placeholder for an ESP32 acting as a web server, letting me play and experiment quickly without constantly re-flashing my ESP32.

The other motivation was that I wanted to get better at JavaScript. Not necessarily because of the language itself (I’m not a huge fan) but because of the huge community that has sprung up around it, sharing reusable components. I was impressed by what I saw of Node-RED (built on Node.js) and even more impressed when I realized that was only a small subset of the overall Node.js community. More than a few times I’ve researched a topic and found that there was an available JavaScript tool for doing it. (Like building desktop apps.) I’m tired of looking at this treasure trove from the outside, I want this in my toolbox.

Node.js is available with a Windows installer, but given my recent knowledge, I went instead to their officially published Docker images. Using that to run through Node.js introduction required making a few on-the-fly adaptations to Node.js in a container, but I did not consider that a hinderance. I consider it great container practice! But this only barely scratches the surface of what I can find within the Node.js community. Reading the list of Node.js Frameworks and Tools I realized not only have I not heard about many of these things, I don’t even understand the words used to describe them! But there were a lot of great information in that introduction. On the infrastructure side, the live demo code was made possible by, another online development environment I’ll mentally file away alongside Cloud9 and StackBlitz.

Even though Google’s V8 JavaScript engine is at the heart of both Chrome browser and Node.js server, there are some obviously significant differences between running in a server environment versus running in browser. But sometimes there are concepts from one world that can be useful in the the other, and I was fascinated by people who try to bring these worlds closer together. One example is Browserify which brings some server-side component management features to browser-side code. And Event Emitter is a project working in the other direction, bringing browser-style events to server-side code.

As far as I can tell, the JavaScript language itself was not explicitly designed with a focus on handling asynchronous operations. However, because it evolved in the web world where network latency is an ever-present factor, the ecosystem has developed in that direction out of necessity. The flexibility of the language permitted an evolution into asynchronous callbacks, but “possible” isn’t necessarily “elegant” leading to scenarios like callback hell. To make asynchronous callbacks a little more explicit, JavaScript Promise was introduced to help improve code readability. There’s even a tool to convert old-school callbacks into Promises. But as nice as that was, people saw room for improvement, and they built on top of Promises to create the much more easier-to-read async/await pattern for performing asynchronous operations in JavaScript. Anything that makes JavaScript easier to read is a win in my book.

With such an enormous ecosystem, it’s clear I can spend a lot more time learning Node.js. There are plenty of resources online like Node School to do so, but I wanted to maintain some resemblance of focus on my little rover project. So I went back to the Docker getting started tutorial and researching how to adapt it to my needs. I started looking at a tool called webpack to distill everything into a few static files I can serve from an ESP32, but then I decided I should be able to keep my project simple enough I wouldn’t need webpack. And for serving static files, I learned Express would be overkill. There’s a Node.js module node-static available for serving static files so I’ll start by using that and build up as needed from there. This gives me enough of a starting point on server side so I can start looking at the client side.

I Started Learning Jamstack Without Realizing It

My recent forays into learning about static-site generators, and the earlier foray into Angular framework for single-page applications, had a clearly observable influence on my web search results. Especially visible are changes in the “relevant to your interests” sidebars. “Jamstack” specifically started popping up more and more frequently as a suggestion.

Web frameworks have been evolving very rapidly. This is both a blessing when bug fixes and new features are added at a breakneck pace, and a curse because knowledge is quickly outdated. There are so many web stacks I can’t even begin to track of what’s what. With Hugo and Angular on my “devise a project for practice” list I had no interest in adding yet another concept to my to-do list.

But with the increasing frequency of Jamstack being pushed on my search results list, it was a matter of time before an unintentional click took me to I read the title claim in the time it took for me to move my mouse cursor towards the “Back” button on my browser.

The modern way to build [websites & apps] that delivers better performance

Yes, of course, they would all say that. No framework would advertise they are the old way, or that they deliver worse performance. So none of the claim is the least bit interesting, but before I clicked “Back” I noticed something else: the list of logos scrolling by included Angular, Hugo, and Netlify. All things that I have indeed recently looked at. What’s going on?

So instead of clicking “Back”, I continued reading and learned proponents of Jamstack are not promoting a specific software tool like I had ignorantly assumed. They are actually proponents of an approach to building web applications. JAM stands for (J)avaScript, web (A)PIs, and (M)arkup. Tools like Hugo and Angular (and others on that scrolling list) are all under that umbrella. An application developer might have to choose between Angular and its peers like React and Vue, but no matter the decision, the result is still JAM.

Thanks to my click mistake, I now know I’ve started my journey down the path of Jamstack philosophy without even realizing it. Now I have another keyword I can use in my future queries.

Notes on Angular Architecture Guide

After completing two beginner tutorials, I returned for another pass through the Angular Architecture Guide. These words now make a lot more sense when backed by the hands-on experience of the two tutorials. There are still a few open question marks, though, the long standing top of my list are Angular Modules. I think each of the tutorial is contained into a single module? That would explain why I haven’t seen it in action yet. It doesn’t help that JavaScript also has a “Module” concept, makes things confusing to a beginner like myself. And as if that’s not confusing enough, there are also “Libraries” which are different from modules… how? I expect these concepts won’t become concrete until I tackle larger projects that incorporate code from multiple different sources.

In contrast, Angular Components have become very concrete and these pages even use excerpts from the “Tour of Heroes” tutorial to illustrate its concepts. I feel I have a basic grasp of components now, but I’m also aware I still need to read up on a few things:

  • Component metadata so far has been a copy-and-paste affair with limited explanation. It’ll be a challenge to strike out on my own and get the metadata correct. Not just because I don’t know what I should do, but also I haven’t seen what the error messages are like.
  • Data binding with the chart of four types of binding looks handy, I hope it’s repeated and expanded in more detail elsewhere in documentation so I can get some questions answered. One example: I read “Angular processes all data bindings once for each JavaScript event cycle” but I have to ask… what’s a JavaScript event cycle? The answer lies elsewhere.
  • Pipes feel like something super useful and powerful, looking forward to playing more with the concept and maybe even create a few of my own.
  • Directives seem to be a generic concept whose umbrella is fuzzy, but I’ve been using task-specific directives in the tutorial. *ngFor and *ngIf are structural directives. Attribute directive was used in two-way data binding. Both types have their own specific guide pages.

Reading the broad definition of services I started thinking “Feels like my UWP Logger, maybe I can implement a logger service as exercise.” Only to find out they’re way ahead of me – the example is a logger (to console) service! I had hoped this section would help clear up the concept of service providers, but it is still fuzzy in my head. I understand the default is root, which is a single instance for everything, and this is what was used in the tutorials. I will need to go find examples of providers at other granularities, which apparently can be as specific as per component where each instance of component gets its own instance of that service. When would that be useful? I have yet to learn the answer. But at least I’ve written these questions down so I’m less likely to forget.

Fixing Warnings of TypeScript Strict Mode Violation After “Tour of Heroes” Tutorial

Once I’ve reached the end of the Angular “Tour of Heroes” tutorial, I went back to address something from the beginning. When I created my Angular project, I added the --strict flag for the optional “Strict Mode“. My motivation was the belief that, since I’m starting from scratch, I might as well learn it under enforcement of best practices. I soon realized this was also adding an extra burden on myself for following the tutorial, because the example code does not always follow strict mode. This means when something goes wrong, I might have copied the tutorial code incorrectly, but it’s also possible I copied correctly but it’s just doesn’t conform to strict mode.

As a beginner, I really didn’t need this extra work, since I had enough problems with basics on my own. But I decided to forge onward and figure it out as I went. During the tutorial, I fixed strict mode errors in two categories:

  1. Something so trivial that I could fix quickly and move on.
  2. Something so serious that compilation failed and I had to fix it before I could move on.

In between those two extremes were errors that were not trivial, but only resulted in compilation warnings that I could ignore and address later. They are visible in this GitHub commit:

I first had to understand what the code was doing, which was why I imported MessageService to gain access to logging. The compiler warnings were both about uninitialized variables, but the correct solution was different for the two cases.

For the hero input field, the tutorial code logic treats undefined as a valid case. It is in fact dependent on undefined hero to know when not to display the detail panel. Once I understood this behavior, I felt declaring the variable type as a Hero OR undefined was the correct path forward.

For the Observable collection of Heroes, the correct answer is different. The code never counts on undefined being a valid value, so I did not need to do the if/else checks to handle it as an “OR undefined” value. What I needed instead was an initial value of a degenerate Observable that does nothing until we can get a real Observable. Combing through RxJS documentation I saw this was recognized as a need and was actually done in a few different ways that have since been deprecated. The current recommendation is to use the constant defined as EMPTY, which is what I used to resolve the strict mode errors.

Notes on “Tour of Heroes” Tutorial: Other Web Server Interactions

The Angular “Tour of Heroes” tutorial section 6 “Get Data From Server” covered the standard interactions: Create, Read, Update, and Delete commonly referred to as CRUD. But it didn’t stop there and covered a few other server operations. I was intrigued the next section was titled “Search by name” because I was curious how a client side single page application could search data on a static web server.

It turns out the application does not actually perform the search, the “search by name” example is built around sending a GET URL with a “name=” query parameter and processing the results. So the example here isn’t actually specific to searching, it’s just a convenient example to demonstrate a general server query/response outside of the simplified CRUD mode. It can be argued that this fits under the umbrella of R of CRUD, but this is as far as I’ll pick that nit.

Lucky for us, the search query parameter appears to be part of the feature set of the in-memory web API we’re using to stand in for a web server. Like the rest of the tutorial CRUD operations, none of this will actually work on a static web server. But that’s fine, we get to see the magic of Observable used in a few different ways. Like a new convention of ending an observable name with the $ character and asynchronously piping into a *ngFor directive.

For me, the most interesting new concept introduced in this section is the rate-limiting functionality of debounceTime() filter from RxJS. Aside from being a piece of commonly needed (and thus commonly re-implemented) functionality, it shows the power of using RxJS for asynchronous operations where we can stick these kind of filters in the pipeline to accomplish goals. I don’t fully understand how it works or how I might reuse it in other contexts. I think I have to learn more about Subject<T> first? But anyway, what we’ve seen here is pretty cool and worth following up with more reading later.

Notes on “Tour of Heroes” Tutorial: C and D of CRUD

This Angular tutorial on server interactions started with (R)ead and (U)pdate operations, then we moved to C(reate) of CRUD by adding a hero to the Tour of Heroes. I found it interesting that content creation was not the first thing to be covered, even though it is the obvious first step in life cycle of a piece of information which I supposed was why it was the first letter of CRUD. The authors of this tutorial gave us the luxury of a stub set of data so we can explore other concepts before we worry about data creation.

Even with that background, creation was still confusing to me. For example, our input element has a hash #heroName. I assume the hash prefix tells some piece of Angular infrastructure to do something… but what? That was completely unexplained and I have no idea how to use it myself later. Even worse, they didn’t even give me a keyword to search for, so I’ll start with input element documentation and hunt from there.

Another piece of auto-magic is in generation of hero ID. I felt that was a mistake because the identifier will be the first piece of information we’ll need to understand in any debugging task. The tutorial authors may not think these details are important, but I do, so I’ll have to chase down details later.

And finally we have D(elete) of CRUD. The mind-boggling part for me was learning that RxJS only cares about delivering information to subscribers. If there are no subscribers, RxJS will decide it is not important and won’t do the thing. This had to be called out because in this context it meant we must hang a subscriber on a delete operation, even if we don’t do anything with the response, or else RxJS will not perform the operation. On the one hand, emphasizing that an Observable does nothing unless there are subscribers is a very valuable point to bring up. On the other hand, this feels like an inelegant hack.

I can accept this as an oddity of a system that we just have to learn to live with in the world of Angular development. Even though I can see it biting me in the future if I ever forget, I can see how it is a worthwhile tradeoff to get everything else RxJS offers to make server interaction easier.

Notes on “Tour of Heroes” Tutorial: R and U of CRUD

First up in the server interaction portion of this Angular tutorial is R(ead) of CRUD, and we see how to retrieve data using RxJS as an intermediary for making HTTP GET calls. There were unfortunately a few pieces of unexplained magic, such as the presence of a method getHeroNo404() that was explicitly called out in a sidebar yet whose purpose is, strangely, not explained in that sidebar. We can infer it has something to do with error handling, since HTTP 404 is a common error and the tutorial started covering error handling. A very important part of writing any web pap, since HTTP fails all the time for factors out of our control. Still, it would have been nice to know more about how getHeroNo404() fits into the picture.

Next up is U(pdate) of CRUD, and while I’m happy to see some compile-time verification, there’s still some sadness that a lot are still left up to runtime. When I made a mistake in binding button (click)="save()" without defining a save() function in TS, it did not generate a compile time error even though at first glance all the pieces to detect this at compile time are present. In reality, it’s not until runtime and a click on the button do we get the error. And again we need to learn to interpret the error. Because while the lack of save() is correct, the user never declared anything named ctx_r3 and so we had to work backwards by guessing what Angular framework had created on our behalf.

ERROR TypeError: is not a function
at HeroDetailComponent_div_0_Template_button_click_12_listener (hero-detail.component.html:10)
at executeListenerWithErrorHandling (core.js:14317)
at wrapListenerIn_markDirtyAndPreventDefault (core.js:14352) at HTMLButtonElement.<anonymous> (platform-browser.js:582)
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Object.onInvokeTask (core.js:27428)
at ZoneDelegate.invokeTask (zone-evergreen.js:398)
at Zone.runTask (zone-evergreen.js:167)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:480)
at invokeTask (zone-evergreen.js:1621) defaultErrorLogger @ core.js:4197 handleError @ core.js:4245 handleError @ core.js:8627 executeListenerWithErrorHandling @ core.js:14320 wrapListenerIn_markDirtyAndPreventDefault @ core.js:14352 (anonymous) @ platform-browser.js:582 invokeTask @ zone-evergreen.js:399 onInvokeTask @ core.js:27428 invokeTask @ zone-evergreen.js:398 runTask @ zone-evergreen.js:167 invokeTask @ zone-evergreen.js:480 invokeTask @ zone-evergreen.js:1621 globalZoneAwareCallback @ zone-evergreen.js:1647

Thankfully this was towards the end of the tutorial and chances are good anyone following along would have seen enough to know how to diagnose these problems. Because it certainly doesn’t get any easier as the tutorial continues to the remainder of CRUD.

Notes on “Tour of Heroes” Tutorial: Setting up for CRUD

It was very novel for me to learn how single page applications (SPA) written in Angular handle navigation with help of a router. In contrast, the final section 6 of Tour of Heroes tutorial is more of a review. “Get Data from Server” is certainly a very important part of any web app, but it isn’t as novel for me as the concepts have been covered in other contexts before. For example, the Ruby on Rails Tutorial.

The pattern here is something I know as Create+Read+Update+Delete or CRUD. The vast majority of applications can be fit into a CRUD mold, it just depends on how far we’re willing to stretch the concepts. It’s popular enough that many frameworks like Ruby on Rails have scaffolding scripts optimized to make it easy to build CRUD applications. In fact, some projects fit CRUD so perfectly they don’t need any coding at all, and can be done with tools like Amazon’s Honeycode.

Because CRUD pattern pops up so often, this final section of the Angular tutorial prescribes how to implement them with tools of the Angular framework. Again RxJS features prominently here, helping to deal with the asynchronous nature of network communications.

The functionality here is also getting complex enough we can’t always get a warning about problems at compile time. I saw multiple error messages that were not particularly helpful in tracing to the underlying cause. One of them was “cannot GET” which is not specific enough about why the data retrieval operation failed. And even at compile time, less-than-helpful errors have also started popping up. “File does not exist” is frustrating when the named file actually does exist, but I eventually learned this actually indicates a compile error. When is an error in the file causing it to fail one of the compilation steps, that file would be unavailable to later steps which then complains of “File does not exist”.

Some of these errors were of my own doing, because I choose to specify --strict when creating this project. Unfortunately the copy-and-pasted tutorial code does not following strict TypeScript rules, and so I will be on my own for fixes. I’ll revisit that topic for later, in the meantime I just fix things up just enough to avoid “File does not exist” problems, even though that meant living with a lot of warning messages in the build window. On the upside, I’m starting to learn to identify which errors are --strict violations and which errors I need to fix as I get started with (R)ead and (U)pdate operations.

Notes on “Tour of Heroes” Tutorial 5: In-App Navigation

After getting an introduction to Angular services, I have some understanding but also know I still have a lot to read up on. I see several practice projects ahead, implementing my own Angular services, before I really understand when and where to best utilize its powers. Setting them aside as exercises for later, I proceeded to the next section of the Tour of Heroes tutorial for implementing in-app navigation.

For me, this is the most novel part of learning how to develop a single-page application (SPA) with Angular as the specific example. HTML navigation is very much based on the idea of pages and navigation between them. The “single page” of SPA implies that pattern has been circumvented, but manged to do so while maintaining compatibility with web browsers and static content web servers. How was this magic accomplished?

The “a-ha” moment for me was when I learned about Angular server-side requirements. Even though the server only needs to serve static content and does not need to run any application code, the server needs to be configured so that HTTP404 (not found) errors be sent back to index.html. This is how the web browser’s address bar can change in response to application activity, while still staying on the same page, because those URLs will get sent back to the single HTML page and served up instead of the HTTP404 error.

And when the page loads up (or stays up, really) in response to that new URL, that attempted URL is sent back into the page as well. This informs the SPA as to what to display in response. The code performing this processing is referred to as the router. For this tutorial, we are instructed to pull in an Angular module and call it the AppRoutingModule. The interesting implication here is that despite being a key part of SPAs, the router is “just another module” and can be modified or swapped out with different router modules as needed. I don’t know when this would be done or why, but it’s always good to see flexibility in an architecture.

This tutorial also made use of something I hadn’t seen before: the JavaScript template literal. It’s not the focus of the tutorial so they didn’t say very much about it, but they did at least call it out with a little note.

Note the backticks ( ` ) that define a JavaScript template literal for embedding the id.

As a relative beginner to JavaScript programming, it’s another item I have to add to the “to be investigated later” pile as I move on to the next part of the tutorial.

Notes on “Tour of Heroes” Tutorial 4: Adding Services

Splitting related functionality into its own Angular component results in improved organization and maintenance. However, the structure of Angular components are focused on delivering a visual representation on screen. Sometimes we want to organize a set of related code into a logical unit that has no direct on-screen representation, and that is why the tutorial teaches us how to create Angular services.

Since there is nothing on screen, Angular services are a little more abstract and involve moving parts we haven’t seen yet. I re-read “Provide the HeroService” section several times and I still don’t feel like I have a good grasp of “service”, “provider”, and “injector”. I don’t see why “service” and “provider” are two different concepts, as the tutorial provider instantiates the service class. Perhaps a service can be provided by one of several different providers? Or perhaps a service class can be created by multiple providers? Or is there a 1:1 relationship but they need to be kept separate for some reason I don’t understand? That is an exercise left for later. As for injectors, we use a single global injector in the tutorial. Having multiple injectors — and when it would make sense to do so — is outside the scope of this tutorial.

It didn’t help that the section started with one bear of a compound sentence:

You must make the HeroService available to the dependency injection system before Angular can inject it into the HeroesComponent by registering a provider.

There are multiple ways to parse this sentence. My initial reading was “You must (make the HeroService available to the dependency injection system) before (Angular can inject it into the HeroesComponent by registering a provider.)” but now I think it is “You must (make the HeroService available to the dependency injection system) before (Angular can inject it into the HeroesComponent) by (registering a provider).” But either way I think this sentence should be broken up and rewritten. If I grow in my Angular knowledge to understand what’s going on (which I don’t at the moment) I can try my hand at rewriting that sentence and submit a pull request.

Once we created the service class, we progressed to the implementation which showcased how asynchronous operations are handled in Angular applications. The concept is called “Observable Data” and it is subcontracted out to a separate project named RxJS. I read over the RxJS Overview page and it was clear I did not meet the prerequisites for this class. Reading things like “Think of RxJS as Lodash for events.” didn’t help me at all given my ignorance of JavaScript events and whatever Lodash is. But the examples that followed looked mildly interesting. I guess if I had more experience with JavaScript event handler oddities, I would find RxJS more compelling. But for now it’s just another pattern I’ll learn to use without really understanding why it came to be that way.

Which is a fair description of this services section of the Angular tutorial, actually. The Heroes service is followed by another service example to represent Message. And given the overlap, Message service included fewer explanations than earlier. I think I’m still mostly keeping up, but there’s definitely less comprehension and understanding as I copy and paste. Thankfully I had an easier time following the next section on in-app navigation.

Notes on “Tour of Heroes” Tutorial 3: Feature Component

Once we followed through previous steps of the tutorial, we had enough code in our tutorial project to demonstrate benefits of componentization by creating a feature component. This is when I really started to get a grasp of the power of Angular componentization and the potential for how it helps make large projects more organized. I’ve never tackled web application projects large enough to really benefit, but maybe that was because I was not looking forward to juggling a bunch of structure-less JavaScript files! I suppose whether one views this componentization as a good thing will depend on whether they feel JavaScript’s general flexibility (a.k.a. freedom from organization) a bug or a feature.

I had hoped they would continue discussion project organization to how this relates to Angular modules, but they did not. I assume Angular modules apply the similar concept to a larger scale, each module a collection of components, but I don’t know for sure and haven’t seen how it would be useful.

The componentization tutorial has one aspect unique among all of these tutorial pages: After following through all the steps on the page, the end-user visible web app looks exactly the same. All our effort was spent organizing code behind the scenes without disturbing the user facing visible appearance. I thought it was neat but some may find it pointless. Either way, this would be the last time we “do nothing” in this tutorial.

Notes on “Tour of Heroes” Tutorial 2: Selection List

Editing the name of a single non-copyright-infringing superhero isn’t terribly exciting by itself. We demand a world of many superheroes! Thus we move on to part 2 of the Angular “Tour of Heroes” tutorial: display a selectable list which builds our experience using Angular directives in the template HTML.

During this segment, we have many more opportunities to see what happens when we do something before setting up all the necessary support infrastructure. Meaning we got to see more error messages of a broken app before we proceed to fix it. I love this approach as there’s very little penalty to a momentarily broken Angular app. The more experience we can pick up with Angular errors during a tutorial, the better it is for us down the line when we see it again due to our own mistakes.

I also realized they’ve started showing just short excerpts for the reader to put into their projects. The template (HTML) and class (TypeScript) excerpts were fairly well explained, but following precedent, CSS changes were less well explained. This is not a CSS class, but there was one part I couldn’t follow at all: the CSS select binding. I don’t see how [class.selected]="hero === selectedHero" ends up being class="selected" in the HTML. I guess I have to look up “class binding” later.

Back to the topic of error messages, at the end of the tutorial I was left with an unresolved error.

    ERROR in src/app/heroes/heroes.component.ts:12:3 - error TS2564: Property 'selectedHero' has no initializer and is not definitely assigned in the constructor.
12 selectedHero : Hero;

I thought it was odd for a tutorial to leave us with an error, so I started looking around for help and found this StackOverflow thread. Now I understand this is because I created my tutorial project with the --strict flag. Since learning to operate under strict mode is an extra credit project I’ve given myself, and it is not preventing the app from running, I’ll ignore it for now and make plans to come back later. Code quality is always interesting to look into, in fact the next section is all about giving us tools to organize our Angular code.

Notes on “Tour of Heroes” Tutorial 1: Editor

Once the Angular workspace has been set up and initialized, our tutorial proceeds to the creation of the first Angular component: an editor for our main data object, the superhero. Of course we have to be able to rename them ourselves, because the tutorial gives us a list of non-copyright-infringing superhero names and we want to be able to correct them.

Instead of right-clicking as in StackBlitz, here we run ng generate component to add a new component to our Angular application. And this time we took a little more time by getting into more detail on the individual steps and what they do. This helps us understand what each line of the boilerplate code does. It is mentioned that ng generate also generates a test file for the component, though we don’t get into writing tests in this tutorial. Which is a bit of a shame. Hopefully I can find resources on writing tests elsewhere.

The most interesting mechanism demonstrated here is two-way databinding. I loved the fact that we added it in the template first, without supporting infrastructure, so we can see it break (and the corresponding error messages) before fixing it. I find this more instructive than a tutorial where we never see any of the error messages. But I did run into a brief problem where the two way bind didn’t seem to work. I entered a new name in the textbox and the hero name didn’t change. Oops. I saw no error messages and didn’t know how to start digging in to debug on my own, so I tried the simple thing first: I hit F5 on the browser to refresh. And that did the trick. Perhaps some caching has tripped me up? I’d like to know what happened. But now that the symptoms are gone, all I can do is proceed to the next tutorial step.

Notes on “Tour of Heroes” Tutorial Project Creation

After a beginner is introduced to the objectives of Angular’s “Tour of Heroes” tutorial application, it’s time for us to start working on some actual code. And we start with creating a new project workspace by using Angular command line interface ng new.

This is a step skipped in the “Try It” shopping cart app, as the StackBlitz workspace was already partially populated for us. Now we are faced with a blank application template workspace exactly as we would see when we start striking out on our own later. So there were a few paragraphs helping to orient us in the structure of an Angular application workspace. I appreciated this because not every coding tutorial give us this explanation. Too many just dive straight into “Now open this file and start editing…” without saying anything about the default template structure.

Another step skipped in the “Try It” shopping cart app is the process of setting up a web server for development purposes. After all, we need some way to see the results of our handiwork locally and find problems before we publish to a real web server. StackBlitz handles that for us by default in their online workspace, but when working locally we’ll need to run ng serve --open on our own.

And if everything is successful, we can see the default template, which is a simple HTML page with links to various Angular resources. Our first introductory task is to remove this default page and replace it with a blank page that has the application title. I found this to be a mild novelty. Usually our first task in a tutorial is to add some code, but this time around our first step is to remove code.

Once the placeholder was removed, we can proceed to seeing some Angular concepts in action:

  • Component class — the TypeScript file that will compile to JavaScript.
  • Component template — the HTML files sprinkled with Angular-specific directives that will be translated during compilation.

The third part of a standard Angular component, the component stylesheet, doesn’t get much attention. While CSS is a real and important part of a good looking web app, there’s nothing Angular specific about CSS used in this tutorial. So I understand why there’s very little focus on the why and how of styling an Angular application and we’re merely given our component stylesheets for copying and pasting. I’m fine with focusing on Angular now, and I plan to go (re)learn CSS elsewhere later.

Notes on “Tour of Heroes” Tutorial Introduction

I think I’ve finished preparing my computer for developing Angular applications, so I proceed to start reading the Introduction page of Angular’s “Tour of Heroes” tutorial. The first thing it told us: anyone who hasn’t tried the “Try It” shopping cart example that we can do on StackBlitz should go do that first. It’s easy to get lost online when everything can link to everything else, I appreciated them establishing a recommended ordering.

The high level description of “Tour of Heroes” application is not earth shattering, as it is only intended to demonstrate how to implement all the features common to web applications. And I’ve seen these kinds of tasks before. But that generic sounding paragraph is immediately followed by list of Angular development tasks for accomplishing those features, and I was happy to see that listed up front. Obviously the names for these tasks won’t mean very much to a beginner, but it is worth calling out the major Angular terminology involved so we know to keep our eyes open.

The text description is then followed up by a series of screen shot images of the sample application in action. So we can see what the application should look like in the end. This is another great touch. There have been too many times where I made a mistake and went off track during a tutorial, but I didn’t realize until much later because I didn’t know what the app was supposed to look like. Having this reference will help answer the “Um… is it supposed to look like that?” questions I inevitably have when I follow a tutorial. But this time I am properly armed with the knowledge and can get things set up for the adventure.

Additional Preparation For Angular Tutorial

Once I managed to overcome the few speed bumps on the way to installing Angular CLI on MacOS, technically speaking I’m all set to start writing my first Angular app on my own computer. And some people are happy to launch their vi or emacs and start working, but I’m going to do a few more things.

The first is Visual Studio Code, which is conveniently available for MacOS as well as my usual development environments Ubuntu and Windows. The fact the online tutorial used StackBlitz, which was built with VS Code components, should make the transition to local development easier. But how do I get all the Angular helper goodies I saw in StackBlitz? A search for Angular on VSCode marketplace returned many hits, a good sign of a large development community. One of the extensions appears to be published by Angular themselves, which sounds like a promising addition.

While installing the Angular extension, VS Code suggested that I might also be interested in Prettier code formatter extension. This is a different approach than my last experiment in maintaining coding conventions and I thought it might be worth a look. I like the concept of keeping code formatting configurations as a file in the project. This keeps all developers working on the same project on the same page, rather than requiring everyone to set it up on their own machines. I seemed to have goofed something in the setup, though, as Prettier didn’t seem to do anything as I proceeded through the tutorial. I’ll come back to this later.

The last bit is actually a decision I have to make. When I run ng new to create a new Angular project, I can optionally specify “strict mode” with the --strict flag. I had no idea what this meant, so I went and did some reading. It activates several flags passed to underlying mechanisms that I didn’t fully understand. (webpack? tree shaking?) But I liked the sound of what it aims to accomplish:

Enabling this flag initializes your new workspace or project with a few new settings that improve maintainability, help you catch bugs ahead of time, and allow the CLI to perform advanced optimizations on your application.

Since it is a code quality improvement, I expect it to add some overhead to my coding life up front. Which may not be the best of ideas on a beginner tutorial where we want to keep things easy. But I’m a fan of making the up-front tradeoff for fewer headaches in the future, so I’ll go ahead and create this tutorial project with --strict before diving in to the tutorial.