Browse files

Site updated at 2012-01-02 08:16:32 UTC

  • Loading branch information...
1 parent 5601418 commit fd478969238a4fcd1e8f4909d54ef082bd630d62 @norm2782 committed Jan 2, 2012
View
80 atom.xml
@@ -4,7 +4,7 @@
<title><![CDATA[Norm 2782]]></title>
<link href="http://norm2782.github.com/atom.xml" rel="self"/>
<link href="http://norm2782.github.com/"/>
- <updated>2012-01-01T23:42:22+01:00</updated>
+ <updated>2012-01-02T09:16:28+01:00</updated>
<id>http://norm2782.github.com/</id>
<author>
<name><![CDATA[Jurriën Stutterheim]]></name>
@@ -91,7 +91,8 @@ first some imports:</p>
<p>Since we are using Snap 0.7 at the moment of writing, we start by defining
out snaplet state type, generating some lenses using Template Haskell and
defining a handy type synonym for our handlers. We also want to use Heist,
-so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.</p>
+so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.
+And, since this is a snaplet, we need to define our snaplet initialiser.</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -104,6 +105,14 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+<span class='line-number'>15</span>
+<span class='line-number'>16</span>
+<span class='line-number'>17</span>
+<span class='line-number'>18</span>
+<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">App</span>
</span><span class='line'> <span class="ow">=</span> <span class="kt">App</span>
</span><span class='line'> <span class="p">{</span> <span class="n">_heist</span> <span class="ow">::</span> <span class="kt">Snaplet</span> <span class="p">(</span><span class="kt">Heist</span> <span class="kt">App</span><span class="p">)</span>
@@ -115,6 +124,14 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
</span><span class='line'>
</span><span class='line'><span class="kr">instance</span> <span class="kt">HasHeist</span> <span class="kt">App</span> <span class="kr">where</span>
</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span>
+</span><span class='line'>
+</span><span class='line'><span class="nf">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
+</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
+</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
+</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span>
+</span><span class='line'> <span class="n">h</span> <span class="ow">&lt;-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
+</span><span class='line'> <span class="n">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
+</span><span class='line'> <span class="n">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
</span></code></pre></td></tr></table></div></figure>
@@ -190,22 +207,31 @@ comes from the email-validate library.</p>
</span></code></pre></td></tr></table></div></figure>
-<p>So far we have not seen anything new yet.</p>
+<p>Up to this point we have not seen anything new yet, so lets start with something a bit
+more interesting. For most of my Snap apps I use the following function to render a form:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
-</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">frm</span> <span class="ow">=</span>
+</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
+</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">mth</span> <span class="n">frm</span> <span class="ow">=</span>
</span><span class='line'> <span class="kr">let</span> <span class="p">(</span><span class="n">formHtml&#39;</span><span class="p">,</span> <span class="n">enctype</span><span class="p">)</span> <span class="ow">=</span> <span class="n">renderFormHtml</span> <span class="n">frm</span>
-</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="s">&quot;post&quot;</span>
+</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="n">mth</span>
</span><span class='line'> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">action</span> <span class="n">act</span> <span class="o">$</span> <span class="n">formHtml&#39;</span> <span class="o">&gt;&gt;</span> <span class="n">return</span> <span class="nb">()</span>
</span></code></pre></td></tr></table></div></figure>
+<p>It takes an <code>AttributeValue</code> containing the target of the form, an <code>AttributeValue</code> containing
+the HTTP request method and a form as produced by the <code>eitherSnapForm</code> function we will see
+below, resulting in a rendered form of type <code>Html</code>.</p>
+<p>Now for the request handler, which is where most of the action will take place. We want to
+make our lives easy, so we call in the help of the digestive-functors-snap library, which
+provides the <code>eitherSnapForm</code> function. This function can be applied to a digestive-functors
+form and a form name, after which it will use the Snap API to parse the request. Before
+continueing, lets have a look at some code:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -220,13 +246,29 @@ comes from the email-validate library.</p>
</span><span class='line'> <span class="n">res</span> <span class="ow">&lt;-</span> <span class="n">eitherSnapForm</span> <span class="n">loginForm</span> <span class="s">&quot;login-form&quot;</span>
</span><span class='line'> <span class="kr">case</span> <span class="n">res</span> <span class="kr">of</span>
</span><span class='line'> <span class="kt">Left</span> <span class="n">form</span> <span class="ow">-&gt;</span> <span class="kr">do</span>
-</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="n">form</span>
-</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;form&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;form&quot;</span>
+</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="s">&quot;post&quot;</span> <span class="n">form</span>
+</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;formElm&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;formTpl&quot;</span>
</span><span class='line'> <span class="kt">Right</span> <span class="p">(</span><span class="kt">LoginData</span> <span class="n">e</span> <span class="n">p</span> <span class="n">r</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="n">writeBS</span> <span class="s">&quot;Success!&quot;</span>
</span></code></pre></td></tr></table></div></figure>
-<p>Finally we define our initialiser, which sets up Heist and our routes.</p>
+<p>The result of <code>eitherSnapForm</code> is an <code>Either</code> value. When the form has not been submitted yet,
+or if a submitted form failed validation, the result will be a <code>Left</code> constructor containing
+a form of type <code>FormHtml (HtmlM a)</code>. When a form has been submitted and has succesfully passed
+validation, we will get a <code>Right</code> value containing the constructor applied in our form (in this
+case the <code>LoginData</code> constructor).</p>
+
+<p>Rendering the form is done when we get a <code>Left</code> result. As it turns out, it is almost trivially
+easy to render the form in Heist. To bind the form as a Heist splice, we first need to render it
+to an <code>Html</code> value using our <code>showForm</code> function. Since Heist cannot work with values of type
+<code>Html</code>, we have to convert the <code>Html</code> to something Heist does understand. Luckily, the xmlhtml
+library provides us with a function that does just that: <code>renderHtmlNodes :: Html -&gt; [Node]</code>.
+Heist loves a list of <code>Node</code>s, so all we need to do is <code>return</code> it to the <code>Splice</code> context so
+we can bind it as a splice to our template.</p>
+
+<p>The final piece of the puzzle is the template in which the form needs to be rendered. As you can
+see, rendering the form&#8211;including potential validation error messages&#8211;is done by adding nothing
+but a single element to the template.</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -235,17 +277,21 @@ comes from the email-validate library.</p>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
-</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
-</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
-</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span>
-</span><span class='line'> <span class="n">h</span> <span class="ow">&lt;-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
-</span><span class='line'> <span class="n">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
-</span><span class='line'> <span class="n">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
+<span class='line-number'>8</span>
+</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt">&lt;html&gt;</span>
+</span><span class='line'> <span class="nt">&lt;head&gt;</span>
+</span><span class='line'> <span class="nt">&lt;title&gt;</span>Heist and digestive-functors playing nice<span class="nt">&lt;/title&gt;</span>
+</span><span class='line'> <span class="nt">&lt;/head&gt;</span>
+</span><span class='line'> <span class="nt">&lt;body&gt;</span>
+</span><span class='line'> <span class="nt">&lt;form</span> <span class="nt">/&gt;</span>
+</span><span class='line'> <span class="nt">&lt;/body&gt;</span>
+</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure>
-
+<p>With this, we have seen how to use digestive-functors and Heist together in a win-win scenario.
+On the one hand you mostly maintain your separation of concerns by using Heist for most of your
+HTML output, while on the other hand you can enjoy the great digestive-functors library as-is.</p>
]]></content>
</entry>
View
78 blog/2012/01/01/using-digestive-functors-with-heist/index.html
@@ -165,7 +165,8 @@ <h1 class="entry-title">Using Digestive-functors With Heist</h1>
<p>Since we are using Snap 0.7 at the moment of writing, we start by defining
out snaplet state type, generating some lenses using Template Haskell and
defining a handy type synonym for our handlers. We also want to use Heist,
-so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.</p>
+so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.
+And, since this is a snaplet, we need to define our snaplet initialiser.</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -178,6 +179,14 @@ <h1 class="entry-title">Using Digestive-functors With Heist</h1>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+<span class='line-number'>15</span>
+<span class='line-number'>16</span>
+<span class='line-number'>17</span>
+<span class='line-number'>18</span>
+<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">App</span>
</span><span class='line'> <span class="ow">=</span> <span class="kt">App</span>
</span><span class='line'> <span class="p">{</span> <span class="n">_heist</span> <span class="ow">::</span> <span class="kt">Snaplet</span> <span class="p">(</span><span class="kt">Heist</span> <span class="kt">App</span><span class="p">)</span>
@@ -189,6 +198,14 @@ <h1 class="entry-title">Using Digestive-functors With Heist</h1>
</span><span class='line'>
</span><span class='line'><span class="kr">instance</span> <span class="kt">HasHeist</span> <span class="kt">App</span> <span class="kr">where</span>
</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span>
+</span><span class='line'>
+</span><span class='line'><span class="nf">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
+</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
+</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
+</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span>
+</span><span class='line'> <span class="n">h</span> <span class="ow">&lt;-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
+</span><span class='line'> <span class="n">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
+</span><span class='line'> <span class="n">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
</span></code></pre></td></tr></table></div></figure>
@@ -264,22 +281,31 @@ <h1 class="entry-title">Using Digestive-functors With Heist</h1>
</span></code></pre></td></tr></table></div></figure>
-<p>So far we have not seen anything new yet.</p>
+<p>Up to this point we have not seen anything new yet, so lets start with something a bit
+more interesting. For most of my Snap apps I use the following function to render a form:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
-</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">frm</span> <span class="ow">=</span>
+</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
+</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">mth</span> <span class="n">frm</span> <span class="ow">=</span>
</span><span class='line'> <span class="kr">let</span> <span class="p">(</span><span class="n">formHtml&#39;</span><span class="p">,</span> <span class="n">enctype</span><span class="p">)</span> <span class="ow">=</span> <span class="n">renderFormHtml</span> <span class="n">frm</span>
-</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="s">&quot;post&quot;</span>
+</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="n">mth</span>
</span><span class='line'> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">action</span> <span class="n">act</span> <span class="o">$</span> <span class="n">formHtml&#39;</span> <span class="o">&gt;&gt;</span> <span class="n">return</span> <span class="nb">()</span>
</span></code></pre></td></tr></table></div></figure>
+<p>It takes an <code>AttributeValue</code> containing the target of the form, an <code>AttributeValue</code> containing
+the HTTP request method and a form as produced by the <code>eitherSnapForm</code> function we will see
+below, resulting in a rendered form of type <code>Html</code>.</p>
+<p>Now for the request handler, which is where most of the action will take place. We want to
+make our lives easy, so we call in the help of the digestive-functors-snap library, which
+provides the <code>eitherSnapForm</code> function. This function can be applied to a digestive-functors
+form and a form name, after which it will use the Snap API to parse the request. Before
+continueing, lets have a look at some code:</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -294,13 +320,29 @@ <h1 class="entry-title">Using Digestive-functors With Heist</h1>
</span><span class='line'> <span class="n">res</span> <span class="ow">&lt;-</span> <span class="n">eitherSnapForm</span> <span class="n">loginForm</span> <span class="s">&quot;login-form&quot;</span>
</span><span class='line'> <span class="kr">case</span> <span class="n">res</span> <span class="kr">of</span>
</span><span class='line'> <span class="kt">Left</span> <span class="n">form</span> <span class="ow">-&gt;</span> <span class="kr">do</span>
-</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="n">form</span>
-</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;form&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;form&quot;</span>
+</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="s">&quot;post&quot;</span> <span class="n">form</span>
+</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;formElm&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;formTpl&quot;</span>
</span><span class='line'> <span class="kt">Right</span> <span class="p">(</span><span class="kt">LoginData</span> <span class="n">e</span> <span class="n">p</span> <span class="n">r</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="n">writeBS</span> <span class="s">&quot;Success!&quot;</span>
</span></code></pre></td></tr></table></div></figure>
-<p>Finally we define our initialiser, which sets up Heist and our routes.</p>
+<p>The result of <code>eitherSnapForm</code> is an <code>Either</code> value. When the form has not been submitted yet,
+or if a submitted form failed validation, the result will be a <code>Left</code> constructor containing
+a form of type <code>FormHtml (HtmlM a)</code>. When a form has been submitted and has succesfully passed
+validation, we will get a <code>Right</code> value containing the constructor applied in our form (in this
+case the <code>LoginData</code> constructor).</p>
+
+<p>Rendering the form is done when we get a <code>Left</code> result. As it turns out, it is almost trivially
+easy to render the form in Heist. To bind the form as a Heist splice, we first need to render it
+to an <code>Html</code> value using our <code>showForm</code> function. Since Heist cannot work with values of type
+<code>Html</code>, we have to convert the <code>Html</code> to something Heist does understand. Luckily, the xmlhtml
+library provides us with a function that does just that: <code>renderHtmlNodes :: Html -&gt; [Node]</code>.
+Heist loves a list of <code>Node</code>s, so all we need to do is <code>return</code> it to the <code>Splice</code> context so
+we can bind it as a splice to our template.</p>
+
+<p>The final piece of the puzzle is the template in which the form needs to be rendered. As you can
+see, rendering the form&#8211;including potential validation error messages&#8211;is done by adding nothing
+but a single element to the template.</p>
<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -309,17 +351,21 @@ <h1 class="entry-title">Using Digestive-functors With Heist</h1>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
-</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
-</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
-</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span>
-</span><span class='line'> <span class="n">h</span> <span class="ow">&lt;-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
-</span><span class='line'> <span class="n">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
-</span><span class='line'> <span class="n">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
+<span class='line-number'>8</span>
+</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt">&lt;html&gt;</span>
+</span><span class='line'> <span class="nt">&lt;head&gt;</span>
+</span><span class='line'> <span class="nt">&lt;title&gt;</span>Heist and digestive-functors playing nice<span class="nt">&lt;/title&gt;</span>
+</span><span class='line'> <span class="nt">&lt;/head&gt;</span>
+</span><span class='line'> <span class="nt">&lt;body&gt;</span>
+</span><span class='line'> <span class="nt">&lt;form</span> <span class="nt">/&gt;</span>
+</span><span class='line'> <span class="nt">&lt;/body&gt;</span>
+</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure>
-
+<p>With this, we have seen how to use digestive-functors and Heist together in a win-win scenario.
+On the one hand you mostly maintain your separation of concerns by using Heist for most of your
+HTML output, while on the other hand you can enjoy the great digestive-functors library as-is.</p>
</div>
View
100 blog/categories/digestive-functors/atom.xml
@@ -4,7 +4,7 @@
<title><![CDATA[Category: digestive-functors | Norm 2782]]></title>
<link href="http://norm2782.github.com/blog/categories/digestive-functors/atom.xml" rel="self"/>
<link href="http://norm2782.github.com/"/>
- <updated>2012-01-01T23:42:22+01:00</updated>
+ <updated>2012-01-02T09:16:28+01:00</updated>
<id>http://norm2782.github.com/</id>
<author>
<name><![CDATA[Jurriën Stutterheim]]></name>
@@ -90,7 +90,8 @@ first some imports:</p>
<p>Since we are using Snap 0.7 at the moment of writing, we start by defining
out snaplet state type, generating some lenses using Template Haskell and
defining a handy type synonym for our handlers. We also want to use Heist,
-so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.</p>
+so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.
+And, since this is a snaplet, we need to define our snaplet initialiser.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -103,6 +104,18 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+<span class='line-number'>15</span>
+<span class='line-number'>16</span>
+<span class='line-number'>17</span>
+<span class='line-number'>18</span>
+<span class='line-number'>19</span>
+<span class='line-number'>20</span>
+<span class='line-number'>21</span>
+<span class='line-number'>22</span>
+<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">App</span>
</span><span class='line'> <span class="ow">=</span> <span class="kt">App</span>
</span><span class='line'> <span class="p">{</span> <span class="n">_heist</span> <span class="ow">::</span> <span class="kt">Snaplet</span> <span class="p">(</span><span class="kt">Heist</span> <span class="kt">App</span><span class="p">)</span>
@@ -113,7 +126,19 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="kr">type</span> <span class="kt">AppHandler</span> <span class="ow">=</span> <span class="kt">Handler</span> <span class="kt">App</span> <span class="kt">App</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="kr">instance</span> <span class="kt">HasHeist</span> <span class="kt">App</span> <span class="kr">where</span>
-</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span>
+</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="n">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
+</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
+</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
+</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="n">h</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
+</span><span class='line'><span class="nf">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
+</span><span class='line'><span class="nf">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
+</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
<p>Having written all the boilerplate, we can get started with defining our form.
@@ -216,7 +241,8 @@ comes from the email-validate library.</p>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
-<p>So far we have not seen anything new yet.</p>
+<p>Up to this point we have not seen anything new yet, so lets start with something a bit
+more interesting. For most of my Snap apps I use the following function to render a form:</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -227,17 +253,27 @@ comes from the email-validate library.</p>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
-</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">frm</span> <span class="ow">=</span>
+</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
+</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">mth</span> <span class="n">frm</span> <span class="ow">=</span>
</span><span class='line'> <span class="kr">let</span> <span class="p">(</span><span class="n">formHtml&#39;</span><span class="p">,</span> <span class="n">enctype</span><span class="p">)</span> <span class="ow">=</span> <span class="n">renderFormHtml</span> <span class="n">frm</span>
-</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="s">&quot;post&quot;</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="n">mth</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">action</span> <span class="n">act</span> <span class="o">$</span> <span class="n">formHtml&#39;</span> <span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="n">return</span> <span class="nb">()</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
+<p>It takes an <code>AttributeValue</code> containing the target of the form, an <code>AttributeValue</code> containing
+the HTTP request method and a form as produced by the <code>eitherSnapForm</code> function we will see
+below, resulting in a rendered form of type <code>Html</code>.</p>
+
+<p>Now for the request handler, which is where most of the action will take place. We want to
+make our lives easy, so we call in the help of the digestive-functors-snap library, which
+provides the <code>eitherSnapForm</code> function. This function can be applied to a digestive-functors
+form and a form name, after which it will use the Snap API to parse the request. Before
+continueing, lets have a look at some code:</p>
+
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
@@ -256,15 +292,31 @@ comes from the email-validate library.</p>
</span><span class='line'> <span class="kr">case</span> <span class="n">res</span> <span class="kr">of</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="kt">Left</span> <span class="n">form</span> <span class="o">-&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="kr">do</span>
-</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="n">form</span>
-</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;form&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;form&quot;</span>
+</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="s">&quot;post&quot;</span> <span class="n">form</span>
+</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;formElm&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;formTpl&quot;</span>
</span><span class='line'><span class="kt">Right</span> <span class="p">(</span><span class="kt">LoginData</span> <span class="n">e</span> <span class="n">p</span> <span class="n">r</span><span class="p">)</span> <span class="o">-&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="n">writeBS</span> <span class="s">&quot;Success!&quot;</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
-<p>Finally we define our initialiser, which sets up Heist and our routes.</p>
+<p>The result of <code>eitherSnapForm</code> is an <code>Either</code> value. When the form has not been submitted yet,
+or if a submitted form failed validation, the result will be a <code>Left</code> constructor containing
+a form of type <code>FormHtml (HtmlM a)</code>. When a form has been submitted and has succesfully passed
+validation, we will get a <code>Right</code> value containing the constructor applied in our form (in this
+case the <code>LoginData</code> constructor).</p>
+
+<p>Rendering the form is done when we get a <code>Left</code> result. As it turns out, it is almost trivially
+easy to render the form in Heist. To bind the form as a Heist splice, we first need to render it
+to an <code>Html</code> value using our <code>showForm</code> function. Since Heist cannot work with values of type
+<code>Html</code>, we have to convert the <code>Html</code> to something Heist does understand. Luckily, the xmlhtml
+library provides us with a function that does just that: <code>renderHtmlNodes :: Html -&gt; [Node]</code>.
+Heist loves a list of <code>Node</code>s, so all we need to do is <code>return</code> it to the <code>Splice</code> context so
+we can bind it as a splice to our template.</p>
+
+<p>The final piece of the puzzle is the template in which the form needs to be rendered. As you can
+see, rendering the form--including potential validation error messages--is done by adding nothing
+but a single element to the template.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -277,18 +329,28 @@ comes from the email-validate library.</p>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
-</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
-</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
-</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt">&lt;html&gt;</span>
+</span><span class='line'> <span class="nt">&lt;head&gt;&lt;/p&gt;</span>
</span><span class='line'>
-</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="n">h</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
-</span><span class='line'><span class="nf">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
-</span><span class='line'><span class="nf">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
-</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
+</span><span class='line'><span class="nt">&lt;pre&gt;&lt;code&gt;</span><span class="ni">&amp;lt;</span>title<span class="ni">&amp;gt;</span>Heist and digestive-functors playing nice<span class="ni">&amp;lt;</span>/title<span class="ni">&amp;gt;</span>
+</span><span class='line'><span class="nt">&lt;/code&gt;&lt;/pre&gt;</span>
</span><span class='line'>
-</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'><span class="nt">&lt;p&gt;</span> <span class="nt">&lt;/head&gt;</span>
+</span><span class='line'> <span class="nt">&lt;body&gt;&lt;/p&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="nt">&lt;pre&gt;&lt;code&gt;</span><span class="ni">&amp;lt;</span>form /<span class="ni">&amp;gt;</span>
+</span><span class='line'><span class="nt">&lt;/code&gt;&lt;/pre&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="nt">&lt;p&gt;</span> <span class="nt">&lt;/body&gt;</span>
+</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
+
+<p>With this, we have seen how to use digestive-functors and Heist together in a win-win scenario.
+On the one hand you mostly maintain your separation of concerns by using Heist for most of your
+HTML output, while on the other hand you can enjoy the great digestive-functors library as-is.</p>
]]></content>
</entry>
View
100 blog/categories/haskell/atom.xml
@@ -4,7 +4,7 @@
<title><![CDATA[Category: Haskell | Norm 2782]]></title>
<link href="http://norm2782.github.com/blog/categories/haskell/atom.xml" rel="self"/>
<link href="http://norm2782.github.com/"/>
- <updated>2012-01-01T23:42:22+01:00</updated>
+ <updated>2012-01-02T09:16:28+01:00</updated>
<id>http://norm2782.github.com/</id>
<author>
<name><![CDATA[Jurriën Stutterheim]]></name>
@@ -90,7 +90,8 @@ first some imports:</p>
<p>Since we are using Snap 0.7 at the moment of writing, we start by defining
out snaplet state type, generating some lenses using Template Haskell and
defining a handy type synonym for our handlers. We also want to use Heist,
-so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.</p>
+so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.
+And, since this is a snaplet, we need to define our snaplet initialiser.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -103,6 +104,18 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+<span class='line-number'>15</span>
+<span class='line-number'>16</span>
+<span class='line-number'>17</span>
+<span class='line-number'>18</span>
+<span class='line-number'>19</span>
+<span class='line-number'>20</span>
+<span class='line-number'>21</span>
+<span class='line-number'>22</span>
+<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">App</span>
</span><span class='line'> <span class="ow">=</span> <span class="kt">App</span>
</span><span class='line'> <span class="p">{</span> <span class="n">_heist</span> <span class="ow">::</span> <span class="kt">Snaplet</span> <span class="p">(</span><span class="kt">Heist</span> <span class="kt">App</span><span class="p">)</span>
@@ -113,7 +126,19 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="kr">type</span> <span class="kt">AppHandler</span> <span class="ow">=</span> <span class="kt">Handler</span> <span class="kt">App</span> <span class="kt">App</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="kr">instance</span> <span class="kt">HasHeist</span> <span class="kt">App</span> <span class="kr">where</span>
-</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span>
+</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="n">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
+</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
+</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
+</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="n">h</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
+</span><span class='line'><span class="nf">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
+</span><span class='line'><span class="nf">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
+</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
<p>Having written all the boilerplate, we can get started with defining our form.
@@ -216,7 +241,8 @@ comes from the email-validate library.</p>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
-<p>So far we have not seen anything new yet.</p>
+<p>Up to this point we have not seen anything new yet, so lets start with something a bit
+more interesting. For most of my Snap apps I use the following function to render a form:</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -227,17 +253,27 @@ comes from the email-validate library.</p>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
-</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">frm</span> <span class="ow">=</span>
+</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
+</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">mth</span> <span class="n">frm</span> <span class="ow">=</span>
</span><span class='line'> <span class="kr">let</span> <span class="p">(</span><span class="n">formHtml&#39;</span><span class="p">,</span> <span class="n">enctype</span><span class="p">)</span> <span class="ow">=</span> <span class="n">renderFormHtml</span> <span class="n">frm</span>
-</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="s">&quot;post&quot;</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="n">mth</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">action</span> <span class="n">act</span> <span class="o">$</span> <span class="n">formHtml&#39;</span> <span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="n">return</span> <span class="nb">()</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
+<p>It takes an <code>AttributeValue</code> containing the target of the form, an <code>AttributeValue</code> containing
+the HTTP request method and a form as produced by the <code>eitherSnapForm</code> function we will see
+below, resulting in a rendered form of type <code>Html</code>.</p>
+
+<p>Now for the request handler, which is where most of the action will take place. We want to
+make our lives easy, so we call in the help of the digestive-functors-snap library, which
+provides the <code>eitherSnapForm</code> function. This function can be applied to a digestive-functors
+form and a form name, after which it will use the Snap API to parse the request. Before
+continueing, lets have a look at some code:</p>
+
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
@@ -256,15 +292,31 @@ comes from the email-validate library.</p>
</span><span class='line'> <span class="kr">case</span> <span class="n">res</span> <span class="kr">of</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="kt">Left</span> <span class="n">form</span> <span class="o">-&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="kr">do</span>
-</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="n">form</span>
-</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;form&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;form&quot;</span>
+</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="s">&quot;post&quot;</span> <span class="n">form</span>
+</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;formElm&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;formTpl&quot;</span>
</span><span class='line'><span class="kt">Right</span> <span class="p">(</span><span class="kt">LoginData</span> <span class="n">e</span> <span class="n">p</span> <span class="n">r</span><span class="p">)</span> <span class="o">-&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="n">writeBS</span> <span class="s">&quot;Success!&quot;</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
-<p>Finally we define our initialiser, which sets up Heist and our routes.</p>
+<p>The result of <code>eitherSnapForm</code> is an <code>Either</code> value. When the form has not been submitted yet,
+or if a submitted form failed validation, the result will be a <code>Left</code> constructor containing
+a form of type <code>FormHtml (HtmlM a)</code>. When a form has been submitted and has succesfully passed
+validation, we will get a <code>Right</code> value containing the constructor applied in our form (in this
+case the <code>LoginData</code> constructor).</p>
+
+<p>Rendering the form is done when we get a <code>Left</code> result. As it turns out, it is almost trivially
+easy to render the form in Heist. To bind the form as a Heist splice, we first need to render it
+to an <code>Html</code> value using our <code>showForm</code> function. Since Heist cannot work with values of type
+<code>Html</code>, we have to convert the <code>Html</code> to something Heist does understand. Luckily, the xmlhtml
+library provides us with a function that does just that: <code>renderHtmlNodes :: Html -&gt; [Node]</code>.
+Heist loves a list of <code>Node</code>s, so all we need to do is <code>return</code> it to the <code>Splice</code> context so
+we can bind it as a splice to our template.</p>
+
+<p>The final piece of the puzzle is the template in which the form needs to be rendered. As you can
+see, rendering the form--including potential validation error messages--is done by adding nothing
+but a single element to the template.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -277,18 +329,28 @@ comes from the email-validate library.</p>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
-</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
-</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
-</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt">&lt;html&gt;</span>
+</span><span class='line'> <span class="nt">&lt;head&gt;&lt;/p&gt;</span>
</span><span class='line'>
-</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="n">h</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
-</span><span class='line'><span class="nf">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
-</span><span class='line'><span class="nf">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
-</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
+</span><span class='line'><span class="nt">&lt;pre&gt;&lt;code&gt;</span><span class="ni">&amp;lt;</span>title<span class="ni">&amp;gt;</span>Heist and digestive-functors playing nice<span class="ni">&amp;lt;</span>/title<span class="ni">&amp;gt;</span>
+</span><span class='line'><span class="nt">&lt;/code&gt;&lt;/pre&gt;</span>
</span><span class='line'>
-</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'><span class="nt">&lt;p&gt;</span> <span class="nt">&lt;/head&gt;</span>
+</span><span class='line'> <span class="nt">&lt;body&gt;&lt;/p&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="nt">&lt;pre&gt;&lt;code&gt;</span><span class="ni">&amp;lt;</span>form /<span class="ni">&amp;gt;</span>
+</span><span class='line'><span class="nt">&lt;/code&gt;&lt;/pre&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="nt">&lt;p&gt;</span> <span class="nt">&lt;/body&gt;</span>
+</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
+
+<p>With this, we have seen how to use digestive-functors and Heist together in a win-win scenario.
+On the one hand you mostly maintain your separation of concerns by using Heist for most of your
+HTML output, while on the other hand you can enjoy the great digestive-functors library as-is.</p>
]]></content>
</entry>
View
100 blog/categories/heist/atom.xml
@@ -4,7 +4,7 @@
<title><![CDATA[Category: Heist | Norm 2782]]></title>
<link href="http://norm2782.github.com/blog/categories/heist/atom.xml" rel="self"/>
<link href="http://norm2782.github.com/"/>
- <updated>2012-01-01T23:42:22+01:00</updated>
+ <updated>2012-01-02T09:16:28+01:00</updated>
<id>http://norm2782.github.com/</id>
<author>
<name><![CDATA[Jurriën Stutterheim]]></name>
@@ -90,7 +90,8 @@ first some imports:</p>
<p>Since we are using Snap 0.7 at the moment of writing, we start by defining
out snaplet state type, generating some lenses using Template Haskell and
defining a handy type synonym for our handlers. We also want to use Heist,
-so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.</p>
+so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.
+And, since this is a snaplet, we need to define our snaplet initialiser.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -103,6 +104,18 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+<span class='line-number'>15</span>
+<span class='line-number'>16</span>
+<span class='line-number'>17</span>
+<span class='line-number'>18</span>
+<span class='line-number'>19</span>
+<span class='line-number'>20</span>
+<span class='line-number'>21</span>
+<span class='line-number'>22</span>
+<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">App</span>
</span><span class='line'> <span class="ow">=</span> <span class="kt">App</span>
</span><span class='line'> <span class="p">{</span> <span class="n">_heist</span> <span class="ow">::</span> <span class="kt">Snaplet</span> <span class="p">(</span><span class="kt">Heist</span> <span class="kt">App</span><span class="p">)</span>
@@ -113,7 +126,19 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="kr">type</span> <span class="kt">AppHandler</span> <span class="ow">=</span> <span class="kt">Handler</span> <span class="kt">App</span> <span class="kt">App</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="kr">instance</span> <span class="kt">HasHeist</span> <span class="kt">App</span> <span class="kr">where</span>
-</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span>
+</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="n">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
+</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
+</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
+</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="n">h</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
+</span><span class='line'><span class="nf">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
+</span><span class='line'><span class="nf">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
+</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
<p>Having written all the boilerplate, we can get started with defining our form.
@@ -216,7 +241,8 @@ comes from the email-validate library.</p>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
-<p>So far we have not seen anything new yet.</p>
+<p>Up to this point we have not seen anything new yet, so lets start with something a bit
+more interesting. For most of my Snap apps I use the following function to render a form:</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -227,17 +253,27 @@ comes from the email-validate library.</p>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
-</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">frm</span> <span class="ow">=</span>
+</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
+</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">mth</span> <span class="n">frm</span> <span class="ow">=</span>
</span><span class='line'> <span class="kr">let</span> <span class="p">(</span><span class="n">formHtml&#39;</span><span class="p">,</span> <span class="n">enctype</span><span class="p">)</span> <span class="ow">=</span> <span class="n">renderFormHtml</span> <span class="n">frm</span>
-</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="s">&quot;post&quot;</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="n">mth</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">action</span> <span class="n">act</span> <span class="o">$</span> <span class="n">formHtml&#39;</span> <span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="n">return</span> <span class="nb">()</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
+<p>It takes an <code>AttributeValue</code> containing the target of the form, an <code>AttributeValue</code> containing
+the HTTP request method and a form as produced by the <code>eitherSnapForm</code> function we will see
+below, resulting in a rendered form of type <code>Html</code>.</p>
+
+<p>Now for the request handler, which is where most of the action will take place. We want to
+make our lives easy, so we call in the help of the digestive-functors-snap library, which
+provides the <code>eitherSnapForm</code> function. This function can be applied to a digestive-functors
+form and a form name, after which it will use the Snap API to parse the request. Before
+continueing, lets have a look at some code:</p>
+
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
@@ -256,15 +292,31 @@ comes from the email-validate library.</p>
</span><span class='line'> <span class="kr">case</span> <span class="n">res</span> <span class="kr">of</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="kt">Left</span> <span class="n">form</span> <span class="o">-&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="kr">do</span>
-</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="n">form</span>
-</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;form&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;form&quot;</span>
+</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="s">&quot;post&quot;</span> <span class="n">form</span>
+</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;formElm&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;formTpl&quot;</span>
</span><span class='line'><span class="kt">Right</span> <span class="p">(</span><span class="kt">LoginData</span> <span class="n">e</span> <span class="n">p</span> <span class="n">r</span><span class="p">)</span> <span class="o">-&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="n">writeBS</span> <span class="s">&quot;Success!&quot;</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
-<p>Finally we define our initialiser, which sets up Heist and our routes.</p>
+<p>The result of <code>eitherSnapForm</code> is an <code>Either</code> value. When the form has not been submitted yet,
+or if a submitted form failed validation, the result will be a <code>Left</code> constructor containing
+a form of type <code>FormHtml (HtmlM a)</code>. When a form has been submitted and has succesfully passed
+validation, we will get a <code>Right</code> value containing the constructor applied in our form (in this
+case the <code>LoginData</code> constructor).</p>
+
+<p>Rendering the form is done when we get a <code>Left</code> result. As it turns out, it is almost trivially
+easy to render the form in Heist. To bind the form as a Heist splice, we first need to render it
+to an <code>Html</code> value using our <code>showForm</code> function. Since Heist cannot work with values of type
+<code>Html</code>, we have to convert the <code>Html</code> to something Heist does understand. Luckily, the xmlhtml
+library provides us with a function that does just that: <code>renderHtmlNodes :: Html -&gt; [Node]</code>.
+Heist loves a list of <code>Node</code>s, so all we need to do is <code>return</code> it to the <code>Splice</code> context so
+we can bind it as a splice to our template.</p>
+
+<p>The final piece of the puzzle is the template in which the form needs to be rendered. As you can
+see, rendering the form--including potential validation error messages--is done by adding nothing
+but a single element to the template.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -277,18 +329,28 @@ comes from the email-validate library.</p>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
-</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
-</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
-</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt">&lt;html&gt;</span>
+</span><span class='line'> <span class="nt">&lt;head&gt;&lt;/p&gt;</span>
</span><span class='line'>
-</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="n">h</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
-</span><span class='line'><span class="nf">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
-</span><span class='line'><span class="nf">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
-</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
+</span><span class='line'><span class="nt">&lt;pre&gt;&lt;code&gt;</span><span class="ni">&amp;lt;</span>title<span class="ni">&amp;gt;</span>Heist and digestive-functors playing nice<span class="ni">&amp;lt;</span>/title<span class="ni">&amp;gt;</span>
+</span><span class='line'><span class="nt">&lt;/code&gt;&lt;/pre&gt;</span>
</span><span class='line'>
-</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'><span class="nt">&lt;p&gt;</span> <span class="nt">&lt;/head&gt;</span>
+</span><span class='line'> <span class="nt">&lt;body&gt;&lt;/p&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="nt">&lt;pre&gt;&lt;code&gt;</span><span class="ni">&amp;lt;</span>form /<span class="ni">&amp;gt;</span>
+</span><span class='line'><span class="nt">&lt;/code&gt;&lt;/pre&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="nt">&lt;p&gt;</span> <span class="nt">&lt;/body&gt;</span>
+</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
+
+<p>With this, we have seen how to use digestive-functors and Heist together in a win-win scenario.
+On the one hand you mostly maintain your separation of concerns by using Heist for most of your
+HTML output, while on the other hand you can enjoy the great digestive-functors library as-is.</p>
]]></content>
</entry>
View
100 blog/categories/snap/atom.xml
@@ -4,7 +4,7 @@
<title><![CDATA[Category: Snap | Norm 2782]]></title>
<link href="http://norm2782.github.com/blog/categories/snap/atom.xml" rel="self"/>
<link href="http://norm2782.github.com/"/>
- <updated>2012-01-01T23:42:22+01:00</updated>
+ <updated>2012-01-02T09:16:28+01:00</updated>
<id>http://norm2782.github.com/</id>
<author>
<name><![CDATA[Jurriën Stutterheim]]></name>
@@ -90,7 +90,8 @@ first some imports:</p>
<p>Since we are using Snap 0.7 at the moment of writing, we start by defining
out snaplet state type, generating some lenses using Template Haskell and
defining a handy type synonym for our handlers. We also want to use Heist,
-so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.</p>
+so we need to define a <code>HasHeist</code> instance for our <code>App</code> type as well.
+And, since this is a snaplet, we need to define our snaplet initialiser.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -103,6 +104,18 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+<span class='line-number'>15</span>
+<span class='line-number'>16</span>
+<span class='line-number'>17</span>
+<span class='line-number'>18</span>
+<span class='line-number'>19</span>
+<span class='line-number'>20</span>
+<span class='line-number'>21</span>
+<span class='line-number'>22</span>
+<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">App</span>
</span><span class='line'> <span class="ow">=</span> <span class="kt">App</span>
</span><span class='line'> <span class="p">{</span> <span class="n">_heist</span> <span class="ow">::</span> <span class="kt">Snaplet</span> <span class="p">(</span><span class="kt">Heist</span> <span class="kt">App</span><span class="p">)</span>
@@ -113,7 +126,19 @@ so we need to define a <code>HasHeist</code> instance for our <code>App</code> t
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="kr">type</span> <span class="kt">AppHandler</span> <span class="ow">=</span> <span class="kt">Handler</span> <span class="kt">App</span> <span class="kt">App</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="kr">instance</span> <span class="kt">HasHeist</span> <span class="kt">App</span> <span class="kr">where</span>
-</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span>
+</span><span class='line'> <span class="n">heistLens</span> <span class="ow">=</span> <span class="n">subSnaplet</span> <span class="n">heist</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="n">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
+</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
+</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
+</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="n">h</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
+</span><span class='line'><span class="nf">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
+</span><span class='line'><span class="nf">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
+</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
<p>Having written all the boilerplate, we can get started with defining our form.
@@ -216,7 +241,8 @@ comes from the email-validate library.</p>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
-<p>So far we have not seen anything new yet.</p>
+<p>Up to this point we have not seen anything new yet, so lets start with something a bit
+more interesting. For most of my Snap apps I use the following function to render a form:</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -227,17 +253,27 @@ comes from the email-validate library.</p>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
-</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">frm</span> <span class="ow">=</span>
+</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">showForm</span> <span class="ow">::</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">AttributeValue</span> <span class="ow">-&gt;</span> <span class="kt">FormHtml</span> <span class="p">(</span><span class="kt">HtmlM</span> <span class="n">a</span><span class="p">)</span> <span class="ow">-&gt;</span> <span class="kt">Html</span>
+</span><span class='line'><span class="nf">showForm</span> <span class="n">act</span> <span class="n">mth</span> <span class="n">frm</span> <span class="ow">=</span>
</span><span class='line'> <span class="kr">let</span> <span class="p">(</span><span class="n">formHtml&#39;</span><span class="p">,</span> <span class="n">enctype</span><span class="p">)</span> <span class="ow">=</span> <span class="n">renderFormHtml</span> <span class="n">frm</span>
-</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="s">&quot;post&quot;</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'> <span class="kr">in</span> <span class="kt">H</span><span class="o">.</span><span class="n">form</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">enctype</span> <span class="p">(</span><span class="kt">H</span><span class="o">.</span><span class="n">toValue</span> <span class="o">$</span> <span class="n">show</span> <span class="n">enctype</span><span class="p">)</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">method</span> <span class="n">mth</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span> <span class="o">!</span> <span class="kt">A</span><span class="o">.</span><span class="n">action</span> <span class="n">act</span> <span class="o">$</span> <span class="n">formHtml&#39;</span> <span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span><span class="o">&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="n">return</span> <span class="nb">()</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
+<p>It takes an <code>AttributeValue</code> containing the target of the form, an <code>AttributeValue</code> containing
+the HTTP request method and a form as produced by the <code>eitherSnapForm</code> function we will see
+below, resulting in a rendered form of type <code>Html</code>.</p>
+
+<p>Now for the request handler, which is where most of the action will take place. We want to
+make our lives easy, so we call in the help of the digestive-functors-snap library, which
+provides the <code>eitherSnapForm</code> function. This function can be applied to a digestive-functors
+form and a form name, after which it will use the Snap API to parse the request. Before
+continueing, lets have a look at some code:</p>
+
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
@@ -256,15 +292,31 @@ comes from the email-validate library.</p>
</span><span class='line'> <span class="kr">case</span> <span class="n">res</span> <span class="kr">of</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="kt">Left</span> <span class="n">form</span> <span class="o">-&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="kr">do</span>
-</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="n">form</span>
-</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;form&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;form&quot;</span>
+</span><span class='line'> <span class="kr">let</span> <span class="n">nodes</span> <span class="ow">=</span> <span class="n">renderHtmlNodes</span> <span class="o">$</span> <span class="n">showForm</span> <span class="s">&quot;/&quot;</span> <span class="s">&quot;post&quot;</span> <span class="n">form</span>
+</span><span class='line'> <span class="n">heistLocal</span> <span class="p">(</span><span class="n">bindSplice</span> <span class="s">&quot;formElm&quot;</span> <span class="p">(</span><span class="n">return</span> <span class="n">nodes</span><span class="p">))</span> <span class="o">$</span> <span class="n">render</span> <span class="s">&quot;formTpl&quot;</span>
</span><span class='line'><span class="kt">Right</span> <span class="p">(</span><span class="kt">LoginData</span> <span class="n">e</span> <span class="n">p</span> <span class="n">r</span><span class="p">)</span> <span class="o">-&amp;</span><span class="n">gt</span><span class="p">;</span> <span class="n">writeBS</span> <span class="s">&quot;Success!&quot;</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
-<p>Finally we define our initialiser, which sets up Heist and our routes.</p>
+<p>The result of <code>eitherSnapForm</code> is an <code>Either</code> value. When the form has not been submitted yet,
+or if a submitted form failed validation, the result will be a <code>Left</code> constructor containing
+a form of type <code>FormHtml (HtmlM a)</code>. When a form has been submitted and has succesfully passed
+validation, we will get a <code>Right</code> value containing the constructor applied in our form (in this
+case the <code>LoginData</code> constructor).</p>
+
+<p>Rendering the form is done when we get a <code>Left</code> result. As it turns out, it is almost trivially
+easy to render the form in Heist. To bind the form as a Heist splice, we first need to render it
+to an <code>Html</code> value using our <code>showForm</code> function. Since Heist cannot work with values of type
+<code>Html</code>, we have to convert the <code>Html</code> to something Heist does understand. Luckily, the xmlhtml
+library provides us with a function that does just that: <code>renderHtmlNodes :: Html -&gt; [Node]</code>.
+Heist loves a list of <code>Node</code>s, so all we need to do is <code>return</code> it to the <code>Splice</code> context so
+we can bind it as a splice to our template.</p>
+
+<p>The final piece of the puzzle is the template in which the form needs to be rendered. As you can
+see, rendering the form--including potential validation error messages--is done by adding nothing
+but a single element to the template.</p>
<p><div class='bogus-wrapper'><notextile><figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
@@ -277,18 +329,28 @@ comes from the email-validate library.</p>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
-</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">app</span> <span class="ow">::</span> <span class="kt">SnapletInit</span> <span class="kt">App</span> <span class="kt">App</span>
-</span><span class='line'><span class="nf">app</span> <span class="ow">=</span> <span class="n">makeSnaplet</span> <span class="s">&quot;hdf&quot;</span>
-</span><span class='line'> <span class="s">&quot;An example of digestive-functors and Heist playing nicely together.&quot;</span>
-</span><span class='line'> <span class="kt">Nothing</span> <span class="o">$</span> <span class="kr">do</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
+<span class='line-number'>12</span>
+<span class='line-number'>13</span>
+<span class='line-number'>14</span>
+</pre></td><td class='code'><pre><code class='xml'><span class='line'><span class="nt">&lt;html&gt;</span>
+</span><span class='line'> <span class="nt">&lt;head&gt;&lt;/p&gt;</span>
</span><span class='line'>
-</span><span class='line'><span class="o">&lt;</span><span class="n">pre</span><span class="o">&gt;&lt;</span><span class="n">code</span><span class="o">&gt;</span><span class="n">h</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span><span class="o">-</span> <span class="n">nestSnaplet</span> <span class="s">&quot;heist&quot;</span> <span class="n">heist</span> <span class="o">$</span> <span class="n">heistInit</span> <span class="s">&quot;resources/templates&quot;</span>
-</span><span class='line'><span class="nf">addRoutes</span> <span class="p">[</span> <span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">,</span> <span class="n">formHandler</span><span class="p">)</span> <span class="p">]</span>
-</span><span class='line'><span class="nf">return</span> <span class="o">$</span> <span class="kt">App</span> <span class="n">h</span>
-</span><span class='line'><span class="o">&lt;/</span><span class="n">code</span><span class="o">&gt;&lt;/</span><span class="n">pre</span><span class="o">&gt;</span>
+</span><span class='line'><span class="nt">&lt;pre&gt;&lt;code&gt;</span><span class="ni">&amp;lt;</span>title<span class="ni">&amp;gt;</span>Heist and digestive-functors playing nice<span class="ni">&amp;lt;</span>/title<span class="ni">&amp;gt;</span>
+</span><span class='line'><span class="nt">&lt;/code&gt;&lt;/pre&gt;</span>
</span><span class='line'>
-</span><span class='line'><span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span>
+</span><span class='line'><span class="nt">&lt;p&gt;</span> <span class="nt">&lt;/head&gt;</span>
+</span><span class='line'> <span class="nt">&lt;body&gt;&lt;/p&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="nt">&lt;pre&gt;&lt;code&gt;</span><span class="ni">&amp;lt;</span>form /<span class="ni">&amp;gt;</span>
+</span><span class='line'><span class="nt">&lt;/code&gt;&lt;/pre&gt;</span>
+</span><span class='line'>
+</span><span class='line'><span class="nt">&lt;p&gt;</span> <span class="nt">&lt;/body&gt;</span>
+</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div></p>
+
+<p>With this, we have seen how to use digestive-functors and Heist together in a win-win scenario.
+On the one hand you mostly maintain your separation of concerns by using Heist for most of your
+HTML output, while on the other hand you can enjoy the great digestive-functors library as-is.</p>
]]></content>
</entry>
View
6 sitemap.xml
@@ -2,14 +2,14 @@
<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>
<url>
<loc>http://norm2782.github.com/blog/2012/01/01/using-digestive-functors-with-heist/</loc>
- <lastmod>2012-01-01T23:41:23+01:00</lastmod>
+ <lastmod>2012-01-02T09:16:12+01:00</lastmod>
</url>
<url>
<loc>http://norm2782.github.com/blog/archives/</loc>
- <lastmod>2012-01-01T23:41:23+01:00</lastmod>
+ <lastmod>2012-01-02T09:16:12+01:00</lastmod>
</url>
<url>
<loc>http://norm2782.github.com/</loc>
- <lastmod>2012-01-01T23:41:23+01:00</lastmod>
+ <lastmod>2012-01-02T09:16:12+01:00</lastmod>
</url>
</urlset>

0 comments on commit fd47896

Please sign in to comment.