In 2011, I wrote my first single-page web-app.  I called it the Affordable Living Calculator, or "ALC".  ALC's purpose was to help people with elderly parents compare assisted-living facilities based only on how long they could afford to stay at each one.  I'll go into more detail about the motivation for this web-app in another post.

The first time I wrote this I used the SproutCore Javascript framework.  A colleague recommended it to me one night afer a talk.  I found it devilishly difficult to master.  I spent many all-nighters.  I don't think I ever got the app to work completely right.  When I finally showed it to a focus-group comprised of my wife and my uncle, they found the UI to be incomprehensible.  I'll go into that experience in another post as well.  Now I want to make another go of it.  I have some long-term goals for it, but I'll get into that later, in another post.

Now, after having written several single-page-apps with AngularJs over the past few years, I began to notice all the buzz about ReactJs.   React focused on client-side rendering HTML elements and not much else.  There is no over-arching framework for how to organize your app.  And no built-in mechanism to resolve dependencies with providers (dependency-injection, or DI)  as Angular provides.  In return, you get to write web components that are clean and easy to reason about.  To my surprise, I began not to notice the lack of built-in dependency-injection.  There are plenty of available tools from other repositories for things like mocking endpoints and services.

For testing, I found that Jest and Enzyme were adequate for my needs.  Since React scope is narrower than Angular, it is still possible to choose from a sizable universe of framework-neutral add-on modules and services an app might need.

At first, I could not find an example of using Jest in watch-mode.  All my Google searches on Jest and Continuous Integration (CI) turned up pages about snapshotting, a feature I haven't needed yet.  But then I stumbled upon a blog or Stackoverflow response somewhere and was surprised at how easy it is.  The short answer is, in my package.json "scripts" section, I have

  "scripts": {
"test": "NODE_ENV=test jest --verbose",
"test:watch": "yarn test -- --watch",
...
}

Easy!

There are several goals I had in mind for my app:

  1. Make the UI more intuitive.
  2. Make the app multi-lingual.  Make it so that English just works, but adding support for other languages should be straightforward and require a minimum of fuss and configuration.  While I originally envisioned this app for an American user-base, I soon realized that once it's hosted, anyone with a web browser and an internet connection can get to it, so I might as well allow as many people as I can to use.
  3. Keep it very simple.  Have it do only one thing and do it well.  No bells and whistles.
  4. Respect privacy of respondents.  I will cover this in detail in a subsequent post.
There are also several goals I had in mind for myself while building this app:
  1. Learn how to configure an effective and efficient build and test process with Yarn and webpack.
  2. Learn how to use Redux with React.  Redux can help to make it more straightforward how to wire up components to respond to actions in other components.
  3. Learn how to write effective and comprehensive unit tests for React components.
  4. Learn how to develop and use higher-order components to standardize form-input validation.
  5. Learn how to write and deploy my app as a standalone component with minimal dependencies that can be included in other apps.  This will give me more flexibility for choosing an overall design of the site that hosts the app as a component.  In particular, another app or page that hosts this component need not know anything about my component's dependency on Redux.
  6. Learn how to easily and cheaply deploy my component on its own page for demo purposes.
This app is still in development, but I think I have been successful in accomplishing most my short-term initial goals.  In particular, I now have what I consider to be a flexible and robust development and test framework with Yarn, Webpack, Jest and Enzyme.  

While my work on ALC is private, I want to share some of my recently earned knowledge.  So I cloned the project, and made turned it into a small demo app.  There is a single form with a text input  for birth-year and a drop-down selector for gender.  Each are initialized to an empty value and require a value, forcing the end user to provide a value or make a choice.  Each validate their inputs and display an error message if the validation is not satisfied.

In addition, there is a drop-down above the form to select a language.  This selector is not part of the component.  Presumably, the language will be chosen from the HTTP Accept-Language header in the request for the page that hosts the component.  The selector allows the user to over-ride it if another language is available that he/she prefers.  All the labels and error messages should immediately render again in the new language if one is chosen without need to refresh the page or focus and change input values to force re-validation.


I posted about form-validation with Angular2 in August of 2016.  Angular2 was still in beta, and I immediately ran into technical issues, as did most people who played with it.  The result wasn't very pretty and the post reflects that.