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.

Samsung 500T Unexpected Power Consumption Caused By Patch Tuesday

I’ve set up my unloved Samsung 500T tablet to display the current position of the International Space Station around the clock. This was a very steady and predictable workload for the machine, which made it the perfect solar power test subject. Since the time I devised a first draft of a strategy for maximize solar power runtime, I’ve been tweaking it as I go.

The tablet has behaved predictably over several weeks, so I could test different times to connect/disconnect from the solar panel and maximize storage time while also keeping the battery state of charge between 20% and 80% to maximize its cycle life. It’s not a very precise experiment on my end because I’ve been connecting and disconnecting power manually. An automated solution is in the future, once I’ve figured out what I want to do.

Things were going well until Tuesday of this week, when my power scheme went awry. First problem was that I neglected to disconnect power when it reached 80% SoC, that was on me. But then I ran into a second problem: the power consumption was extremely erratic after I disconnected power to the tablet (area highlighted in red.) As far as I knew, I did nothing to trigger any change in behavior, and the tablet isn’t displaying anything other than the ESA ISS Tracker. What’s going on?

The keyword is “Tuesday”, more specifically, it is the second Tuesday of the month when Microsoft pushes out security updates for Windows. On my other Windows computers, Patch Tuesday takes only a few minutes to download and install. But the Samsung 500T is so slow, patch installation is a drawn-out multi-hour affair. During which it consumes significantly more power than just displaying the ESA ISS tracker.

This episode reminds me of the value of long term testing, and that my Samsung 500T solar power strategy will need to allocate more power on the second Tuesday of the month.

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.

Angular CLI Setup Adventures on MacOS

It was fun to get a taste of Angular completely risk free, without installing anything on my computer courtesy of StackBlitz. I saw enough to believe Angular is worth additional exploration, so it’s time to go ahead and install those developer tools. For this run, I decided to set it up on my Macbook Air running MacOS X Catalina. Following installation directions, Angular CLI installation failed with:

warn checkPermissions Missing write access to /usr/local/lib/node_modules

I probably could get past this problem with sudo, but I looked around for a better way. According to this StackOverflow thread I need to take ownership of a few directories important to Node.JS. Rather than following the list blindly, I only took ownership as needed. Starting with /usr/local/lib/node_modules because that was the specifically named in that error message. After that, I saw a different error:

│ npm update check failed │
│ Try running with sudo or get access │
│ to the local update config store via │
│ sudo chown -R $USER:$(id -gn $USER) /Users/roger/.config │

So I grabbed ownership of .config, and all seems sorted on the permissions front. With the CLI tools installed, I tried to create a new app. It appeared to mostly work but towards the end I saw an error:

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

I have no idea what xcrun had to do with anything. Searching around for what this message might mean, I found a hit on StackExchange explaining this is a very cryptic way to tell me I haven’t yet installed developer tools on my Macbook. In this specific case, git has not yet been installed. I don’t know what xcrun has to do with git, but it appears to be involved in Angular CLI setting up a new project. I guess it calls git init as part of the project creation? In any case, running xcode-select --install got me started. Once git was installed, I configured my required global settings (name and email.) Once that was done I could successfully run the new Angular creation script, whose output at the end confirms it initializes the project as a git repository.

✔ Packages installed successfully.
    Successfully initialized git.

Running ng serve allowed me to load up the boilerplate default Angular application screen in my browser, confirming project creation success and green light to proceed setting up for the tutorial.

StackBlitz: a Web App for Building Web Apps

It’s always nice when the team behind a particular piece of software put in an effort to make newcomer introduction easy. Part of Angular’s low-friction introduction shopping app tutorial is letting us learn Angular basics without installing anything on our development machines, by using the web-based development environment StackBlitz. After I used it for the Angular tutorial, I took a quick detour to learn a bit more about StackBlitz to see what else it might be useful for.

According to the StackBlitz announcement post in 2017, its foundation is built from components of Visual Studio Code but transformed to be accessible via a browser. Behind the VSCode-based UI is a big pool of virtual machines spun up on-demand to support front-end web development. StackBlitz started with support for Angular and React, and more have been added since. Plus a beta program for full stack development so their ambition is still expanding. These virtual machines perform code compilation and also a web server to host the results. These servers are public by default, so developers can check how their results look on a cell phone, on a tablet, etc.

But while StackBlitz gives us online compute resources, their generosity does not extend to online storage. Their “tight GitHub integration” is another way of saying all our project code must be stored in our GitHub repositories. If a user is not willing to enter their GitHub credentials, their work only lasts until they disconnect and the virtual machines are shut down. Since I’m squeamish about spreading my GitHub credentials any more than I absolutely have to, this meant abandoning my Angular introductory app once it was complete.

That was the biggest damper on my enthusiasm for StackBlitz. If it weren’t for that bit of security paranoia, I would consider it a good replacement (at least, for the supported types of projects) for Cloud9 which used to be another free online development environment. Unfortunately, after Cloud9 was acquired by Amazon, using Cloud9 is no longer free. Even though Cloud9 is still very affordable in absolute terms (doing my LRWave project on Cloud9 only cost me $0.43 USD) there’s a huge psychological gap between $0.43 and free. Will StackBlitz lose its free usage in the future? Probably. Money to pay the bills for those virtual machines have to come from somewhere.

If this freebie goes away, so be it. It wouldn’t be the end of the world for the average Angular developer because the primary usage scenario is still centered around installing the tools on a development machine.

Notes on Angular Getting Started Shopping App

Wading into a new domain always means learning a new vocabulary as well. The first thing I read was Introduction to Angular Concepts, knowing full well not all of it would make sense until later. The most valuable thing it taught me is that certain generic-sounding words actually have specific meanings within an Angular context, which is an important lesson to learn while reading documentation. In this case, I have to be careful when coming across words like “modules”, “components”, and “services”.

Angular’s “Getting Started” section starts out with a “Try It” walk through building a sample Angular application. It is a mock shopping app with a product list, a shopping cart, and checkout UI. They do the usual web app things like creating forms (got to have those forms) and communicate over HTTP. Following along with this sample, I got to see the concepts of “components” and “services” put into practice. I’m still a little fuzzy on “modules”, though. I believe it is because modules don’t really come into their own until we have a much larger project. At which point it makes sense to group lots of components into modules, something that would not be necessary in a small sample tutorial.

I also got to see the good and bad sides of using TypeScript. The good news is that some mistakes will trigger compile-time errors for me to fix before proceeding. I find this a vast and compelling improvement over JavaScript standard operating procedure of watching things going awry at runtime and trying to debug what went wrong. The bad news is that it’ll take some experience before I can understand what those error messages are trying to tell me. Here’s one example of an error message that I found bewildering. It wasn’t immediately obvious to me that I used too many curly braces, three instead of two.

Template parse errors:
Parser Error: Missing expected : at column 9 in [ {{{}}} ] in ng:///AppModule/ProductListComponent.html@3:6 ("

<div *ngFor="let product of products">
<h3>[ERROR ->]
"): ng:///AppModule/ProductListComponent.html@3:6
Parser Error: Unexpected end of expression: {{{}}} at the end of the expression [ {{{}}} ]

Going through the exercise I learned that an Angular component typically associates the three parts of web development (HTML, CSS, JavaScript) into a functional unit. The JavaScript file defines the component class. The HTML is modified with Angular-specific annotations and called the component template. And the component style sheet was a pleasant surprise, since I had struggled with how to best organize my style sheet files in earlier projects. Hopefully Angular components will make it easier.

I felt it was an effective introduction, giving a quick tour of major components of Angular and giving me enough of a vague idea of what’s going on, enough to proceed further and learn more. But before I go deeper into Angular, a little detour to look at the infrastructure behind this “Try It” walkthrough.

Siren Call of Angular Material

I started thinking about doing another web technology project because I thought it might be good to have the option of building my own custom Node-RED Dashboard widgets. But during my research of study prerequisites I started reading about Angular. The more I read, the more I think it’s worth a closer look. I was enticed by the following:

  • It is a web technology of the SPA (single page application) era, moving more processing to the web browser and reducing load on the web server. Google has obvious incentive to reduce their server load, but it also means SPAs can be compiled down to static content and hosted on any web server. For hobbyist projects, this drops the minimum hardware requirement from a Raspberry Pi (to run something like Ruby on Rails) down to an ESP32 (static web server).
  • Angular is built on TypeScript, which adds compile-time type checking capabilities to JavaScript. Potentially eliminating a lot of JavaScript runtime failures that have frustrated me in the past.
  • And last but definitely not least: Angular Material components

Angular Materials is now my primary motivation, displacing Node-RED Dashboard. I’ve been fascinated by Google’s Material Design ever since the concept was launched. This is not a surprise to anyone who’ve seen my web technology projects. The SGVHAK rover UI was built on an early version of Materialize CSS. It gave me a Material Design look but with usage semantics somewhat resembling Bootstrap. My LRWave project was written using completely different set of tools, but it also picked up a Material Design style by the use of Material Design Components (MDC) for Web.

So the siren song call of Material Design has pulled me in yet again, this time to Angular and the promise of being able to build UI for projects that can be hosted anywhere… from static servers like an ESP32 or GitHub Pages, to full fledged web server running on a Raspberry Pi, to desktop applications via ElectronJS.

It all sounds very attractive for a tool to add to my toolbox, so I’ll start investing some time into learning Angular.

Diving Into Web Technologies Again

Digging into an obscure button was fun, but (sadly?) not the main focus of this blog, which is for me to write down notes about my projects and technology explorations. If anyone finds the information useful, that’s just icing on the cake.

This time around, getting back to “work” puts focus on software development. My learning experience with the Node-RED Dashboard taught me it was very easy to get a functional browser-based UI up and running giving users like myself a fantastic way to build out ideas. But with ease of use comes the usual trade-off of limited control. The people behind Node-RED Dashboard is aware of this, providing anyone who is unsatisfied with the default tools an entry point to add custom dashboard widgets. Unfortunately, the learning curve climbs sharply upwards for me since I have little experience with many of the underlying technologies. If I want to explore that world, I have to weigh the following points:

  1. No experience with AngularJS (a.k.a Angular v1) which is the foundation of Node-RED Dashboard.
  2. No experience with Angular (a.k.a. Angular v2+) which is an incompatible but currently-maintained replacement.
  3. No experience with creating reusable JavaScript modules or the convention around creating packages.
  4. Only basic skills with HTML, CSS, and JavaScript.

This list is sorted roughly in the order of most- to least-specific to my original motivation of creating custom Node-RED widgets. With such a list it usually makes the most sense to start at the top (focus on the motivating goal) or start at the bottom (build a solid foundation.)

For the purposes of foundation building, I’ve tackled a few HTML/CSS/JavaScript projects but nothing that really stuck with me for long term development. An early example was the web based UI for SGVHAK rover, which eventually became my default control scheme for Sawppy rover as well. Updating that UI has been on my to-do list ever since, and I have yet to get back to it. I later explored a different set of web development tools with my LRWave project, but again that had been set aside after v1.0 was complete. Given this track record, I’m not sure retreading the same grounds will give better results.

So what about the other side? Start with AngularJS? I was ready to do so because of Node-RED Dashboard, but most of my motivation evaporated when I learned AngularJS has been abandoned. If I want to learn something that’ll be useful beyond Node-RED dashboards, I should learn its successor Angular instead.

But there was also a more vain attraction to Angular that called to me…

A Delight for the Button Connoisseur

Yesterday I documented my quest to track down a button I saw on a prop used in the movie Sneakers which premiered 28 years ago. Eventually learning that they were Omron B3J-2100s, and they are still available for purchase from Digi-Key. Given the age of the movie, plus the fact this little detail was not important to the plot, plus the fact the rows of buttons were on screen for only roughly five seconds, I expected my blog post to quickly disappear into footnotes of the internet. Like everything else on this blog it was just a note from my personal explorations. Maybe it’ll receive an occasional a visitor, here to learn how to get these buttons for themselves.

Judging by web traffic, I was quite mistaken. I knew that the movie made impressions on others like myself, but I underestimated how many of us were out there. And even more surprisingly, these buttons made an impression on people as well. I had no idea there were so many button connoisseurs out there whose appreciation for a switch goes beyond whether it can reliable close and open a circuit. My blog post and associated Tweet were picked up by Adafruit blog and someone even submitted it to Hacker News where it was as high as #13 for a brief time. Amazing.

Its popularity also received feedback from many others. I found the prop in the movie was a Sequential Circuits Prophet 2002, but several people brought up the Roland TR-808 and there was also a mention of the Oberheim OB-X. They all used similar looking buttons for similar purposes: select options and an associated LED to indicates the active item. However, despite the similarity (and the TR-808 uses color to great effect) they are not the same Omron B3J buttons of a Prophet 2002.

I started posting a few corrections, but then I stopped. I realized that people were just sharing their own fond memories and there is no particular reason I have to point out they weren’t Omron B3Js. If someone is fond of a stylish button, what’s the point of taking away their joy? For the sake of pedantic correctness? Nah, we’re all connoisseurs of our own favorites. They have theirs, and I have Omron B3J.

Thanks to [garrettlarson] on Hacker News, we have a link to a YouTube clip where we can see the Prophet 2002 and its row of Omron B3J-2100s. (Go to ~1:20 if embedded time offset isn’t working.)