Introduction

In this tutorial, I'll share with you how I built freeCodeCamp's Build a JavaScript Calculator frontend project with Elm.

Here's the live demo of the Elm web application for you to explore how it works. And, here's the reference to its source code.

My primary goal is to share my experience, perspective and processes so that you are exposed to an alternative approach to web application development with Elm. I am not aware of any resources that explain how to develop web applications with Elm that are similar to mine. That's why I thought it might be valuable to share this with the Elm community. I am not trying to teach you Elm, nor am I trying to teach you web application development. All I'm trying to do is to have you take a look over my shoulder as I explain to you how I built the application so that you can be exposed to ideas that could be helpful to you in your own Elm projects.

Audience

Any web developer interested in using Elm to build maintainable, testable, and reliable web applications.

Prerequisites

Exposure

As I've stated before, I'm not intentionally trying to teach you anything in particular. That's why there are no learning outcomes. However, I am delibrately trying to expose you to ideas. As many ideas as it takes to develop the application in an honest and realistic way. So, after completing this tutorial I hope you will have been exposed to:

  • A process for building any Elm web application starting from a given design.
  • A bottom-up approach for building reliable UIs with HTML/CSS that's easy to maintain and extend.
  • A way to prototype with HTML/CSS.
  • A way to structure your HTML/CSS with BEM.
  • A way to design an API for your Elm views.
  • A way to separate your UI and application logic.
  • Unit testing.

Other interesting things you'd be exposed to because I'm working on a calculator, include:

The 10,000 Foot View

Design

My process starts with knowing what I want to build and how I want it to look. Design is important but it has a separate process that is outside the scope of this tutorial. The design for the calculator was inspired by lifted from this CodePen example. Thanks Peter Weinberg.

Prototype

The next step in my process is realizing the design using HTML, CSS, and possibly JavaScript. I call this my prototyping phase. Three key concepts support this phase:

  1. HTML is for structure and semantics (meaning).
  2. CSS is for styling and layout.
  3. JavaScript is for controlling dynamic behaviour and managing application logic.

In practice, by keeping these concepts in mind, it helps me to have a clear separation between the user interface (UI) and the application logic. The UI consists of HTML, CSS, and some JavaScript for controlling dynamic behaviour. The application logic consists entriely of JavaScript.

The main goal I try to achieve in this phase is to solve most if not all the UI related problems that the design surfaces. This phase is the phase to figure out HTML semantics, CSS selector names, accessibility, layout, etc.

HTML/CSS to Elm

At this point in the process most if not all of my UI related problems have been solved and it's time to translate the HTML portion into elm/html. This is typically straightforward to do but there is a little bit of view function API design that tends to occur. However, this is definitely the easiest part of the entire process.

Application Logic

The brains of the application is managed by JavaScript and hence, in our case as Elm developers, by Elm. In this part of the process I build a logical model for the application domain. Elm really shines during this part of the process because functional programming using modules, opaque types, union types, pattern matching, immutable data types, and pure functions supports a delightful approach to data modeling.

I don't practice test-driven development but I do test and unit testing the tricky parts of my application logic helps me to find and fix bugs.

Web Application = UI + Application Logic

Finally, I connect the UI with the application logic. The UI provides the means by which input gets passed to the API that models the application domain.