Dhruv's Blog2015-03-09T07:11:25+00:00http://dhruvp.github.ioDhruv Parthasarathydhruv@udacity.comRe-Frame - Functional Reactive Programming With Clojurescript2015-03-07T00:00:00+00:00http://dhruvp.github.io/2015/03/07/re-frame<!--
- Step 1 - Editing the phones page
- intro to hiccup syntax
- what's cool about hiccup syntax?
- Step 2 - A Basic Phone List
- Reagent components
- Introduction to Reactions and Ratoms
- Dispatchers
- Subscribers
- Handlers
- Step 3 - Search
- search input reaction/stream
- handler for search dispatcher
- Search input component
Step 4 - Ordering
- functions on components
- mark selected
Step 5 - Ajax
- ...
Step 6 - Adding images
- talk about how nice reagent makes it to keep and maintain components
Step 7 - Add new route
- Secretary
- setToken google History
Step 8 - Filling out the phone detail page
- Create a template for phone details
- would love to contrast this with angular at this point
- Good chance to discuss reactions more also
Step 9 - Load phone data over ajax
- Again nice point to compare against Angular
- no additional templating language - just cljs!
Step 10 - Select Images
- Simple
Takeaways
- may seem like framework is adding overhead but since it makes it so easy to reason about I think it's worth it
- all our logic is pure functional logic! No state transformations - so testing will be a breeze
- One way data flow vs Two way data flow
- templating is so much simpler. Compare their code vs ours - ours is way more concise! -->
<!-- - Why FRP?
- async programming is tough
- callbacks are not a good way of describing processes
- promises only deal with one off events
- link to Rich Hickey's talk on the matter
- One solution is FRP
- deal with streams of events and focus on describing WHAT to do rather than HOW to do it
- focus on core logic vs. how to implement async behavior (calblacks etc.)
- link to Jafar Hussain's talk
- it isolates state so you barely have to worry about it
- Wy Clojurescript
- built from the ground up to play well with functional programming
- persistent data structures
- strong tools for avoiding state manipulation
- community!
- Enter Re-frame
- What is it?
- architecture built on top of Reagent to design FRP based apps
- emulates Flux and Elm Lang with Reagent as the view layer
- Architecture
- Model Layer
- single place where all data is stored
- Subscription Layer
- create streams based on transformations of the data
- View Layer
- plug the streams of data into Reagent components that auto update on new data
- Dispatch Layer
- Dispatch events that change app data out and start over
- NEEDS DIAGRAM HERE
- Why use it?
- easy to reason about application
- all state stored in one place
- each view corresponds to a specific value of the state
- fast
- lightweight -->
<p>In this blog post, I’m going to walk you through the port of the Angular Phonecat tutorial in Re-frame - a very simple, yet expressive, library for architecting Single Page Apps in Clojurescript. Rather than discuss why use such a framework, I’ll let Mike’s excellent <a href="https://github.com/Day8/re-frame">writeup</a> on the project do the talking. Read it? Okay let’s get into building an app with phone-cat! We’re going to go step by step and mirror the exact steps taken in the official angular <a href="https://docs.angularjs.org/tutorial">walkthrough</a>. As a result, you’ll be able to compare each step against its analog in Angular and get a better feel of how these frameworks are different and what their strengths and weaknesses are.</p>
<p>Finally, each step has its own branch in this <a href="https://github.com/dhruvp/angular-phonecat-re-frame" target="_blank">repository</a>. So feel free to clone, fork, and follow along with the code for each step!</p>
<h2 id="step-0---setting-up">Step 0 - Setting up</h2>
<h3 id="a-hrefhttpsgithubcomdhruvpangular-phonecat-re-frametreestep-0-targetblankdiffa"><a href="https://github.com/dhruvp/angular-phonecat-re-frame/tree/step-0" target="_blank">Diff</a></h3>
<h3 id="explanation">Explanation</h3>
<p>Okay let’s get started! Step 0 is where we set up our application. The steps are as follows:</p>
<ol>
<li>Download <a href="http://leiningen.org/" target="_blank">Leiningen</a></li>
<li>Run lein new reagent angular-phonecat-re-frame</li>
</ol>
<p>Awesome! You should have the scaffolding for the app. Let’s try and understand the pieces of the scaffolding.</p>
<ul>
<li>
<p>project.clj</p>
<ul>
<li>Project.clj defines the libraries your project depends on and its build settings. See <a href="https://github.com/technomancy/leiningen#configuration" target="_blank">here</a> for more information.</li>
</ul>
</li>
<li>
<p>src/cljs/phonecat_re_frame/</p>
<ul>
<li>This is where most of our main application logic will go. During the build step, we are going to look at the cljs code here and compile it into javascript.</li>
</ul>
</li>
<li>
<p>resources/templates</p>
<ul>
<li>This is where we will place our html.</li>
</ul>
</li>
<li>
<p>resources/public</p>
<ul>
<li>This will hold the css, images, js, and other resources for our project. After the build compiles the clojurescript into javascript, it will place the javascript in a subdirectory of this folder.</li>
</ul>
</li>
</ul>
<p>Now go ahead and open src/cljs/phonecat_re_frame/core.cljs. This is where our main logic will go! I’m going to assume that you have a basic idea of reagent from here going forward. If you don’t check out my <a href="http://dhruvp.github.io/2015/02/23/mailchimip-clojure/" target="_blank">post</a> on reagent where I go into further detail than I’ll have room for here.</p>
<h2 id="step-1---a-basic-phone-page">Step 1 - A basic phone page</h2>
<h3 id="a-hrefhttpsgithubcomdhruvpangular-phonecat-re-framecomparestep-0step-1-targetblankdiffa"><a href="https://github.com/dhruvp/angular-phonecat-re-frame/compare/step-0...step-1" target="_blank">Diff</a></h3>
<h3 id="explanation-1">Explanation</h3>
<p>In our first step, we just fill out our home page to show a little information about some phones. If you haven’t seen hiccup before this should be a good introduction. Hiccup allows us to define html elements using Clojure vectors. Let’s look at an example to understand how it works. In the current step, we added the following Hiccup Vector:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">[</span><span class="ss">:ul</span>
<span class="p">[</span><span class="ss">:li</span>
<span class="p">[</span><span class="ss">:span</span> <span class="s">"Nexus S"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:p</span> <span class="s">"Fast just got faster with Nexus S."</span><span class="p">]]</span>
<span class="p">[</span><span class="ss">:li</span>
<span class="p">[</span><span class="ss">:span</span> <span class="s">"Motorola XOOM with Wi-Fi"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:p</span> <span class="s">"The Next, Next Generation tablet."</span><span class="p">]]]</span></code></pre></div>
<p>This translates into the following html:</p>
<div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt"><ul></span>
<span class="nt"><li></span>
<span class="nt"><span></span>"Nexus S"<span class="nt"></span></span>
<span class="nt"><p></span>"Fast just got faster with the Nexus S."<span class="nt"></p></span>
<span class="nt"></li></span>
<span class="nt"><li></span>
<span class="nt"><span></span>"Motorola XOOM with Wi-Fi"<span class="nt"></span></span>
<span class="nt"><p></span>"The Next, Next Generation tablet."<span class="nt"></p></span>
<span class="nt"></li></span>
<span class="nt"></ul></span></code></pre></div>
<p>So what’s going on here? The first element in the vector is just the tag. So [:ul] indicates that we are creating a <ul> element. Next, we can nest elements inside other elements by nesting vectors. So [:ul [:li]] translates to <ul><li></li></ul>. To fill out the body of the element, we just add the body details after the tag name in the vector. So in our example [:span “Nexus S”] gives us <span>Nexus S</span>. Pretty neat right?</p>
<p>The awesome part about this is that our HTML is now a first class data structure that we can compose, return, and apply functions upon. Basically we have way more power over them! You’ll see how this will come in handy as we write some basic templating functions in future steps.</p>
<h2 id="step-2---using-real-data">Step 2 - Using real data</h2>
<h3 id="a-hrefhttpsgithubcomdhruvpangular-phonecat-re-framecomparestep-1step-2diffa"><a href="https://github.com/dhruvp/angular-phonecat-re-frame/compare/step-1...step-2">Diff</a></h3>
<h3 id="explanation-2">Explanation</h3>
<p>Now we are going to change our phones page to use data from a database that we setup. The re-frame architecture espouses the idea of storing all your application data in a single place. This isolates state mutations to a single place and also ensures that all your data is in sync. Ok enough talk. How do we actually set up this db?</p>
<h4 id="handlers">Handlers</h4>
<p>In re-frame, we make mutations to our db by creating handlers. A handler is just a function that takes in the current application state and some parameters and returns a new application state. What could be simpler?</p>
<p>We create our handler as an anonymous function and then register it by passing it into re-frame/register-pure-handler (pure handler just indicates that our handler doesn’t mutate state).</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">re-frame/register-pure-handler</span>
<span class="ss">:initialise-db</span> <span class="c1">;; usage: (dispatch [:initialise-db])</span>
<span class="p">(</span><span class="nf">fn</span>
<span class="p">[</span><span class="nv">db</span> <span class="nv">v</span><span class="p">]</span> <span class="c1">;; Ignore both params (db and v).</span>
<span class="p">{</span><span class="ss">:phones</span> <span class="p">[{</span><span class="ss">:name</span> <span class="s">"Nexus S"</span> <span class="ss">:snippet</span> <span class="s">"Fast just got faster with Nexus S."</span><span class="p">}</span>
<span class="p">{</span><span class="ss">:name</span> <span class="s">"Motorola XOOM™ with Wi-Fi"</span> <span class="ss">:snippet</span> <span class="s">"The Next, Next Generation tablet."</span><span class="p">}</span>
<span class="p">{</span><span class="ss">:name</span> <span class="s">"Motoral Xoom"</span> <span class="ss">:snippet</span> <span class="s">"The Next, Next Generation tablet."</span><span class="p">}]}))</span></code></pre></div>
<p>So above, we initialize our db as a hashmap with a key :phones and a corresponding value.</p>
<p>In the above declaration, we have also given our handler a name :initialise-db that re-frame will use to lookup the handler.</p>
<h4 id="dispatchers">Dispatchers</h4>
<p>Now that we’ve created our handler, how do we call it? That’s done in this little bit:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">re-frame/dispatch</span> <span class="p">[</span><span class="ss">:initialise-db</span><span class="p">])</span></code></pre></div>
<p>We call handlers by calling the re-frame dispatch function with the name of our handler. So in summary, here’s the process of what’s going on:</p>
<ol>
<li>We call dispatch with a handler name.</li>
<li>Re-frame looks up the handler and calls it with the current app data and any additional params you passed it.</li>
<li>Re-frame updates the app data with the output of the handler.</li>
</ol>
<p>This is going to be our flow for ALL events. Dispatch is called with a handler, the handler creates a new db, and we use that db going forward. But how does our app know when parts of the db have changed? We would need to update our views right?</p>
<h4 id="subscriptions">Subscriptions</h4>
<p>In Re-frame, we do that through subscriptions, which we use in the following code:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">re-frame/register-subs</span> <span class="c1">;; a new subscription handler</span>
<span class="ss">:phones</span> <span class="c1">;; usage (subscribe [:phones])</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">db</span><span class="p">]</span>
<span class="p">(</span><span class="nf">reaction</span> <span class="p">(</span><span class="ss">:phones</span> <span class="o">@</span><span class="nv">db</span><span class="p">))))</span> <span class="c1">;; pulls out :phones</span></code></pre></div>
<p>Just like register-handler, register-subs takes in two arguments: a name, and a function. The function in this case returns an ratom that represents some part of the data (Don’t worry we’ll get into ratoms in a sec). We then use this subscription to always get access to the latest value of :phones in our db. We use it as below:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">phones</span> <span class="p">(</span><span class="nf">re-frame/subscribe</span> <span class="p">[</span><span class="ss">:phones</span><span class="p">])]</span></code></pre></div>
<p>Now, whenever we call @phones, we will always have the latest value of phones in our database. The beautiful part about this is that @phones will automatically update when the underlying value gets changed in our database. Wow! That to me is pretty sick. Ok but what’s the dark magic going on here?</p>
<p>Our subscriber function,</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">db</span><span class="p">]</span>
<span class="p">(</span><span class="nf">reaction</span> <span class="p">(</span><span class="ss">:phones</span> <span class="o">@</span><span class="nv">db</span><span class="p">))))</span> <span class="c1">;; pulls out :phones</span></code></pre></div>
<p>returns an ratom representing the latest value of :phones in our app database. This is achieved through using Reagent’s reaction function. Reaction takes in a function that depends on an ratom, and returns another ratom. Now whenever the value of the ratom we depend on changes, @db in this case, the function is recomputed and the value of the ratom that reaction returns updates also. So say I had the following:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def </span><span class="nv">db</span> <span class="p">(</span><span class="nf">ratom</span> <span class="p">{</span><span class="ss">:a</span> <span class="mi">1</span><span class="p">}))</span>
<span class="p">(</span><span class="k">def </span><span class="nv">a-value</span> <span class="p">(</span><span class="nf">reaction</span> <span class="p">(</span><span class="ss">:a</span> <span class="o">@</span><span class="nv">db</span><span class="p">)))</span></code></pre></div>
<p>At this point, @a-value will be 1. If I update db and print a-value,</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">assoc </span><span class="nv">db</span> <span class="p">[</span><span class="ss">:a</span><span class="p">]</span> <span class="mi">3</span><span class="p">)</span>
<span class="p">(</span><span class="nb">println </span><span class="o">@</span><span class="nv">a-value</span><span class="p">)</span>
<span class="c1">; 3</span></code></pre></div>
<p>@a-value automatically updates! Under the hood, reaction just creates a callback that fires whenever @db changes. It then sets resets the output of its returned ratom to be the result of calling this callback on the new @db.</p>
<h4 id="view-layer">View Layer</h4>
<p>We’ve also updated our view layer in a few important ways. First, we’ve created a separate function that is responsible for displaying each individual phone item. We see it here:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">phone-component</span>
<span class="p">[</span><span class="nv">phone</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:li</span>
<span class="p">[</span><span class="ss">:span</span> <span class="p">(</span><span class="ss">:name</span> <span class="o">@</span><span class="nv">phone</span><span class="p">)]</span>
<span class="p">[</span><span class="ss">:p</span> <span class="p">(</span><span class="ss">:snippet</span> <span class="o">@</span><span class="nv">phone</span><span class="p">)]])</span></code></pre></div>
<p>Check out how freaking easy it is to create separate view components! This component just takes in a phone ratom and displays its name and snippet. Simple.
We then also create a component for displaying the phones list and have it use the phone-component we defined above:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">phones-component</span>
<span class="p">[]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">phones</span> <span class="p">(</span><span class="nf">re-frame/subscribe</span> <span class="p">[</span><span class="ss">:phones</span><span class="p">])]</span> <span class="c1">; subscribe to the phones value in our db</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:ul</span> <span class="p">(</span><span class="nb">for </span><span class="p">[</span><span class="nv">phone</span> <span class="nv">in</span> <span class="o">@</span><span class="nv">phones</span><span class="p">]</span> <span class="o">^</span><span class="p">{</span><span class="ss">:key</span> <span class="nv">phone</span><span class="p">}</span> <span class="p">[</span><span class="nv">phone-component</span> <span class="nv">phone</span><span class="p">]</span> <span class="o">@</span><span class="nv">phones</span><span class="p">)])))</span></code></pre></div>
<p>In the above snippet we first subscribe to the phones value in our db. Then, we use the power of hiccup to iterate over each phone in our database (for [phone in @phones]) and display a separate phone-component for it. We use the phone-component function by calling [phone-component phone]. To understand how this works see Mike Thompson’s awesome explanation of Reagent components <a href="https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components">here</a>. Note how we don’t need to use any new templating language - we just use clojurescript!</p>
<h2 id="step-3---search">Step 3 - Search</h2>
<h3 id="a-hrefhttpsgithubcomdhruvpangular-phonecat-re-framecomparestep-2step-3-targetblankdiffa"><a href="https://github.com/dhruvp/angular-phonecat-re-frame/compare/step-2...step-3" target="_blank">Diff</a></h3>
<p>Now let’s add a little search box that allows us to search for phones and just display the ones we are interested in.</p>
<h4 id="handlers-1">Handlers</h4>
<p>As in the previous step, we start by adding in a handler that fires when a user types something into the search box. This handler will update our app data with the new search term.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">handle-search-input-entered</span>
<span class="p">[</span><span class="nv">app-state</span> <span class="p">[</span><span class="nv">_</span> <span class="nv">search-input</span><span class="p">]]</span>
<span class="p">(</span><span class="nf">assoc-in</span> <span class="nv">app-state</span> <span class="p">[</span><span class="ss">:search-input</span><span class="p">]</span> <span class="nv">search-input</span><span class="p">))</span></code></pre></div>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">re-frame/register-pure-handler</span>
<span class="ss">:search-input-entered</span>
<span class="nv">handle-search-input-entered</span><span class="p">)</span></code></pre></div>
<h4 id="subscribers">Subscribers</h4>
<p>We also create a new subscriber to get the latest search term from the db:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">re-frame/register-subs</span>
<span class="ss">:search-input</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">db</span><span class="p">]</span>
<span class="p">(</span><span class="nf">reaction</span> <span class="p">(</span><span class="ss">:search-input</span> <span class="o">@</span><span class="nv">db</span><span class="p">))))</span></code></pre></div>
<h4 id="view-layer-1">View Layer</h4>
<p>Next, we create a simple search component that calls our new handler whenever the user types something in:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">search</span>
<span class="p">[]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">search-input</span> <span class="p">(</span><span class="nf">re-frame/subscribe</span> <span class="p">[</span><span class="ss">:search-input</span><span class="p">])])</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:input</span> <span class="p">{</span><span class="ss">:on-change</span> <span class="o">#</span><span class="p">(</span><span class="nf">re-frame/dispatch</span> <span class="p">[</span><span class="ss">:search-input-entered</span> <span class="p">(</span><span class="nb">-> </span><span class="nv">%</span> <span class="nv">.-target</span> <span class="nv">.-value</span><span class="p">)])}]))</span></code></pre></div>
<p>Note how we are passing a value into our handler function by giving dispatch a vector of two items: the first is the name of the handler, the next is the additional argument to that handler.</p>
<p>Finally, we update our phones-component to only show phones that match the search term in some way:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">matches-query?</span>
<span class="p">[</span><span class="nv">search-input</span> <span class="nv">phone</span><span class="p">]</span>
<span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">= </span><span class="s">""</span> <span class="nv">search-input</span><span class="p">)</span>
<span class="nv">true</span>
<span class="p">(</span><span class="nb">boolean </span><span class="p">(</span><span class="nf">or</span>
<span class="p">(</span><span class="nb">re-find </span><span class="p">(</span><span class="nb">re-pattern </span><span class="nv">search-input</span><span class="p">)</span> <span class="p">(</span><span class="ss">:name</span> <span class="nv">phone</span><span class="p">))</span>
<span class="p">(</span><span class="nb">re-find </span><span class="p">(</span><span class="nb">re-pattern </span><span class="nv">search-input</span><span class="p">)</span> <span class="p">(</span><span class="ss">:snippet</span> <span class="nv">phone</span><span class="p">))))))</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">phones-component</span>
<span class="p">[]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">phones</span> <span class="p">(</span><span class="nf">re-frame/subscribe</span> <span class="p">[</span><span class="ss">:phones</span><span class="p">])</span>
<span class="nv">search-input</span> <span class="p">(</span><span class="nf">re-frame/subscribe</span> <span class="p">[</span><span class="ss">:search-input</span><span class="p">])]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:ul</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"phones"</span><span class="p">}</span>
<span class="p">(</span><span class="nb">for </span><span class="p">[</span><span class="nv">phone</span> <span class="p">(</span><span class="nb">filter </span><span class="p">(</span><span class="nb">partial </span><span class="nv">matches-query?</span> <span class="o">@</span><span class="nv">search-input</span><span class="p">)</span> <span class="o">@</span><span class="nv">phones</span><span class="p">)]</span>
<span class="o">^</span><span class="p">{</span><span class="ss">:key</span> <span class="nv">phone</span><span class="p">}</span> <span class="p">[</span><span class="nv">phone-component</span> <span class="nv">phone</span><span class="p">])])))</span></code></pre></div>
<p>Here, we use Clojure’s filter function to just filter our phones vector with the function matches-query?. Note how we don’t have to create any messy callbacks or anything. @search-input automatically updates with the new value!</p>
<p>matches-query just uses a regexp to check if the search term is present in the name or snippet of the phone. Again, notice how we don’t have to define any special filters in our template. We are using plain old Clojure code.</p>
<h2 id="step-4---sorting-our-phones">Step 4 - Sorting our phones</h2>
<h3 id="a-hrefhttpsgithubcomdhruvpangular-phonecat-re-framecomparestep-3step-4-targetblankdiffa"><a href="https://github.com/dhruvp/angular-phonecat-re-frame/compare/step-3...step-4" target="_blank">Diff</a></h3>
<p>Step 4 is almost identical in nature to step 3. We are going to store an ‘order-by’ property in our app-db and use it to sort the phones in the list.</p>
Understanding Core Async vs. Events and Callbacks2015-02-24T00:00:00+00:00http://dhruvp.github.io/2015/02/24/understanding-core-async-examples<h2 id="introduction">Introduction</h2>
<p>If you read David Nolen’s <a href="http://swannodette.github.io/">blog</a>, you’ll notice he frequently extolls the virtues of Core.Async as opposed to events and callbacks. For a while, I haven’t quite understood why Core.Async and Go style concurrency is a big deal. So I went over to his blog and read this <a href="http://swannodette.github.io/2013/07/12/communicating-sequential-processes/">post</a> to get a better idea. The below is my attempt to break down his example and contrast it to what you would do in traditional eventing to finally understand why Core.Async and Go Channels are a big deal.</p>
<h1 id="diving-into-coreasync">Diving into Core.Async</h1>
<p>Core.Async, if you haven’t seen it before, is essentially a library for Clojure that gives you access to the concurrency pattern implemented in Go. To read more about it, see <a href="http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html">this</a>. Moreover, there’s an awesome talk on the matter you can check out <a href="http://www.infoq.com/presentations/clojure-core-async" target="_blank">here</a>.</p>
<p>The main idea is that Core.Async emphasizes using shared Queues as the underlying way for different processes to communicate. Each process just places its message onto the queue and anyone interested in the message, grabs the queue and reads from it. What could be more simple?</p>
<p>Well it’s not quite that simple. Say we have two processes, a Caller, and a Listener. The Caller keeps throwing out new things onto the queue, and the Listener is listening to new things on this queue. How would the listener know when to listen to the queue and pick new things off it? Naively, it would have a while loop where it just keeps checking the size of the queue right? We obviously don’t want this as it would block the hell out of our program! Both Go and Core.Async solve this problem using Goroutines which essentially are light weight threads that run asynchronously. When Listener listens to a queue from within a go routine, it parks the go routine and returns execution to the main thread UNTIL there’s something to get from the queue. This way you’re not blocking AND you know when stuff comes off the queue. Really the bigger idea here is that the Listener and Caller don’t have to know eachother in any way. All they have to do is share a queue and that leads to a simpler, decoupled design. BOOM.</p>
<h1 id="diving-into-david-nolens-example">Diving into David Nolen’s example</h1>
<p>In David Nolen’s <a href="http://swannodette.github.io/2013/07/12/communicating-sequential-processes/">blog post</a>, he starts off with an example that he says should make you “fall out of your chair”. I honestly did not fall out of my chair at first because I didn’t understand it! So I’m now going to break it down and say WHY what he’s doing is interesting and what’s cool about it. In his example, Nolen creates 3 independent processes fire events off at different rates. He then creates a fourth process that collects the events from these three processes and presents them to the user. You should just go check it out because it’s best understood by seeing it. His code is here for reference.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">def </span><span class="nv">c</span> <span class="p">(</span><span class="nf">chan</span><span class="p">))</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">render</span> <span class="p">[</span><span class="nv">q</span><span class="p">]</span>
<span class="p">(</span><span class="nb">apply </span><span class="nv">str</span>
<span class="p">(</span><span class="nb">for </span><span class="p">[</span><span class="nv">p</span> <span class="p">(</span><span class="nb">reverse </span><span class="nv">q</span><span class="p">)]</span>
<span class="p">(</span><span class="nb">str </span><span class="s">"<div class='proc-"</span> <span class="nv">p</span> <span class="s">"'>Process "</span> <span class="nv">p</span> <span class="s">"</div>"</span><span class="p">))))</span>
<span class="p">(</span><span class="nf">go</span> <span class="p">(</span><span class="nf">while</span> <span class="nv">true</span> <span class="p">(</span><span class="nf"><!</span> <span class="p">(</span><span class="nf">timeout</span> <span class="mi">250</span><span class="p">))</span> <span class="p">(</span><span class="nf">>!</span> <span class="nv">c</span> <span class="mi">1</span><span class="p">)))</span>
<span class="p">(</span><span class="nf">go</span> <span class="p">(</span><span class="nf">while</span> <span class="nv">true</span> <span class="p">(</span><span class="nf"><!</span> <span class="p">(</span><span class="nf">timeout</span> <span class="mi">1000</span><span class="p">))</span> <span class="p">(</span><span class="nf">>!</span> <span class="nv">c</span> <span class="mi">2</span><span class="p">)))</span>
<span class="p">(</span><span class="nf">go</span> <span class="p">(</span><span class="nf">while</span> <span class="nv">true</span> <span class="p">(</span><span class="nf"><!</span> <span class="p">(</span><span class="nf">timeout</span> <span class="mi">1500</span><span class="p">))</span> <span class="p">(</span><span class="nf">>!</span> <span class="nv">c</span> <span class="mi">3</span><span class="p">)))</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">peekn</span>
<span class="s">"Returns vector of (up to) n items from the end of vector v"</span>
<span class="p">[</span><span class="nv">v</span> <span class="nv">n</span><span class="p">]</span>
<span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">> </span><span class="p">(</span><span class="nb">count </span><span class="nv">v</span><span class="p">)</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="nb">subvec </span><span class="nv">v</span> <span class="p">(</span><span class="nb">- </span><span class="p">(</span><span class="nb">count </span><span class="nv">v</span><span class="p">)</span> <span class="nv">n</span><span class="p">))</span>
<span class="nv">v</span><span class="p">))</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">el</span> <span class="p">(</span><span class="nf">by-id</span> <span class="s">"ex0"</span><span class="p">)</span>
<span class="nv">out</span> <span class="p">(</span><span class="nf">by-id</span> <span class="s">"ex0-out"</span><span class="p">)]</span>
<span class="p">(</span><span class="nf">go</span> <span class="p">(</span><span class="k">loop </span><span class="p">[</span><span class="nv">q</span> <span class="p">[]]</span>
<span class="p">(</span><span class="nf">set-html!</span> <span class="nv">out</span> <span class="p">(</span><span class="nf">render</span> <span class="nv">q</span><span class="p">))</span>
<span class="p">(</span><span class="nf">recur</span> <span class="p">(</span><span class="nb">-> </span><span class="p">(</span><span class="nb">conj </span><span class="nv">q</span> <span class="p">(</span><span class="nf"><!</span> <span class="nv">c</span><span class="p">))</span> <span class="p">(</span><span class="nf">peekn</span> <span class="mi">10</span><span class="p">))))))</span></code></pre></div>
<p>Nolen immediately says that, when done without any mutability, “[this] should seem impossible for those familiar with JavaScript)”. Let’s find out why!</p>
<p>We first recreate Nolen’s render and peek functions in JS. They’re simple enough!</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="nx">render</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">q</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">str</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span>
<span class="nx">q</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">processNumber</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="s2">"<div class='proc-"</span> <span class="o">+</span> <span class="nx">processNumber</span> <span class="o">+</span> <span class="s2">"'>Process "</span> <span class="o">+</span> <span class="nx">processNumber</span> <span class="o">+</span> <span class="s2">"</div>"</span><span class="p">;</span>
<span class="p">}));</span>
<span class="p">};</span>
<span class="nx">peek</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">v</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">v</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="nx">n</span><span class="p">,</span><span class="nx">v</span><span class="p">.</span><span class="nx">length</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">v</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span></code></pre></div>
<p>Now let’s focus on the main concept. We now need to create three processes that fire off events at different rates and somehow collect them all. I’m going to start by recreating the three independent processes that fire at different rates and place their events onto some sort of list. This is easy enough with callbacks:</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="nx">subscribeToProcess1</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">},</span> <span class="mi">250</span><span class="p">);</span>
<span class="p">};</span></code></pre></div>
<p>And likewise for the other processes.</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="nx">subscribeToProcess2</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">subscribeToProcess3</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">callback</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="p">},</span> <span class="mi">1500</span><span class="p">);</span>
<span class="p">};</span></code></pre></div>
<p>Ok now that I have these processes set up, let me call them. I’m going to create an array to collect all the events.</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="kd">var</span> <span class="nx">collector</span> <span class="o">=</span> <span class="p">[];</span>
<span class="nx">callback</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">collector</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">event</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">subscribeToProcess1</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
<span class="nx">subscribeToProcess2</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
<span class="nx">subscribeToProcess3</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span></code></pre></div>
<h2 id="processing-and-rendering">Processing And Rendering</h2>
<p>If I’m to proceed. I need to do something like what Nolen does here:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">go</span> <span class="p">(</span><span class="k">loop </span><span class="p">[</span><span class="nv">q</span> <span class="p">[]]</span>
<span class="p">(</span><span class="nf">set-html!</span> <span class="nv">out</span> <span class="p">(</span><span class="nf">render</span> <span class="nv">q</span><span class="p">))</span>
<span class="p">(</span><span class="nf">recur</span> <span class="p">(</span><span class="nb">-> </span><span class="p">(</span><span class="nb">conj </span><span class="nv">q</span> <span class="p">(</span><span class="nf"><!</span> <span class="nv">c</span><span class="p">))</span> <span class="p">(</span><span class="nf">peekn</span> <span class="mi">10</span><span class="p">)))))</span></code></pre></div>
<p>Now I need to just get the last 10 events and render them. In accordance with Nolen’s solution, I’ll make sure that the array I pass to peek and render isn’t mutated by anything else.</p>
<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="nx">callback</span> <span class="o">=</span> <span class="nx">fn</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">render</span><span class="p">(</span><span class="nx">peek</span><span class="p">(</span><span class="nx">collector</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="nx">event</span><span class="p">]),</span> <span class="mi">10</span><span class="p">));</span>
<span class="nx">collector</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">event</span><span class="p">);</span>
<span class="p">};</span></code></pre></div>
<p>This does indeed work like Nolen’s example. Whenever one of my processes fires an event, it will add the event to the collector, and then render and peek will be called on the collector to display the values. And indeed, the array passed in to peek and render will not be mutated.</p>
<p>Note that Nolen, much like us, uses mutable state to collect the events from the separate processes. A channel is indeed an example shared mutable state!</p>
<h1 id="so-whats-the-big-deal">So what’s the big deal?</h1>
<p>It seems like we were able to recreate Nolen’s solution in JS without too much crazyness. So what’s the big deal after all? I think it is this: Nolen’s solution uses no callbacks and I think that’s really his main point. In this toy example it may not seem like a big deal, but for those who’ve dealt with callback hell, it probably will be. Callback hell is essentially a way of describing the following problem - Callbacks are not always a good way of representing processes and flows through a program. This is because if you want to impose any kind of ordering on multiple such callbacks, you quickly start nesting callbacks which leads to code that can be hard to understand. On the other hand, the ideas used by Core.Async do a great job of explaining processes. In Nolen’s code, it’s clear that the following happen in order:</p>
<ol>
<li>An event is pulled off the channel</li>
<li>That event is added to the vector of existing events to create a new vector</li>
<li>Peek and Render are called on the new vector</li>
</ol>
<p>Why is this clear? Because his code is able to describe this process in a very nice, imperative way:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nb">-> </span><span class="p">(</span><span class="nb">conj </span><span class="nv">q</span> <span class="p">(</span><span class="nf"><!</span> <span class="nv">c</span><span class="p">))</span>
<span class="p">(</span><span class="nf">peekn</span> <span class="mi">10</span><span class="p">))</span></code></pre></div>
<p>Moreover, it’s a better separation of concerns. In the callback code, the processes that generate the events also have to worry about running code for collecting and rendering those events. In fact they are potentially running arbitrary code from whoever called them via the callback. Similarly, even if we used an eventing system, the eventing system would have to still run arbitrary code when an event happens.</p>
<p>In Nolen’s version there is no such problem. All the processes have to do is push events onto a channel and that’s it. There’s no executing arbitrary code, handing control of execution over etc. Indeed this is quite simple! And if you’ve heard Rich Hickey Talk, then you’ll know that simple is easy.</p>
Building a login form in Clojurescript and Reagent2015-02-23T00:00:00+00:00http://dhruvp.github.io/2015/02/23/mailchimip-clojure<p>I recently have been reading up on LISP (on LISP) a lot lately and have been quite excited by the ideas and simplicity of the language. So I looked for a nice project to get started on and decided to try building a simple Mailchimp-esque login form in Clojurescript to get my feet wet. You can see the dead simple demo <a href="https://dhruvp.github.io/mailchimp-form-cljs/" target="_blank">here</a>, and the full repo <a href="https://github.com/dhruvp/mailchimp-form-cljs" target="_blank">here</a>. It is inspired by Lukas Ruebbelke’s awesome <a href="http://onehungrymind.com/build-mailchimp-signup-form-angularjs/" target="_blank">post</a> on the same idea, but in Angular. Below, I’m going to walk you through the process of how to get from 0 to a working site and all the cool things I learned along the way. Ready? LEGGO!</p>
<h2 id="what-is-clojurescript">What is Clojurescript</h2>
<p>Clojurescript is tightly associated with Clojure, the LISP with all the attention these days that runs on the JVM. The language itself is almost identical to Clojure with the primary difference being that Clojurescript compiles to Javascript and thus can be used for client side code! If you want to learn more about Clojure and Clojurescript, do listen to Rich Hickey’s talks on the language and its ideas. They’re really well presented and beautifully explained. See the following:</p>
<ul>
<li><a href="https://www.infoq.com/author/Rich-Hickey" target="_blank">A collection of Rich Hickey Talks</a></li>
<li><a href="https://www.braveclojure.com/" target="_blank">An introduction to learning Clojure</a></li>
<li><a href="https://github.com/magomimmo/modern-cljs">A series of tutorials on Clojurescript</a></li>
</ul>
<h2 id="what-are-we-going-to-do">What are we going to do?</h2>
<ol>
<li>Setup a development process for Clojurescript</li>
<li>Walk through building a simple form for login with the following:
<ul>
<li>Validate the form as it’s being typed</li>
<li>Hide and show labels based on your focus</li>
</ul>
</li>
</ol>
<p>Alright then! On to step 1.</p>
<h2 id="setting-up-your-developer-workflow">Setting up your developer workflow</h2>
<p>First, let’s get a developer flow going so that the build process gets out of the way and we can focus on coding. Do the following:</p>
<ol>
<li>Install <a href="https://github.com/technomancy/leiningen" target="_blank">Leiningen</a>
<ul>
<li>Leiningen is a tool for automating Clojure project tasks.</li>
</ul>
</li>
<li>Go to the directory you wish to create your project in and type the following:
<ul>
<li>
<div class="highlight"><pre><code class="language-bash" data-lang="bash">lein new reagent myproject</code></pre></div>
</li>
</ul>
</li>
<li>cd into your new project and execute the following:
<ul>
<li>
<div class="highlight"><pre><code class="language-bash" data-lang="bash">lein ring server</code></pre></div>
</li>
<li>You should see Leiningen try and download a whole host of dependencies. Not to worry!</li>
<li>At the end, you should see a server running on localhost:3000</li>
</ul>
</li>
<li>Open a new terminal and execute the following from the base of your project:
<ul>
<li>
<div class="highlight"><pre><code class="language-bash" data-lang="bash">lein figwheel</code></pre></div>
</li>
</ul>
</li>
</ol>
<h2 id="what-was-all-that">What was all that?</h2>
<p>Here’s what each of those pieces were:</p>
<h3 id="a-hrefhttpsgithubcomtechnomancyleiningen-targetblankleiningena"><a href="https://github.com/technomancy/leiningen" target="_blank">Leiningen</a></h3>
<p>This is an absolute necessity for clojure development. It helps automate tasks and even comes with a repl!</p>
<h3 id="a-hrefhttpsgithubcomweavejesterlein-ring-targetblankringa"><a href="https://github.com/weavejester/lein-ring" target="_blank">Ring</a></h3>
<p>Ring is a simple abstraction for HTTP in Clojure. It allows you to create a webserver, define middleware etc.</p>
<h3 id="a-hrefhttpsgithubcombhaumanlein-figwheel-targetblankfigwheela"><a href="https://github.com/bhauman/lein-figwheel" target="_blank">Figwheel</a></h3>
<p>Figwheel autoreloads and compiles your clojurescript code so that you can live code and see your changes update in the browser. It also comes with a repl for your clojurescript so you can evaluate your code there. This will come in handy.</p>
<h3 id="a-hrefhttpsgithubcomreagent-projectreagent-targetblankreagenta"><a href="https://github.com/reagent-project/reagent" target="_blank">Reagent</a></h3>
<p>Reagent wraps the React.js library and provides a neat Clojurescript interface to it. This is my first time using it and it’s been very simple to pick up and use.</p>
<h2 id="understanding-the-basic-setup">Understanding the basic setup</h2>
<p>Let’s get started then. We’re going to first look at some of the scaffolding code and understand at a high level what’s going on. The code is in this <a href="https://github.com/dhruvp/mailchimp-form-cljs" target="_blank">repo</a> for following along.</p>
<p>Open up the core.cljs file in <code>src/cljs/<your-project>/core.cljs</code> in emacs or your favorite editor.</p>
<p>You should see a few function definitions under the heading “Views”. This is the first thing we’re going to edit. Each of these functions return separate DOM elements. If you check out the code under the Routes heading, you should see the following:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="nf">secretary/defroute</span> <span class="s">"/"</span> <span class="p">[]</span>
<span class="p">(</span><span class="nf">session/put!</span> <span class="ss">:current-page</span> <span class="o">#</span><span class="ss">'home-page</span><span class="p">))</span></code></pre></div>
<p>What’s happening there is <a href="https://github.com/gf3/secretary" target="_blank">Secretary</a>, another Clojurescript library we are using for routing, is matching the route “/” to the home-page function we defined in the views section. The function is simply setting a session variable, :current-page, to be home-page upon the match.</p>
<p>Then, at the bottom of the page, we see are telling reagent to render what’s defined by current-page, and bind it to whatever is at document.getElementById(“app”). That’s defined here:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="c1">;; Initialize app</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">init!</span> <span class="p">[]</span>
<span class="p">(</span><span class="nf">hook-browser-navigation!</span><span class="p">)</span>
<span class="p">(</span><span class="nf">reagent/render-component</span> <span class="p">[</span><span class="nv">current-page</span><span class="p">]</span> <span class="p">(</span><span class="nf">.getElementById</span> <span class="nv">js/document</span> <span class="s">"app"</span><span class="p">)))</span></code></pre></div>
<p>Ok cool. So we are just going to play around with the home page to get what we need. Let’s take a closer look at how the home-page view is being defined quickly.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">home-page</span> <span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to my-project"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">[</span><span class="ss">:a</span> <span class="p">{</span><span class="ss">:href</span> <span class="s">"#/about"</span><span class="p">}</span> <span class="s">"go to about page"</span><span class="p">]]])</span></code></pre></div>
<p>home-page is just a function that returns DOM elements (theme alert - we are going to make many such functions!). The syntax for defining HTML is similar to <a href="https://github.com/weavejester/hiccup">hiccup</a> in that HTML is represented by clojure vectors. The first element of the vector is the tag of the element (in this case :div as in [:div …]). We can then place other vectors(that represent elements) inside the original vector to represent element nesting (in the example above, the Welcome to my Project h2 is nested inside the div). So to show an example, I’ve pasted a vector representation of a DOM and its corresponding HTML element below it.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">[</span><span class="ss">:div</span> <span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to my-project"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">[</span><span class="ss">:a</span> <span class="p">{</span><span class="ss">:href</span> <span class="s">"#/about"</span><span class="p">}</span> <span class="s">"go to about page"</span><span class="p">]]]</span></code></pre></div>
<p>And the HTML:</p>
<div class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt"><div></span>
<span class="nt"><h2></span>Welcome to my-project<span class="nt"></h2></span>
<span class="nt"><div></span>
<span class="nt"><a</span> <span class="na">href=</span><span class="s">"#/about"</span> <span class="na">go</span> <span class="na">to</span> <span class="na">about</span> <span class="na">page</span><span class="nt">></a></span>
<span class="nt"></div></span>
<span class="nt"></div></span></code></pre></div>
<p>This is cool because we can now pass along representations of DOM elements as first class data structures! I can pass them to functions, return them, map over them, compose them … Basically the possibilities are endless.</p>
<h2 id="starting-to-build-the-form">Starting to build the form</h2>
<p>Ok now let’s remove the gunk and focus just on the home page. We don’t really need the about page. Edit the home-page code to be</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">home-page</span> <span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"signup-wrapper"</span><span class="p">}</span>
<span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to TestChimp"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:form</span><span class="p">]])</span></code></pre></div>
<p>We now have an empty form! Look at that.</p>
<p>Let’s now create a function for rendering an email-input component. We define a simple email-input function that for now will return an empty-div. We’ll fix it shortly.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">email-input</span>
<span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span><span class="p">])</span></code></pre></div>
<h2 id="data-binding">Data Binding</h2>
<p>Ok back to the form. We’re going to need a variable to track the state of the email-address field and auto updates as users type in their email address. In Angular and similar frameworks, we would achieve this by using some form of two way data binding. In reagent, we do something very similar using an Atom. Atoms are one of the few mutable data structure in Clojure. Reagent extends a Clojure Atom by ensuring that whenever an Atom is mutated, any component that uses it is rerendered (so we don’t have to worry about updating our views). So let’s use that!</p>
<p>Let’s just create a new atom for email-address to start.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">home-page</span> <span class="p">[]</span>
<span class="c1">;; We define the email-address as an atom right here</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">email-address</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"signup-wrapper"</span><span class="p">}</span>
<span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to TestChimp"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:form</span><span class="p">]])))</span></code></pre></div>
<p>Notice how we changed home-page now to return a function. Reagent requires that if we do any setup via lets etc., we return a function that in turn returns the elements we want. This just sets up the lexical scoping up front.</p>
<h2 id="the-building-blocks-of-our-ui---functions">The Building Blocks of our UI - Functions</h2>
<p>Let’s now create the HTML for our actual email input form. We’re going to do this by creating a function that is just responsible for the UI of the email input. What’s awesome about this is that functions are now the building blocks of our UI. That’s exactly how LISP was intended to be used!</p>
<p>Let’s develop a generic function for input-elements, and have the email-input just be a specific application of that function.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">input-element</span>
<span class="s">"An input element which updates its value on change"</span>
<span class="p">[</span><span class="nv">id</span> <span class="nb">name </span><span class="nv">type</span> <span class="nv">value</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:input</span> <span class="p">{</span><span class="ss">:id</span> <span class="nv">id</span>
<span class="ss">:name</span> <span class="nv">name</span>
<span class="ss">:class</span> <span class="s">"form-control"</span>
<span class="ss">:type</span> <span class="nv">type</span>
<span class="ss">:required</span> <span class="s">""</span>
<span class="ss">:value</span> <span class="o">@</span><span class="nv">value</span>
<span class="ss">:on-change</span> <span class="o">#</span><span class="p">(</span><span class="nf">reset!</span> <span class="nv">value</span> <span class="p">(</span><span class="nb">-> </span><span class="nv">%</span> <span class="nv">.-target</span> <span class="nv">.-value</span><span class="p">))}])</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">email-input</span>
<span class="p">[</span><span class="nv">email-address-atom</span><span class="p">]</span>
<span class="p">(</span><span class="nf">input-element</span> <span class="s">"email"</span> <span class="s">"email"</span> <span class="s">"email"</span> <span class="nv">email-address-atom</span><span class="p">))</span></code></pre></div>
<p>Let’s now use this UI component and put it into our original form.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">home-page</span> <span class="p">[]</span>
<span class="c1">;; We define the email-address as an atom right here</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">email-address</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"signup-wrapper"</span><span class="p">}</span>
<span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to TestChimp"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:form</span>
<span class="c1">;; We use the email-input component here</span>
<span class="p">[</span><span class="nv">email-input</span> <span class="nv">email-address</span><span class="p">]]])))</span></code></pre></div>
<p>Notice how we compose the email-input component into a form div by just placing a vector [email-input email-address] inside the vector describing the form. Super simple! The first element of the vector is just the name of the function defining the component and the next elements are the arguments to that function. You can see how easy it is to build and compose components to make simple, modular ui elements.</p>
<h2 id="implementing-two-way-data-binding">Implementing Two Way Data Binding</h2>
<p>Now, we need to implement a basic form of two way data binding so that when the user types something in we are able to track it. We can implement this with an :on-change attribute on our element. We pass the following function into :on-change attribute of the input element.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="o">#</span><span class="p">(</span><span class="nf">reset!</span> <span class="nv">value</span> <span class="p">(</span><span class="nb">-> </span><span class="nv">%</span> <span class="nv">.-target</span> <span class="nv">.-value</span><span class="p">))</span></code></pre></div>
<p>Here, we are resetting the value of atom to be the output of (-> % .-target .-value). The hell is that? That is a <a href="http://clojuredocs.org/clojure.core/-%3E">macro</a> that expands to (.-value (.-target %)) or just event.target.value in JavaScript. Note that .-value and .-target are how we call JavaScript properties in Clojurescript (yes! Clojurescript let’s you talk to JavaScript objects!). The cool thing here is we just have to change the atom here and ANY other component that uses this atom rerenders automatically! This is some sweet stuff already.</p>
<p>And what’s with the “@value” we passed to the value field of input? Well the @ is just telling the function to apply the value of the atom (So that we don’t pass in an atom which HTML has no idea how to display!).</p>
<p>So now if you check out localhost:3000, you should see a simple page with an input for your email-address! Add in the following to display the email address.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">home-page</span> <span class="p">[]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">email-address</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"signup-wrapper"</span><span class="p">}</span>
<span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to TestChimp"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:form</span>
<span class="p">[</span><span class="nv">email-input</span> <span class="nv">email-address</span><span class="p">]]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="s">"EMAIL ADDRESS IS "</span> <span class="o">@</span><span class="nv">email-address</span><span class="p">]])))</span></code></pre></div>
<h2 id="sharing-state-between-components">Sharing state between components</h2>
<p>Ok, now I want to display a little message that says “What is your email address?” when you click on the email box. Let’s create a component for that.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="c1">;;generic function</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">prompt-message</span>
<span class="s">"A prompt that will animate to help the user with a given input"</span>
<span class="p">[</span><span class="nv">message</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"my-messages"</span><span class="p">}</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"prompt message-animation"</span><span class="p">}</span> <span class="p">[</span><span class="ss">:p</span> <span class="nv">message</span><span class="p">]]])</span>
<span class="c1">;;specific function</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">email-prompt</span>
<span class="p">[]</span>
<span class="p">(</span><span class="nf">prompt-message</span> <span class="s">"What's your email address?"</span><span class="p">))</span></code></pre></div>
<p>Depending on when that input is in focus, we need to hide or show the component we defined above. The below function is going to do just that. It will take in information about the input, and a prompt element, and return a representation of a DOM element that has an input field, and a prompt field that appears above it if the input is in focus.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">input-and-prompt</span>
<span class="s">"Creates an input box and a prompt box that appears above the input when the input comes into focus."</span>
<span class="p">[</span><span class="nv">label-value</span> <span class="nv">input-name</span> <span class="nv">input-type</span> <span class="nv">input-element-arg</span> <span class="nv">prompt-element</span><span class="p">]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">input-focus</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">false</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span>
<span class="p">[</span><span class="ss">:label</span> <span class="nv">label-value</span><span class="p">]</span>
<span class="p">(</span><span class="k">if </span><span class="o">@</span><span class="nv">input-focus</span> <span class="nv">prompt-element</span> <span class="p">[</span><span class="ss">:div</span><span class="p">])</span>
<span class="p">[</span><span class="nv">input-element</span> <span class="nv">input-name</span> <span class="nv">input-name</span> <span class="nv">input-type</span> <span class="nv">input-element-arg</span> <span class="nv">input-focus</span><span class="p">]])))</span></code></pre></div>
<p>Let’s dive in a little deeper. The below snippet is what hides and shows the prompt element:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="k">if </span><span class="o">@</span><span class="nv">input-focus</span> <span class="nv">prompt-element</span> <span class="p">[</span><span class="ss">:div</span><span class="p">])</span></code></pre></div>
<p>If the input-focus atom is set to true, we return the prompt-element, otherwise, we return an empty div. COOL! We need to pass this input-focus atom to our input-element and have it update this atom on focus or blur. Let’s share this state variable by making input-element use it.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">input-element</span>
<span class="s">"An input element which updates its value and on focus parameters on change, blur, and focus"</span>
<span class="p">[</span><span class="nv">id</span> <span class="nb">name </span><span class="nv">type</span> <span class="nv">value</span> <span class="nv">in-focus</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:input</span> <span class="p">{</span><span class="ss">:id</span> <span class="nv">id</span>
<span class="ss">:name</span> <span class="nv">name</span>
<span class="ss">:class</span> <span class="s">"form-control"</span>
<span class="ss">:type</span> <span class="nv">type</span>
<span class="ss">:required</span> <span class="s">""</span>
<span class="ss">:value</span> <span class="o">@</span><span class="nv">value</span>
<span class="ss">:on-change</span> <span class="o">#</span><span class="p">(</span><span class="nf">reset!</span> <span class="nv">value</span> <span class="p">(</span><span class="nb">-> </span><span class="nv">%</span> <span class="nv">.-target</span> <span class="nv">.-value</span><span class="p">))</span>
<span class="c1">;; Below we change the state of in-focus</span>
<span class="ss">:on-focus</span> <span class="o">#</span><span class="p">(</span><span class="nf">swap!</span> <span class="nv">in-focus</span> <span class="nv">not</span><span class="p">)</span>
<span class="ss">:on-blur</span> <span class="o">#</span><span class="p">(</span><span class="nf">swap!</span> <span class="nv">in-focus</span> <span class="nv">not</span><span class="p">)}])</span></code></pre></div>
<p>So now we have our input element swap the in-focus atom to be its converse when an on-focus or on-blur event happens. Dope.</p>
<h2 id="putting-it-all-together">Putting it all together</h2>
<p>Let’s now use all these functions we’ve built.</p>
<p>Rename the email-input method to be email-form, and change it to be what you see below so that it uses input-and-prompt.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">email-form</span>
<span class="p">[</span><span class="nv">email-address-atom</span><span class="p">]</span>
<span class="p">(</span><span class="nf">input-and-prompt</span> <span class="s">"email"</span>
<span class="s">"email"</span>
<span class="s">"email"</span>
<span class="nv">email-address-atom</span>
<span class="p">[</span><span class="nv">prompt-message</span> <span class="s">"What's your email?"</span><span class="p">]))</span></code></pre></div>
<p>Right now, your home-page function should be:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">home-page</span> <span class="p">[]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">email-address</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"signup-wrapper"</span><span class="p">}</span>
<span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to TestChimp"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:form</span>
<span class="p">[</span><span class="nv">email-form</span> <span class="nv">email-address</span><span class="p">]]])))</span></code></pre></div>
<p>Try it out! As you click in and click out, you should see the prompt message appear and disappear.
Finally, we want a little validation. If the field is required, we want our form to throw out a little message if it’s not filled in. This is a simple addition. Let’s change our input-and-prompt method to take in a required? attribute and display a message saying “Field is required!” when the field is empty.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">input-and-prompt</span>
<span class="s">"Creates an input box and a prompt box that appears above the input when the input comes into focus. Also throws in a little required message"</span>
<span class="p">[</span><span class="nv">label-value</span> <span class="nv">input-name</span> <span class="nv">input-type</span> <span class="nv">input-element-arg</span> <span class="nv">prompt-element</span> <span class="nv">required?</span><span class="p">]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">input-focus</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">false</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span>
<span class="p">[</span><span class="ss">:label</span> <span class="nv">label-value</span><span class="p">]</span>
<span class="p">(</span><span class="k">if </span><span class="o">@</span><span class="nv">input-focus</span> <span class="nv">prompt-element</span> <span class="p">[</span><span class="ss">:div</span><span class="p">])</span>
<span class="p">[</span><span class="nv">input-element</span> <span class="nv">input-name</span> <span class="nv">input-name</span> <span class="nv">input-type</span> <span class="nv">input-element-arg</span> <span class="nv">input-focus</span><span class="p">]</span>
<span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">and </span><span class="nv">required?</span> <span class="p">(</span><span class="nb">= </span><span class="s">""</span> <span class="o">@</span><span class="nv">input-element-arg</span><span class="p">))</span>
<span class="p">[</span><span class="ss">:div</span> <span class="s">"Field is required!"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:div</span><span class="p">])])))</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">email-form</span>
<span class="p">[</span><span class="nv">email-address-atom</span><span class="p">]</span>
<span class="p">(</span><span class="nf">input-and-prompt</span> <span class="s">"email"</span>
<span class="s">"email"</span>
<span class="s">"email"</span>
<span class="nv">email-address-atom</span>
<span class="p">[</span><span class="nv">prompt-message</span> <span class="s">"What's your email?"</span><span class="p">]</span>
<span class="nv">true</span><span class="p">))</span></code></pre></div>
<h2 id="the-power-of-generics---create-a-name-form-and-a-password-form">The power of generics - create a name form and a password form</h2>
<p>Hopefully this works as expected. Now you must be thinking, why did we define so many generic components instead of directly creating the components themselves? Couldn’t we have tailored input-and-prompt to just worry about email addresses? Well we could have. But because we made it generic, we now a password, and name form for free! Just add in the following:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">name-form</span> <span class="p">[</span><span class="nv">name-atom</span><span class="p">]</span>
<span class="p">(</span><span class="nf">input-and-prompt</span> <span class="s">"name"</span>
<span class="s">"name"</span>
<span class="s">"text"</span>
<span class="nv">name-atom</span>
<span class="p">(</span><span class="nf">prompt-message</span> <span class="s">"What's your name?"</span><span class="p">)</span>
<span class="nv">true</span><span class="p">))</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">password-form</span> <span class="p">[</span><span class="nv">password-atom</span><span class="p">]</span>
<span class="p">(</span><span class="nf">input-and-prompt</span> <span class="s">"password"</span>
<span class="s">"password"</span>
<span class="s">"password"</span>
<span class="nv">password-atom</span>
<span class="p">(</span><span class="nf">prompt-message</span> <span class="s">"What's your password?"</span><span class="p">)</span>
<span class="nv">true</span><span class="p">))</span></code></pre></div>
<p>This to me is a big deal. We can now create UI elements using reusable, testable, utility functions. I don’t think that’s particularly easy in most setups. Let’s add in these additional forms by changing the home-page method to be the following:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">home-page</span> <span class="p">[]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">email-address</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)</span>
<span class="nb">name </span><span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)</span>
<span class="nv">password</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"signup-wrapper"</span><span class="p">}</span>
<span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to TestChimp"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:form</span>
<span class="p">[</span><span class="nv">email-form</span> <span class="nv">email-address</span><span class="p">]</span>
<span class="p">[</span><span class="nv">name-form</span> <span class="nv">name</span><span class="p">]</span>
<span class="p">[</span><span class="nv">password-form</span> <span class="nv">password</span><span class="p">]]])))</span></code></pre></div>
<h2 id="bonus---applying-additional-validation-on-the-password">Bonus - Applying Additional validation on the password</h2>
<p>Ok! Onto the last challenge. We are going to validate the password field a little more heavily. We want the password to be at least 8 characters long, have at least 1 special character, and have at least one digit. Let’s start by defining some regexps to check for this.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">check-nil-then-predicate</span>
<span class="s">"Check if the value is nil, then apply the predicate"</span>
<span class="p">[</span><span class="nv">value</span> <span class="nv">predicate</span><span class="p">]</span>
<span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">nil? </span><span class="nv">value</span><span class="p">)</span>
<span class="nv">false</span>
<span class="p">(</span><span class="nf">predicate</span> <span class="nv">value</span><span class="p">)))</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">eight-or-more-characters?</span>
<span class="p">[</span><span class="nv">word</span><span class="p">]</span>
<span class="p">(</span><span class="nf">check-nil-then-predicate</span> <span class="nv">word</span> <span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">arg</span><span class="p">]</span> <span class="p">(</span><span class="nb">> </span><span class="p">(</span><span class="nb">count </span><span class="nv">arg</span><span class="p">)</span> <span class="mi">7</span><span class="p">))))</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">has-special-character?</span>
<span class="p">[</span><span class="nv">word</span><span class="p">]</span>
<span class="p">(</span><span class="nf">check-nil-then-predicate</span> <span class="nv">word</span> <span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">arg</span><span class="p">]</span> <span class="p">(</span><span class="nb">boolean </span><span class="p">(</span><span class="nb">first </span><span class="p">(</span><span class="nb">re-seq </span><span class="o">#</span><span class="s">"\W+"</span> <span class="nv">arg</span><span class="p">))))))</span>
<span class="p">(</span><span class="kd">defn </span><span class="nv">has-number?</span>
<span class="p">[</span><span class="nv">word</span><span class="p">]</span>
<span class="p">(</span><span class="nf">check-nil-then-predicate</span> <span class="nv">word</span> <span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">arg</span><span class="p">]</span> <span class="p">(</span><span class="nb">boolean </span><span class="p">(</span><span class="nb">re-seq </span><span class="o">#</span><span class="s">"\d+"</span> <span class="nv">arg</span><span class="p">)))))</span></code></pre></div>
<p>Ok great. We now move on to defining the component that will show what requirements we haven’t satisfied yet in our password. It’s going to be a list where requirements disappear as we meet them. The function will take in a data structure like the one pasted below it.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">password-requirements</span>
<span class="s">"A list to describe which password requirements have been met so far"</span>
<span class="p">[</span><span class="nv">password</span> <span class="nv">requirements</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:div</span>
<span class="p">[</span><span class="ss">:ul</span> <span class="p">(</span><span class="nf">->></span> <span class="nv">requirements</span>
<span class="p">(</span><span class="nb">filter </span><span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">req</span><span class="p">]</span> <span class="p">(</span><span class="nb">not </span><span class="p">((</span><span class="ss">:check-fn</span> <span class="nv">req</span><span class="p">)</span> <span class="o">@</span><span class="nv">password</span><span class="p">))))</span>
<span class="p">(</span><span class="nf">doall</span><span class="p">)</span>
<span class="p">(</span><span class="nb">map </span><span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">req</span><span class="p">]</span> <span class="o">^</span><span class="p">{</span><span class="ss">:key</span> <span class="nv">req</span><span class="p">}</span> <span class="p">[</span><span class="ss">:li</span> <span class="p">(</span><span class="ss">:message</span> <span class="nv">req</span><span class="p">)])))]])</span></code></pre></div>
<p>Let’s break down the function above. It’s taking in a password (atom) and a set of requirements. You can see what the requirements data structure looks like below.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">[{</span><span class="ss">:message</span> <span class="s">"8 or more characters"</span> <span class="ss">:check-fn</span> <span class="nv">eight-or-more-characters?</span><span class="p">}</span>
<span class="p">{</span><span class="ss">:message</span> <span class="s">"At least one special character"</span> <span class="ss">:check-fn</span> <span class="nv">has-special-character?</span><span class="p">}</span>
<span class="p">{</span><span class="ss">:message</span> <span class="s">"At least one number"</span> <span class="ss">:check-fn</span> <span class="nv">has-number?</span><span class="p">}]</span></code></pre></div>
<p>password-requirements then returns a div with a ul list inside it.</p>
<p>For each requirement, we filter out the requirements that aren’t passed, and then map those requirements to create :li elements whose contents are just the messages of the requirements. This is cool. Again, this shows how we are doing things most templating languages can’t really do.</p>
<p>Let’s now change our password-form to use these requirements.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">password-form</span>
<span class="p">[</span><span class="nv">password</span><span class="p">]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">password-type-atom</span> <span class="p">(</span><span class="nf">atom</span> <span class="s">"password"</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span>
<span class="p">[(</span><span class="nf">input-and-prompt</span> <span class="s">"password"</span>
<span class="s">"password"</span>
<span class="o">@</span><span class="nv">password-type-atom</span>
<span class="nv">password</span>
<span class="p">(</span><span class="nf">prompt-message</span> <span class="s">"What's your password"</span><span class="p">)</span>
<span class="nv">true</span><span class="p">)]</span>
<span class="p">[</span><span class="nv">password-requirements</span> <span class="nv">password</span> <span class="p">[{</span><span class="ss">:message</span> <span class="s">"8 or more characters"</span> <span class="ss">:check-fn</span> <span class="nv">eight-or-more-characters?</span><span class="p">}</span>
<span class="p">{</span><span class="ss">:message</span> <span class="s">"At least one special character"</span> <span class="ss">:check-fn</span> <span class="nv">has-special-character?</span><span class="p">}</span>
<span class="p">{</span><span class="ss">:message</span> <span class="s">"At least one number"</span> <span class="ss">:check-fn</span> <span class="nv">has-number?</span><span class="p">}]]])))</span></code></pre></div>
<p>Finally, notice that password-form, input-form etc. aren’t in a form-group class. Let’s fix that. We create the following function:</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">wrap-as-element-in-form</span>
<span class="p">[</span><span class="nv">element</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class=</span><span class="s">"row form-group"</span><span class="p">}</span>
<span class="nv">element</span><span class="p">])</span></code></pre></div>
<p>And then use it to wrap all our forms in form-group elements.</p>
<div class="highlight"><pre><code class="language-clojure" data-lang="clojure"><span class="p">(</span><span class="kd">defn </span><span class="nv">home-page</span> <span class="p">[]</span>
<span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">email-address</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)</span>
<span class="nb">name </span><span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)</span>
<span class="nv">password</span> <span class="p">(</span><span class="nf">atom</span> <span class="nv">nil</span><span class="p">)]</span>
<span class="p">(</span><span class="k">fn </span><span class="p">[]</span>
<span class="p">[</span><span class="ss">:div</span> <span class="p">{</span><span class="ss">:class</span> <span class="s">"signup-wrapper"</span><span class="p">}</span>
<span class="p">[</span><span class="ss">:h2</span> <span class="s">"Welcome to TestChimp"</span><span class="p">]</span>
<span class="p">[</span><span class="ss">:form</span>
<span class="p">(</span><span class="nf">wrap-as-element-in-form</span> <span class="p">[</span><span class="nv">email-form</span> <span class="nv">email-address</span><span class="p">])</span>
<span class="p">(</span><span class="nf">wrap-as-element-in-form</span> <span class="p">[</span><span class="nv">name-form</span> <span class="nv">name</span><span class="p">])</span>
<span class="p">(</span><span class="nf">wrap-as-element-in-form</span> <span class="p">[</span><span class="nv">password-form</span> <span class="nv">password</span><span class="p">])]])))</span></code></pre></div>
<p>That’s it for now! Your final code should match the file <a href="https://github.com/dhruvp/mailchimp-form-cljs/blob/master/src/cljs/mailchimp_form/core.cljs">here</a>.</p>
<h2 id="so-what-have-we-learned">So what have we learned?</h2>
<p>We went through something really cool in this post (I think at least!). We applied the Clojure principle of using simple, composable functions as a way of building UIs! And why should we not? Can’t frontend software development also use the same principles of modularity, simplicity, and composition? Indeed, I think with Clojurescript and Reagent, it can.</p>
<p>More specifically, here are my main takeaways:</p>
<ol>
<li>
<p>It’s really nice to be able to treat UI elements as first class data structures that you can compose and apply logic on. I think it does lead to more modular pieces.</p>
</li>
<li>
<p>It’s also very nice that you can use clojure as your templating language! No need for feeling hamstrung by a lack of functionality there and we don’t have to learn any new languages.</p>
</li>
<li>
<p>Reagent is also just a really simple to use library. Atoms abstract away any worrying about rerendering elements and the syntax of using reagent is dead simple.</p>
</li>
<li>
<p>It is hard for me to debug clojurescript code. I still don’t know how to do this efficiently. Many times I would see errors and have no idea why they were ocurring. In JavaScript, I would just breakpoint my code to catch the error. Here I couldn’t do that. Also, at times I would have to run lein clean and then rerun a cljscript autobuild and this took like 30 seconds each time. You can imagine that this is not fun.</p>
</li>
</ol>