{
    "componentChunkName": "component---src-templates-blog-post-tsx",
    "path": "/blog/2016-01-22-functional-templating-in-ember/",
    "result": {"data":{"blogPost":{"title":"Functional Templating in Ember","slug":"/blog/2016-01-22-functional-templating-in-ember/","authorNodes":[{"name":"Charles Lowell","slug":"/people/charles-lowell/"}],"markdown":{"html":"<!-- <% content_for :head do  %>\n  <%= ember_stylesheet_link_tags \"2016-01-22-functional-templating-in-ember\" %>\n<% end %>\n<% content_for :foot do  %>\n  <%= ember_javascript_tags \"2016-01-22-functional-templating-in-ember\" %>\n<% end %> -->\n<blockquote>\n<p>TL;DR --  Avoid using \"magically bound\" internal component properties in your templates at all costs. Instead be explicit about only passing values around through actions and block params. This will engender a new level of breeziness to your UI.</p>\n</blockquote>\n<p>Implementing a file upload in your web application is just the worst, am I right?</p>\n<p>I mean, once you get your server set up, it’s on to choosing which\noff-the-shelf JavaScript Hairball ™ widget you’re going to use to\nactually walk the user through the upload process. And no matter which\none you choose it never seems to fit quite right over the long-term\ndoes it? Let’s forget for a moment that they usually come with their\nown markup and style which is either difficult or impossible to\nreplace with your own. As irritating as that is though, it’s something\nthat we can perhaps live with, or at least wrestle into a submission\nhold. But where one-size-fits-all solutions really start to fall down\nis when you want to customize the actual file upload workflow. And\neven the simplest file upload workflows are involved aren’t they?</p>\n<p>There’s not just the transfer of the bytes. First, there is the file selection process. If the file is an image, at the very least, you may want to show users a preview of that image. In some cases, you want to initiate the file upload immediately and without further action on the part of the user, but then again in others, you may need to stop and perform some intermediate work such as image resizing and cropping, and only then begin the transfer of the file to the server. If you’re uploading other MIME types like spreadsheets, there might be other intermediate preview-modify-and-confirm workflows altogether.</p>\n<p>And so if you’re like me up until about a year ago, your experience with it was a constant and simmering frustration of whacking the square peg of an upload widget into the round hole of your application’s unique workflow, and caulking around the inevitable gouges and gaps with healthy dollops of JavaScript. In a word: Exhausting. Exhausting to stand up in the first place, and exhausting to maintain over the long haul.</p>\n<p>So what would you say if I told you that with Ember components that are available on NPM right now you could build your own image upload widget, complete with preview and progress bars using nothing but about fifteen lines of Handlebars? Furthermore, what if I told you that you had complete freedom to use whatever markup and styling you saw fit, and beyond that, you could do it without a single line of JavaScript?</p>\n<p>With the technique I’m going to outline, you’ll see that these are not outlandish claims, but rather the happy, daily reality of working with what I like to call <em>functional templating</em>. What makes a template functional? It's simple really. All it means is that the only way a name becomes bound to a value is via function application. That is to say, as a block parameter, or via a <code class=\"language-text\">mut</code> action.</p>\n<p>A key construct underlying functional templating is the component that has little or no visual presence in terms of markup, but whose sole purpose is to manage a single piece of state and present it to a template.</p>\n<p>I'm going to be using three functional components today to build our file uploader, the first of which is the <em>file chooser</em>. The file chooser is a component whose sole responsibility is to capture a <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/FileList\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">FileList</a> object and present it to the templating context. What happens to the files is not the concern of the file chooser however. That can be left up to other components later on down the road.</p>\n<p>Let's see it in action! Click the \"choose files\" button below to select any number of files and have their metadata displayed in the area below the button.</p>\n<div data-component=\"demo-pane\" data-attrs='{\"name\": \"file-chooser-only\", \"title\": \"Selecting Files\"}'></div>\n<p>In this example, the <code class=\"language-text\">x-file-input</code>'s action emits a <code class=\"language-text\">FileList</code> object every time that the user selects a group of files. By binding <code class=\"language-text\">(action (mut files))</code> to that action, we can inject that <code class=\"language-text\">FileList</code> into the handlebars scope, so that now it's available as a templating variable just the same as any other. Once it's in scope, the <code class=\"language-text\">{{each}}</code> iterates over the files and lists its metadata.</p>\n<p>Notice how the <code class=\"language-text\">x-file-input</code> component in our chooser places very little restriction on the markup that activates the dialog. In this case we chose a button, but we could have made it a link, or a label, or picture of a cat.</p>\n<style type=\"text/css\">\n\n .demo-pane {\n   margin-bottom: 2em;\n }\n\n figure {\n   display: inline-block;\n   margin-bottom: 1em;\n }\n\n figure img {\n   border: 1px solid #ddd;\n   border-radius: 3px;\n   background-color: rgb(248,248,248);\n   padding: 15px;\n   margin: 0 !important;\n   border: 1px solid rgb(249,249,249);\n   box-shadow: #ccc 1px 1px 10px;\n }\n figcaption {\n   padding: 10px 10px 10px 0;\n   font-size: 90%;\n   font-style: italic;\n   border-bottom-left-radius: 2px;\n   border-bottom-right-radius: 2px;\n }\n</style>\n<figure alt=\"picture of data flow from file input to template scope\">\n  <img style=\"background-color: rgb(248,248,248); padding 15px; border 1px solid #ddd;\" src=\"/img/2016-01-22-functional-templating-in-ember_file-chooser-only.svg\">\n  <figcaption>Fig 1: Data flows from file input into template scope</figcaption>\n</figure>\n<p>Selecting the files and viewing all the metadata about them is great, but in our case, where we're headed is a full featured file upload complete with preview. In order to get there, we'll use two more functional components.</p>\n<h3 id=\"preview-all-the-images\" style=\"position:relative;\"><a href=\"#preview-all-the-images\" aria-label=\"preview all the images permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Preview All the Images</h3>\n<p>In order to preview our image, we'll need to display it in the browser. Luckily, the <a href=\"https://w3c.github.io/FileAPI/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">File API</a> provides a <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">createObjectURL</a> method to help you do just that. Call it with a <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Blob</a> object, and it hands you back a url that you can use for links, images, or any other place a url might be prone to go. When you're done with it, you call <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">revokeObjectURL</a> so that the browser knows it doesn't need to hang onto that Blob anymore.</p>\n<p>And in order to present this url to our templating context? Yep, you guessed it. We'll use a functional component. We've written an <code class=\"language-text\">object-url</code> component which is responsible for managing an object url. It creates the url out of its <code class=\"language-text\">blob</code> attribute, and then revokes that url when either it receives a new <code class=\"language-text\">blob</code> attribute, or the component itself passes out of scope. Let's see it in action.</p>\n<blockquote>\n<p>Note: In this example, the file input has been restricted to only image mime types by setting the <code class=\"language-text\">accept</code> attribute.</p>\n</blockquote>\n<div data-component=\"demo-pane\" data-attrs='{\"name\": \"choose-files-with-preview\", \"title\": \"Choose Images With Preview\"}'></div>\n<p>All we do is allow the <code class=\"language-text\">file</code> attribute to flow right into the <code class=\"language-text\">object-url</code> component which yields the url we need into the template to make the image preview.</p>\n<p>Again, <code class=\"language-text\">object-url</code> has no markup of its own. Instead, its only job is to yield the model that makes the file preview markup possible. In this case, we bind the <code class=\"language-text\">url</code> value yielded by the <code class=\"language-text\">x-object-url</code> to the <code class=\"language-text\">background-image</code> property of a div and we're done.</p>\n<figure alt=\"file value is converted into a url\">\n  <img src=\"/img/2016-01-22-functional-templating-in-ember_choose-files-with-preview.svg\">\n  <figcaption>Fig 2: object-url :: Blob -&gt; String</figcaption>\n</figure>\n<p>Finally, we arrive at our destination: the actual upload. To do this, we use a functional component that executes a real life <a href=\"https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">XMLHttpRequest</a>!</p>\n<p>This might seem totally nuts at first, but mostly because we’ve been trained over the years to think that a custom ajax request has  always got to feel “heavy”. It turns out though that your plain vanilla, garden variety XHR is actually a well defined state machine, and as such, it maps pretty neatly onto a functional component.</p>\n<p>We'll just let the file object flow into an <code class=\"language-text\">x-xml-http-request</code> component just like it did the <code class=\"language-text\">x-object-url</code></p>\n<figure alt=\"file object flows into x-xml-http-request\">\n  <img src=\"/img/2016-01-22-functional-templating-in-ember_full-demo.svg\">\n  <figcaption>Fig 3: x-xml-http-request :: File -&gt; XHR </figcaption>\n</figure>\n<p>Again, the <code class=\"language-text\">x-xml-http-request</code> has absolutely no markup. Its only job is to continually yield a value into the template that represents the most up-to-date status of the request as it runs. Because of this, we can use it to very quickly model a progress bar! The only thing we need to do is leverage the <code class=\"language-text\">xhr.upload.percentage</code> property within the colorstops of a <code class=\"language-text\">linear-gradient</code>.</p>\n<blockquote>\n<p><em>Heads Up!</em> The following demo will actually upload images to <a href=\"http://posttestserver.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">posttestserver.com</a> which is a <em>real</em> server on the <em>real</em> internet.  Even though it’s  just a bit bucket that periodically wipes all of its contents, you should still <em>never</em> upload anything sensitive to it.</p>\n</blockquote>\n<div data-component=\"demo-pane\" data-attrs='{\"name\": \"full-demo\", \"title\": \"Image Upload With Preview\"}'></div>\n<p>And there you have it. A fairly decent file upload widget in about 15 lines of handlebars. It's worth noting though, that if you don't like the way I've done it here, you have a free hand to change the markup and workflow to suit your liking since the components I used don't prescribe any of it.</p>\n<h3 id=\"dropping-the-f-bomb\" style=\"position:relative;\"><a href=\"#dropping-the-f-bomb\" aria-label=\"dropping the f bomb permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Dropping the F-Bomb</h3>\n<p>These demos were nearly trivial to put together because of the composability afforded by shifting to a more functional style. Values never just magically appear from some unknown location that could be inside your controller or your component. Instead, as in a functional language, variable names like <code class=\"language-text\">xhr</code> and <code class=\"language-text\">url</code> are only ever introduced as the formal parameters of a function. Because each component only interacts with its environment via its inputs and its outputs, it means that they can freely click together output-to-input; in as many ways as you can think of.</p>\n<p>The first time this technique really came together for me it felt impossibly light-weight. It felt like I must be missing something. Could it really be that easy to upload a file? Could I really style it any way that I wanted? Did I really have control over every aspect of the entire workflow from start to finish? And could I really do all of that while providing little or no custom JavaScript? The answer to all those questions turned out to be yes, and the resulting feeling was spectacular.</p>\n<hr/>\n<p>I’m Charles Lowell (<a href=\"https://twitter.com/cowboyd\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@cowboyd</a> on twitter), and I build UI for a living at <a href=\"https://frontside.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">The Frontside</a>. If you enjoyed this, I’d love to hear from you.</p>\n<p>Also, If you'd like to work with our team doing stuff like this, then please <a href=\"mailto:cowboyd@frontside.com\">get in touch</a>. We're hiring.</p>","frontmatter":{"date":"January 22, 2016","description":"See how easy it is to build a fully formed image upload widget complete with preview and progress bars when you apply functional programming techniques to your handlebars templates","tags":["ember","javascript"],"img":{"childImageSharp":{"fixed":{"src":"/static/dd57d22b676f75ef5a4e78895f742818/fad57/2016-01-22-functional-templating-in-ember_lisp-all.png"}}}}}}},"pageContext":{"id":"4bab4526-2a49-59aa-9f87-243861a7594c"}},
    "staticQueryHashes": ["1241260443"]}